|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: File: uslDescriptors.c
27:
28: Contains: xxx put contents here xxx
29:
30: Version: xxx put version here xxx
31:
32: Copyright: � 1998 by Apple Computer, Inc., all rights reserved.
33:
34: File Ownership:
35:
36: DRI: xxx put dri here xxx
37:
38: Other Contact: xxx put other contact here xxx
39:
40: Technology: xxx put technology here xxx
41:
42: Writers:
43:
44: (BG) Bill Galcher
45: (DF) David Ferguson
46: (BT) Barry Twycross
47:
48: Change History (most recent first):
49:
50: <USB39> 10/29/98 BT Close old configurations on reset or reconfiguration.
51: <USB38> 10/26/98 BT fix not finding interface
52: <USB37> 10/12/98 BT Add power qualification to find next interface
53: <USB36> 10/6/98 BT Fix Find next assoc desc with endpoint. Fix usage of getDev in
54: various places
55: <USB35> 9/17/98 BT 1.1 rules for captive devices.
56: <USB34> 8/25/98 BT Isoc name changes
57: <USB33> 8/24/98 BT Isoc param block definition
58: <USB32> 8/18/98 BT Fix small config descriptor error again
59: <USB31> 7/9/98 BT Fix previous fixes. Do not call back to dead device
60: <USB30> 7/9/98 BT Clean up after delete device and config clash.
61: <USB29> 7/8/98 BT Make findconfigdescriptor more paranoid.
62: <USB28> 7/2/98 BT Fix new interface ref to not accept interface ref
63: <USB27> 7/2/98 BT Fix hang if associated descriptor does not exist.
64: <USB26> 6/29/98 BT Fix zeroing paramblock fields after callback in FindNextPipe.
65: <USB25> 6/24/98 BT Fix config interface to open all pipes properly.
66: <USB24> 6/22/98 BT Add Alt interface to configure interface
67: <USB23> 6/18/98 BG Use the correct notation for including <Errors.h> and
68: <DriverServices.h>. I know, this is a nit.
69: <USB22> 6/9/98 BT Find next pipe returns max packert size
70: <USB21> 5/21/98 BT Note dependancy on dev req in open device. Make config work with
71: more than one descriptor
72: <USB20> 5/20/98 BT FIx find with interface alt
73: <USB19> 5/20/98 BT Fix alt usage in interface functions
74: <USB18> 5/20/98 BT Make this top of trunk, (17a2, V2 param b lock stuff)
75: <USB17> 5/18/98 DF Get config descriptor actually takes notice of index.
76: <USB16> 5/18/98 DF Remove nested comment warning
77: <USB15> 5/17/98 BT Add config stuff
78: <USB14> 5/5/98 BT Change name to ...immediate
79: <USB13> 4/16/98 BT Add include of USBpriv
80: <USB12> 4/9/98 BT Use USB.h
81: <11> 4/8/98 BT Move error codes
82: <10> 4/8/98 BT More error checking
83: <9> 4/6/98 BT Change w names
84: <8> 4/6/98 BT Change param block names.
85: <7> 4/2/98 BT Add grabbing all config descriptors
86: <6> 3/19/98 BT Get endpoint descriptor returns max packet size with right byte
87: ordering.
88: <5> 3/9/98 BT Eliminate one set of redundant enums
89: <4> 3/5/98 BT Add interrupt pipe
90: <3> 2/23/98 BT Fix swapped values
91: <2> 2/4/98 BT Cope with multiple configs
92: <1> 1/29/98 BT first checked in
93: */
94:
95:
96: #include "../USB.h"
97: #include "../USBpriv.h"
98:
99: #include "uslpriv.h"
100: //#include <Errors.h>
101: #include "../driverservices.h"
102:
103:
104: //enum{
105: // kUSLClientUser = 0,
106: // kUSLClientEndPoint
107:
108: // };
109: static Boolean immediateError(OSStatus err)
110: {
111: return((err != kUSBPending) && (err != noErr) );
112: }
113: static Boolean checkZeroBuffer(USBPB *pb)
114: {
115: return( (pb->usbBuffer != 0) || (pb->usbReqCount != 0) || (pb->usbActCount != 0) );
116: }
117:
118: /* These allow USL functions to have an internal stage counter. */
119: /* This drives internal state machines. */
120:
121: /* In this incarnation some bits in the flags long word are */
122: /* hijacked for this. If you wanted to revise the PB, an */
123: /* internal field could be added to do this. See uslPriv.h */
124: /* abuse of flags */
125:
126: static void uslClearInternalStage(USBPB *pb)
127: {
128: pb->usbFlags &= ~kUSLStageMask;
129: }
130:
131: static int uslFindInternalStageAndIncriment(USBPB *pb)
132: {
133: int stage;
134: stage = (pb->usbFlags & kUSLStageMask) >>kUSLStageShift;
135: stage++;
136: pb->usbFlags = (pb->usbFlags & ~kUSLStageMask) | stage << kUSLStageShift;
137: return(stage);
138: }
139:
140: static void uslCompleteInternalStages(USBPB *pb)
141: {
142: usbDevice *dev;
143:
144: /* make sure we never hose up a device by leaving it locked */
145: dev = getDevicePtr(pb->usbReference);
146: if( (dev != nil) && (dev->configLock != 0) )
147: {
148: dev->configLock = 0;
149: }
150:
151: uslClearInternalStage(pb);
152: pb->usbCompletion = (void *)pb->reserved2;
153: (*pb->usbCompletion)(pb);
154: }
155:
156: static void uslInitialiseInternalStages(USBPB *pb, void (*fn)(USBPB *pb))
157: {
158: uslClearInternalStage(pb);
159: pb->reserved2 = (UInt32) pb->usbCompletion; /* Save users handler */
160: pb->usbCompletion = fn; /* use our handler */
161: pb->usbStatus = noErr; // so cache conf desc doesn't crapout to start.
162: (*fn)(pb);
163: }
164:
165:
166: static SInt32 subtractAddress(void *a1, void *a2)
167: {
168: /* Use this to get signed addess compares. */
169: /* you get large pos instead of neg using UInts */
170: return((SInt32)a1 - (SInt32)a2);
171:
172: }
173:
174: static void uslSetInternalStage(USBPB *pb, int stage)
175: {
176: pb->usbFlags = (pb->usbFlags & ~kUSLStageMask) | stage << kUSLStageShift;
177: }
178:
179: static void nextInternalStage(USBPB *pb)
180: {
181: int stage;
182: stage = (pb->usbFlags & kUSLStageMask) >>kUSLStageShift;
183: stage ++;
184: pb->usbFlags = (pb->usbFlags & ~kUSLStageMask) | stage << kUSLStageShift;
185: }
186: #if 0
187:
188: static void uslMoveStageAlong(USBPB *pb, int n)
189: {
190: int stage;
191: stage = (pb->usbFlags & kUSLStageMask) >>kUSLStageShift;
192: stage += n;
193: pb->usbFlags = (pb->usbFlags & ~kUSLStageMask) | stage << kUSLStageShift;
194: }
195: #endif
196:
197: static OSStatus uslReadConfigurationDescriptor(USBPB *pb)
198: {
199:
200: // --> usbReference Device
201: // --> usb.cntl.WValue Configuration value
202: // --> usbBuffer Configuration Descriptor Structure
203: // --> usbReqCount size of descriptor
204: // <-- usbActCount size of descriptor returned
205:
206: pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBIn, kUSBStandard, kUSBDevice);
207: pb->usb.cntl.BRequest = kUSBRqGetDescriptor;
208:
209: pb->usb.cntl.WValue = (kUSBConfDesc << 8) + (pb->usb.cntl.WValue & 0xff);
210: pb->usb.cntl.WIndex = 0;
211:
212: return(uslDeviceRequest(pb));
213: }
214:
215: static usbDevice *getDev(USBPB *pb)
216: {
217: usbDevice *dev;
218: dev = getDevicePtr(pb->usbReference);
219: if(dev == nil)
220: {
221: pb->usbStatus = kUSBUnknownDeviceErr;
222: (*pb->usbCompletion)(pb);
223: }
224: return(dev);
225: }
226:
227: /* xxxx This needs to be redone in terms or cache config descr */
228: static void getFulConfHandler(USBPB *pb)
229: {
230: int stage;
231:
232: // --> usbReference Device
233: // --> usb.cntl.WValue Configuration number
234: // <-- usbBuffer Configuration Descriptor Structure
235: // usbReqCount undefined
236: // <-- usbActCount size of descriptor returned
237:
238:
239: usbDevice *dev;
240:
241: if(pb->usbStatus != noErr)
242: {
243: uslCompleteInternalStages(pb);
244: return;
245: }
246:
247: stage = uslFindInternalStageAndIncriment(pb);
248:
249: do{switch(stage)
250: {
251: case 1:
252: dev = getDev(pb);
253: if(dev == nil) break;
254:
255: /* use dev scratch to get the root config descritor */
256: pb->usbReqCount = sizeof(configHeader);
257: pb->usbBuffer = &dev->configScratch;
258:
259: /* Get the descriptor */
260: if(immediateError(uslReadConfigurationDescriptor(pb)))
261: {
262: uslCompleteInternalStages(pb);
263: }
264: break;
265:
266: case 2:
267: /* How long is full descritptor */
268: pb->usbReqCount = USBToHostWord(((configHeader *)pb->usbBuffer)->totalLen);
269:
270: /* Allocate the full descriptor */
271: if(immediateError(uslAllocMem(pb)))
272: {
273: uslCompleteInternalStages(pb);
274: }
275: break;
276:
277: case 3:
278: /* Populate the full descriptor */
279: pb->usb.cntl.WValue = pb->usb.cntl.WValue & 0xff; // assumes what readconf does internally
280: if(immediateError(uslReadConfigurationDescriptor(pb)))
281: {
282: uslCompleteInternalStages(pb);
283: }
284: break;
285:
286: case 4:
287: uslCompleteInternalStages(pb);
288:
289: break;
290:
291: default:
292: USBExpertStatus(0,"USL - get full conf handler, unknown case", 0);
293: pb->usbStatus = kUSBInternalErr;
294: uslCompleteInternalStages(pb);
295: break;
296: }
297: break; /* only execute once, unless continue used */
298: }while(1); /* so case can be reentered with a continue */
299:
300:
301: }
302:
303: /* xxxx recast interms of cached */
304: OSStatus USBGetFullConfigurationDescriptor(USBPB *pb)
305: {
306: // --> usbReference Device
307: // --> usb.cntl.WValue Configuration
308: // <-- usbBuffer Configuration Descriptor Structure
309: // <-- usbActCount size of descriptor returned
310:
311:
312: if(!checkPBVersion(pb, 0))
313: {
314: return(pb->usbStatus);
315: }
316:
317:
318: pb->usbStatus = noErr;
319: uslInitialiseInternalStages(pb, getFulConfHandler);
320:
321: return(kUSBPending);
322: }
323:
324: static void *nextDescriptor(void *desc)
325: {
326: UInt8 *next;
327: next = desc;
328: next = &next[next[0]];
329: return(next);
330: }
331:
332: static OSStatus isConfigDescriptor(USBConfigurationDescriptor *conf)
333: {
334: if( (conf->descriptorType != kUSBConfDesc) ||
335: (conf->length < 9) ||
336: (conf->totalLength < 9) )
337: {
338: USBExpertStatus(0,"USL - Parse bad config descriptor", 0);
339: return(kUSBInternalErr);
340: }
341: return(noErr);
342: }
343:
344: /* xxxx make externally visible ? */
345: /* xxxx do some sanity checking on the dscriptor?? */
346: static OSStatus USBFindConfigDescriptorImmedite(USBPB *pb)
347: {
348: // <--> usbBuffer --> all config descriptors <-- Config desc
349: // --> usbReqCount total length of descriptors
350: // <-- usbActCount offset of this descriptor in config descriptor
351: // --> usb.cntl.WValue Config number
352: USBConfigurationDescriptor *conf;
353: void *end;
354:
355: if(!checkPBVersion(pb, 0))
356: {
357: return(pb->usbStatus);
358: }
359:
360: /* find configuration */
361: conf = pb->usbBuffer;
362: pb->usbStatus = isConfigDescriptor(conf);
363: if(pb->usbStatus != noErr)
364: {
365: return(pb->usbStatus);
366: }
367:
368: end = (void *)(((UInt32)pb->usbBuffer) + pb->usbReqCount);
369:
370: while( subtractAddress(end, conf) > 4)
371: {
372: pb->usbStatus = isConfigDescriptor(conf);
373: if(pb->usbStatus != noErr)
374: {
375: return(pb->usbStatus);
376: }
377:
378: if(subtractAddress(end, conf) < USBToHostWord(conf->totalLength) )
379: {
380: return(kUSBNotFound);
381: }
382: if(conf->configValue == pb->usb.cntl.WValue)
383: {
384: break;
385: }
386:
387: conf = (void *)(((UInt32)conf) + USBToHostWord(conf->totalLength) );
388:
389: }
390: if(subtractAddress(end, conf) < (9+9)) // smaller than 1 interface desc and 1 config desc
391: { // BT 18 Aug 98, Rainbow fix. Eliminate the =, so minimal descriptor can work
392: return(kUSBNotFound);
393: }
394:
395: // This check must be done after the one above.
396: pb->usbStatus = isConfigDescriptor(conf);
397: if(pb->usbStatus != noErr)
398: {
399: return(pb->usbStatus);
400: }
401:
402: pb->usbActCount = subtractAddress(conf, pb->usbBuffer);
403: pb->usbBuffer = conf;
404: return(noErr);
405:
406: }
407:
408: /* xxxx make externally visible ? */
409: /* xxxx do some sanity checking on the dscriptor?? */
410: static OSStatus USBFindNextConfigDescriptorImmedite(USBPB *pb)
411: {
412: // <--> usbBuffer --> all config descriptors <-- Config desc
413: // --> usbReqCount total length of descriptors
414: // <-- usbActCount offset of this descriptor in config descriptor
415: // <--> usb.cntl.WValue -->Config number <-- next config number
416: USBConfigurationDescriptor *conf;
417: void *end;
418: UInt32 remaining, confLen;
419:
420: if(!checkPBVersion(pb, 0))
421: {
422: return(pb->usbStatus);
423: }
424:
425: end = (void *)(((UInt32)pb->usbBuffer) + pb->usbReqCount);
426: /* find configuration */
427: pb->usbStatus = USBFindConfigDescriptorImmedite(pb);
428: if(pb->usbStatus != noErr)
429: {
430: return(pb->usbStatus);
431: }
432:
433: conf = pb->usbBuffer;
434: if(conf > end)
435: {
436: return(kUSBNotFound);
437: }
438: confLen = USBToHostWord(conf->totalLength);
439: remaining = subtractAddress(end, conf) - confLen;
440: if(remaining < 9+9) // a config plus an interface desc again
441: {
442: return(kUSBNotFound);
443: }
444: pb->usbBuffer = (void *)( ((UInt32)conf) + confLen );
445: pb->usbActCount += confLen;
446: conf = pb->usbBuffer;
447:
448: pb->usbStatus = isConfigDescriptor(conf);
449: if(pb->usbStatus != noErr)
450: {
451: return(pb->usbStatus);
452: }
453:
454: pb->usb.cntl.WValue = conf->configValue;
455: return(noErr);
456:
457: }
458: /* xxxx make externally visible ? */
459: /* xxxx do some sanity checking on the dscriptor?? */
460: static OSStatus USBFindInterfaceDescriptorImmedite(USBPB *pb)
461: {
462: // <--> usbBuffer --> all config descriptors <-- interface desc
463: // --> usbReqCount total length of descriptors
464: // <-- usbActCount offset of this descriptor in config descriptor
465: // --> usb.cntl.WIndex Interface number
466: // --> usb.cntl.WValue Config number
467: // --> usbOther alt. Set to 0xff to only find alt zero.
468: USBConfigurationDescriptor *conf;
469: USBInterfaceDescriptor *interface;
470: void *end;
471: UInt8 matchAlt;
472:
473: if(!checkPBVersion(pb, 0))
474: {
475: return(pb->usbStatus);
476: }
477:
478: pb->usbStatus = USBFindConfigDescriptorImmedite(pb);
479: if(pb->usbStatus != noErr)
480: {
481: return(pb->usbStatus);
482: }
483:
484: /* we found the configuration descriptor with this number */
485:
486: conf = pb->usbBuffer;
487:
488: /* now find the right interface */
489:
490: end = (void *)(((UInt32)conf) + USBToHostWord(conf->totalLength) - 9 /* interface desc length */ );
491: interface = nextDescriptor(conf);
492:
493: matchAlt = pb->usbOther;
494: if(matchAlt == 0xff)
495: {
496: matchAlt = 0;
497: }
498:
499: while(interface <= end) // BT 18Aug98, add = so minimal descriptors can work.
500: {
501: if( (interface->descriptorType == kUSBInterfaceDesc) &&
502: (interface->interfaceNumber == pb->usb.cntl.WIndex) &&
503: (interface->alternateSetting == matchAlt)
504: )
505: {
506: pb->usbActCount = subtractAddress(interface, pb->usbBuffer);
507: pb->usbBuffer = interface;
508: return(noErr);
509: }
510:
511: interface = nextDescriptor(interface);
512: }
513:
514: return(kUSBNotFound);
515: }
516:
517:
518:
519: OSStatus USBFindNextEndpointDescriptorImmediate(USBPB *pb)
520: {
521:
522: // <--> usbBuffer --> interface/endpoint descriptor <-- endpoint desc
523: // <--> usbReqCount offset of this descriptor in config descriptor
524: // <-- usbActcount length of descriptor found
525: // <--> usbDirection direction/wild card
526: // <--> usbClassType Endpoint type/wild card
527: // <--> usbOther Endpoint number, start at zero
528: // <-- usb.cntl.WValue Max packet size of endpoint
529:
530: // Note: usbReqCount is used for output here, the value needs to be fed back to the
531: // next call for this to work. In this sense, treat it like a magic cookie. It should
532: // be initialised to zero.
533:
534: USBConfigurationDescriptor *conf;
535: USBInterfaceDescriptor *interface;
536: USBEndPointDescriptor *endPt, *end;
537: UInt8 endPointNum;
538: UInt8 direction;
539: UInt8 type;
540: USBDirection usbDirection;
541:
542: if(!checkPBVersion(pb, kUSBAnyDirn))
543: {
544: return(pb->usbStatus);
545: }
546:
547: usbDirection = pb->usbFlags & kUSBAnyDirn;
548:
549: conf = (void *)((UInt8 *)pb->usbBuffer - pb->usbReqCount);
550: if( (conf->descriptorType != kUSBConfDesc)
551: || (pb->usbReqCount == 0) )
552: {
553: pb->usbStatus = paramErr;
554: return(pb->usbStatus);
555: }
556: end = (void *)(((UInt8 *)conf)+USBToHostWord(conf->totalLength));
557:
558: interface = (void *)pb->usbBuffer;
559:
560: if(interface->descriptorType == kUSBInterfaceDesc)
561: {
562: /* We have an interface descriptor */
563: endPt = nextDescriptor(interface);
564: }
565: else
566: { /* We have an endPt desccriptor */
567: endPt = pb->usbBuffer;
568: if(endPt->descriptorType != kUSBEndpointDesc)
569: {
570: pb->usbStatus = paramErr;
571: return(pb->usbStatus);
572: }
573: endPt = nextDescriptor(endPt);
574: }
575:
576: while(endPt < end)
577: {
578: if(endPt->descriptorType == kUSBInterfaceDesc)
579: {
580: break; /* not found */
581: }
582: if(endPt->descriptorType == kUSBEndpointDesc)
583: {
584: endPointNum = endPt->endpointAddress & 0xf;
585: direction = endPt->endpointAddress >> 7;
586: type = endPt->attributes & 3;
587:
588: if(
589: ( (usbDirection == kUSBAnyDirn) || (usbDirection == direction) ) &&
590: ( (pb->usbClassType == kUSBAnyType) || (pb->usbClassType == type) ) &&
591: ( (pb->usbOther == 0) || (pb->usbOther == endPointNum) )
592: )
593: {
594: /* This matches */
595: pb->usbBuffer = endPt;
596: pb->usbReqCount = subtractAddress(endPt, conf);
597: pb->usbActCount = endPt->length;
598: pb->usbFlags = direction;
599: pb->usbClassType = type; /* Fix this sometime */
600: pb->usbOther = endPointNum;
601: pb->usb.cntl.WValue = USBToHostWord(endPt->maxPacketSize);
602: return(noErr);
603: }
604: }
605:
606: endPt = nextDescriptor(endPt);
607: }
608:
609: pb->usbBuffer = conf;
610: pb->usbReqCount = 0;
611: pb->usbActCount = 0;
612: pb->usbFlags = kUSBAnyDirn;
613: pb->usbClassType = kUSBAnyType;
614: pb->usbOther = 0;
615: return(kUSBNotFound);
616:
617: }
618:
619: static OSStatus uslFindNextInterfaceDescriptorImmediate(USBPB *pb)
620: {
621:
622: // <--> usbBuffer --> config/interface descriptor <-- interface desc
623: // <-- usbActcount length of descriptor found
624: // <--> usbReqCount offset of this descriptor in config descriptor start = 0
625: // <--> usbClassType Class/wild card
626: // <--> usbSubclass subclass/wildcard
627: // <--> usbProtocol Protocol/wildcard
628: // <-- usb.cntl.WIndex InterfaceNumber
629: // <-- usb.cntl.WValue configuration value - Always return this, even on error
630: // <--> usbWOther alt. Set to Oxff to only find alt zero.
631:
632:
633: // Note: usbReqCount is used for output here, the value needs to be fed back to the
634: // next call for this to work. In this sense, treat it like a magic cookie. It should
635: // be initialised to zero.
636:
637: USBConfigurationDescriptor *conf;
638: USBInterfaceDescriptor *interface, *end;
639: UInt8 confNum;
640:
641: conf = (void *)((UInt8 *)pb->usbBuffer - pb->usbReqCount);
642: if(conf->descriptorType != kUSBConfDesc)
643: {
644: pb->usbStatus = paramErr;
645: return(pb->usbStatus);
646: }
647: confNum = conf->configValue;
648: end = (void *)(((UInt8 *)conf)+USBToHostWord(conf->totalLength));
649: pb->usb.cntl.WValue = confNum; // always return this
650:
651: if(pb->usbReqCount == 0)
652: {
653: /* We have a config descriptor */
654: interface = nextDescriptor(conf);
655: }
656: else
657: { /* We have an interface desccriptor */
658: interface = pb->usbBuffer;
659: if(interface->descriptorType != kUSBInterfaceDesc)
660: {
661: pb->usbStatus = paramErr;
662: return(pb->usbStatus);
663: }
664: interface = nextDescriptor(interface);
665: }
666:
667: while(interface < end)
668: {
669: if(interface->descriptorType == kUSBInterfaceDesc)
670: {
671: if(
672: ( (pb->usbClassType == 0) || (pb->usbClassType == interface->interfaceClass) ) &&
673: ( (pb->usbSubclass == 0) || (pb->usbSubclass == interface->interfaceSubClass) ) &&
674: ( (pb->usbProtocol == 0) || (pb->usbProtocol == interface->interfaceProtocol) ) &&
675: ( (pb->usbOther != 0xff) || (interface->alternateSetting == 0) )
676: )
677: {
678: /* This matches */
679: pb->usbBuffer = interface;
680: pb->usbReqCount = subtractAddress(interface, conf);
681: pb->usbActCount = interface->length;
682: pb->usb.cntl.WIndex = interface->interfaceNumber;
683: pb->usbClassType = interface->interfaceClass;
684: pb->usbSubclass = interface->interfaceSubClass;
685: pb->usbProtocol = interface->interfaceProtocol;
686: if(pb->usbOther != 0xff)
687: {
688: pb->usbOther = interface->alternateSetting;
689: }
690: return(noErr);
691: }
692: }
693:
694: interface = nextDescriptor(interface);
695: }
696:
697: pb->usbBuffer = conf;
698: pb->usbReqCount = 0;
699: pb->usbActCount = 0;
700:
701: return(kUSBNotFound);
702:
703: }
704:
705: OSStatus USBFindNextInterfaceDescriptorImmediate(USBPB *pb)
706: {
707:
708: // <--> usbBuffer --> config/interface descriptor <-- interface desc
709: // <-- usbActcount length of descriptor found
710: // <--> usbReqCount offset of this descriptor in config descriptor start = 0
711: // <--> usbClassType Class/wild card
712: // <--> usbSubclass subclass/wildcard
713: // <--> usbProtocol Protocol/wildcard
714: // <-- usb.cntl.WIndex InterfaceNumber
715: // <-- usb.cntl.WValue configuration value
716: // <--> usbWOther alt. Set to Oxff to only find alt zero.
717:
718: // Note: usbReqCount is used for output here, the value needs to be fed back to the
719: // next call for this to work. In this sense, treat it like a magic cookie. It should
720: // be initialised to zero.
721: OSStatus err;
722:
723: if(!checkPBVersion(pb, 0))
724: {
725: return(pb->usbStatus);
726: }
727:
728: err = uslFindNextInterfaceDescriptorImmediate(pb);
729: if(err != noErr)
730: {
731: pb->usb.cntl.WIndex = 0;
732: pb->usb.cntl.WValue = 0;
733: }
734: return(err);
735: }
736:
737: /* xxxx Need a force unit access bit, or clear cahced descriptor function */
738: /* xxxx need to read configs other than zero */
739: static void *uslCacheConfigDescriptors(USBPB *pb)
740: { /* make confid descriptors are cached. Return pointer when they are */
741: int stage;
742: usbDevice *dev;
743: static countLoop, getLoop;
744:
745: #if 0
746: if(pb->usbStatus != noErr)
747: {
748: uslCompleteInternalStages(pb);
749: return(nil);
750: }
751: #endif
752:
753: // Don't use getDev here, if it goes wrong it calls back straight to here
754: dev = getDevicePtr(pb->usbReference);
755: if(dev == nil)
756: {
757: pipe *p;
758: // Maybe its a pipe ref. This is only used find assoc desc.
759: // That should have the descriptors cached, so this is not going to be called too often
760: (void)findPipe(pb->usbReference, &p);
761: if(p != nil)
762: {
763: dev = getDevicePtr(p->devIntfRef);
764: }
765: if(dev == nil)
766: {
767: pb->usbStatus = kUSBUnknownDeviceErr;
768: (*pb->usbCompletion)(pb);
769: return(nil);
770: }
771: }
772:
773: if(dev->killMe)
774: {
775: USBExpertStatus(0,"USL - Killing dead device", 0);
776: dev->killMe = 0;
777: #if 1
778: dev->configLock = 0;
779: uslClearInternalStage(pb);
780: // Don't call back this has been hosed already?
781: #else
782: dev->configLock = 0;
783: uslClearInternalStage(pb);
784: pb->usbCompletion = (void *)pb->reserved2;
785: uslDeleteDevice(pb, dev);
786: #endif
787: return(nil);
788: }
789:
790:
791: if(dev->confValid)
792: { /* We should CRC the descriptor here */
793: pb->usbActCount = dev->allConfigLen;
794: pb->usbBuffer = dev->allConfigDescriptors;
795: return(dev->allConfigDescriptors);
796: }
797:
798: /* xxx we need to lock out concurrent attempts to do this */
799:
800:
801: do{
802: stage = uslFindInternalStageAndIncriment(pb);
803: switch(stage)
804: {
805: case 1:
806: pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBIn, kUSBStandard, kUSBDevice);
807: pb->usb.cntl.BRequest = kUSBRqGetDescriptor;
808: pb->usb.cntl.WValue = (kUSBDeviceDesc << 8) + 0/*index*/;
809: pb->usb.cntl.WIndex = 0;
810: pb->usbReqCount = OFFSET(USBDeviceDescriptor, descEnd);
811: pb->usbBuffer = &dev->deviceDescriptor;
812:
813: if(immediateError(uslDeviceRequest(pb)))
814: {
815: uslCompleteInternalStages(pb);
816: }
817:
818: break;
819:
820: case 2:
821: /* use dev scratch to get the root config descritor */
822:
823: /* count length of all descriptors */
824: dev->allConfigLen = 0;
825:
826: pb->usbReqCount = sizeof(configHeader);
827: pb->usbBuffer = &dev->configScratch;
828: pb->usb.cntl.WValue = 0;
829: countLoop = stage;
830:
831: continue;
832: break;
833:
834: case 3:
835: /* Get the descriptor */
836: if(immediateError(uslReadConfigurationDescriptor(pb)))
837: {
838: uslCompleteInternalStages(pb);
839: }
840: break;
841:
842: case 4:
843:
844: pb->usb.cntl.WValue &= 0xff;
845: pb->usb.cntl.WValue++;
846: if(pb->usbStatus == noErr)
847: {
848: dev->allConfigLen += USBToHostWord(((configHeader *)pb->usbBuffer)->totalLen);
849: if(pb->usb.cntl.WValue < dev->deviceDescriptor.numConf)
850: {
851: stage = countLoop;
852: uslSetInternalStage(pb, stage);
853: }
854: }
855: else
856: {
857: if(dev->allConfigLen == 0)
858: {
859: uslCompleteInternalStages(pb);
860: return(nil);
861: }
862: }
863: continue;
864:
865: break;
866:
867: case 5:
868: /* How long is full descritptor */
869: pb->usbReqCount = dev->allConfigLen;
870:
871: /* Allocate the full descriptor */
872: if(immediateError(uslAllocMem(pb)))
873: {
874: uslCompleteInternalStages(pb);
875: }
876: break;
877:
878: case 6:
879: if(pb->usbStatus != noErr)
880: {
881: uslCompleteInternalStages(pb);
882: return(nil);
883: }
884: dev->allConfigDescriptors = pb->usbBuffer;
885: // note pb->usbReqCount still valid from alloc
886: /* Populate the full descriptor */
887: getLoop =stage;
888: pb->usb.cntl.WValue = 0;
889:
890: continue;
891: break;
892:
893: case 7:
894:
895: if(immediateError(uslReadConfigurationDescriptor(pb)))
896: {
897: uslCompleteInternalStages(pb);
898: }
899: break;
900:
901: case 8:
902: pb->usb.cntl.WValue &= 0xff;
903: pb->usb.cntl.WValue++;
904:
905: if(pb->usbStatus == noErr)
906: {
907: pb->usbBuffer = (void *)((UInt32)pb->usbBuffer + USBToHostWord(((configHeader *)pb->usbBuffer)->totalLen));
908: pb->usbReqCount = dev->allConfigLen - subtractAddress(pb->usbBuffer, dev->allConfigDescriptors);
909: if(pb->usbReqCount > dev->allConfigLen) // we wrapped
910: {
911: pb->usbStatus = kUSBInternalErr;
912: }
913: if( (pb->usbReqCount != 0) && (pb->usb.cntl.WValue < dev->deviceDescriptor.numConf) )
914: {
915: stage = getLoop;
916: uslSetInternalStage(pb, stage);
917: }
918: }
919: else
920: {
921: if(dev->allConfigLen == 0)
922: {
923: uslCompleteInternalStages(pb);
924: return(nil);
925: }
926: }
927: continue;
928: break;
929:
930: case 9:
931: dev->confValid = true;
932: uslClearInternalStage(pb);
933: pb->usbActCount = dev->allConfigLen;
934: pb->usbBuffer = dev->allConfigDescriptors;
935: return(dev->allConfigDescriptors);
936:
937: break;
938:
939: default:
940: USBExpertStatus(0,"USL - cache conf handler, unknown case", 0);
941: pb->usbStatus = kUSBInternalErr;
942: uslCompleteInternalStages(pb);
943: break;
944: }
945: break; /* only execute once, unless continue used */
946: }while(1); /* so case can be reentered with a continue */
947: return(nil);
948: }
949: #if 0
950: OSStatus USBFindInterface(USBPB *pb); (Not implemented yet)
951:
952: --> usbReference device /interface????
953: <-- usbBuffer interface descriptor
954: <-- usbActcount length of descriptor found
955: -- usbReqCount reserved, set to zero.
956: --> usbClassType Class
957: --> usbSubclass subclass
958: --> usbProtocol Protocol
959: <--> usb.cntl.WValue configuration number (start at zero)
960: <--> usb.cntl.WIndex InterfaceNumber (start at zero)
961: <--> usbOther alt // (set to 0xff to find first alt zero only)
962: #endif
963:
964: /* xxxx sort out usage of alt */
965: static void uslFindNextInterface(USBPB *pb)
966: {
967: OSStatus err = kUSBNotFound;
968: void *configDescriptors;
969: UInt32 totalLen;
970:
971: configDescriptors = uslCacheConfigDescriptors(pb);
972: if(configDescriptors == nil)
973: {
974: return;
975: }
976: totalLen = pb->usbActCount;
977:
978: pb->usb.cntl.WIndex = pb->wIndexStash;
979: pb->usb.cntl.WValue = pb->wValueStash;
980:
981: if( (pb->usb.cntl.WIndex == 0) && (pb->usb.cntl.WValue == 0) )
982: {
983: /* First call to this, init config descriptor */
984: pb->usbReqCount = 0;
985: pb->usbStatus = noErr;
986: }
987: else
988: {
989: pb->usbReqCount = pb->usbActCount;
990: pb->usbStatus = USBFindInterfaceDescriptorImmedite(pb);
991: pb->usbReqCount = pb->usbActCount;
992: }
993: while(pb->usbStatus == noErr)
994: {
995: USBConfigurationDescriptor *c;
996: c = (void *)pb->usbBuffer;
997: pb->usbStatus = uslFindNextInterfaceDescriptorImmediate(pb);
998: if(pb->usbStatus == noErr)
999: {
1000: if( (pb->addrStash == 0) ||
1001: (c->maxPower <= pb->addrStash) )
1002: {
1003: break;
1004: }
1005: err = kUSBDevicePowerProblem;
1006: }
1007:
1008: /* Not found in that config desc, try the next */
1009: pb->usbReqCount = totalLen;
1010: pb->usbBuffer = configDescriptors;
1011: pb->usbStatus = USBFindNextConfigDescriptorImmedite(pb);
1012: pb->usbReqCount = 0;
1013: }
1014:
1015: pb->usbActCount = 0;
1016: pb->usbBuffer = 0;
1017: // pb->usbReqCount = 0;
1018: pb->usbReqCount = pb->addrStash;
1019:
1020: if(pb->usbStatus != noErr)
1021: {
1022: pb->usb.cntl.WValue = 0;
1023: pb->usb.cntl.WIndex = 0;
1024: }
1025:
1026: if(pb->usbStatus == kUSBNotFound)
1027: { // If an interface found without sufficient power, say power prob
1028: pb->usbStatus = err;
1029: }
1030: uslCompleteInternalStages(pb);
1031: return;
1032:
1033: }
1034:
1035: /* xxxx sort out usage of alt */
1036: OSStatus USBFindNextInterface(USBPB *pb)
1037: {
1038: usbDevice *dev;
1039:
1040: if(!checkPBVersion(pb, 0))
1041: {
1042: return(pb->usbStatus);
1043: }
1044: pb->addrStash = pb->usbReqCount; // reqcount now has the power available
1045: pb->usbReqCount = 0;
1046: if(checkZeroBuffer(pb))
1047: {
1048: return(paramErr);
1049: }
1050: dev = getDev(pb);
1051: if(dev == nil)
1052: {
1053: return(kUSBUnknownDeviceErr);
1054: }
1055:
1056: pb->wIndexStash = pb->usb.cntl.WIndex;
1057: pb->wValueStash = pb->usb.cntl.WValue;
1058:
1059: pb->usbStatus = noErr;
1060: uslInitialiseInternalStages(pb, uslFindNextInterface);
1061: return(kUSBPending);
1062: }
1063:
1064: static void uslGetConfigurationDescriptor(USBPB *pb)
1065: {
1066: USBConfigurationDescriptor *configDescriptors;
1067: UInt32 confLen;
1068: configDescriptors = uslCacheConfigDescriptors(pb);
1069: if(configDescriptors == nil)
1070: {
1071: return;
1072: }
1073:
1074: /* note, we're relying on WValue being passed through here */
1075:
1076: pb->usbReqCount = pb->usbActCount;
1077: pb->usbStatus = USBFindConfigDescriptorImmedite(pb);
1078: configDescriptors = pb->usbBuffer;
1079: confLen = USBToHostWord(configDescriptors->totalLength);
1080: pb->usbActCount = pb->usbReqCount;
1081: if(pb->usbActCount > pb->wValueStash)
1082: {
1083: pb->usbActCount = pb->wValueStash;
1084: }
1085: if(pb->usbActCount > confLen)
1086: {
1087: pb->usbActCount = confLen;
1088: }
1089: pb->usbReqCount = pb->wValueStash;
1090: pb->wIndexStash = pb->usb.cntl.WIndex;
1091: usb_BlockMoveData(pb->usbBuffer, (void *) pb->addrStash, pb->usbActCount);
1092: pb->usbBuffer = (void *)pb->addrStash;
1093:
1094: uslCompleteInternalStages(pb);
1095: return;
1096:
1097: }
1098:
1099: OSStatus USBGetConfigurationDescriptor(USBPB *pb)
1100: {
1101:
1102: // --> usbReference Device
1103: // --> usb.cntl.WValue Configuration index
1104: // --> usbBuffer Configuration Descriptor Structure
1105: // --> usbReqCount size of edscriptor
1106: // <-- usbActCount size of descriptor returned
1107: usbDevice *dev;
1108:
1109: if(!checkPBVersion(pb, 0))
1110: {
1111: return(pb->usbStatus);
1112: }
1113: dev = getDev(pb);
1114: if(dev == nil)
1115: {
1116: return(kUSBUnknownDeviceErr);
1117: }
1118: pb->usbStatus = noErr;
1119: pb->wIndexStash = pb->usb.cntl.WIndex;
1120: pb->addrStash = (UInt32)pb->usbBuffer;
1121: pb->wValueStash = pb->usbReqCount;
1122: if(pb->usbReqCount > 0x7fff)
1123: {
1124: pb->wValueStash = 0x7fff;
1125: }
1126: uslInitialiseInternalStages(pb, uslGetConfigurationDescriptor);
1127: return(kUSBPending);
1128: }
1129:
1130: static Boolean noMoreDescriptors(USBDescriptorHeader *desc, void *end, Boolean endpoint)
1131: {
1132: return(
1133: (desc >= end) || /* run out of descriptors */
1134: /* BT 2Jul98, don't forget ==, caused hang of desc did not exist */
1135: (desc->descriptorType == kUSBConfDesc) || /* got to next conf desc */
1136: (desc->descriptorType == kUSBInterfaceDesc) || /* got to next interfc desc */
1137: ( (desc->descriptorType == kUSBEndpointDesc) && endpoint )
1138: /* got to next endpoint desc, for endpoint only*/
1139: );
1140: }
1141:
1142: static void uslFindNextAssociatedDescriptor(USBPB *pb)
1143: {
1144: USBConfigurationDescriptor *configDescriptors;
1145: uslInterface *intrfc;
1146: pipe *p;
1147: USBInterfaceRef iRef;
1148: usbDevice *dev;
1149: UInt16 count;
1150: UInt8 *end;
1151: USBDescriptorHeader *desc;
1152: UInt8 descType;
1153:
1154: configDescriptors = uslCacheConfigDescriptors(pb);
1155: if(configDescriptors == nil)
1156: {
1157: return;
1158: }
1159:
1160: pb->usbFlags = 0;
1161: end = (UInt8 *)configDescriptors + pb->usbActCount;
1162: pb->usbReqCount = pb->usbActCount;
1163:
1164: pb->usbStatus = findPipe(pb->usbReference, &p);
1165: if(pb->usbStatus == noErr)
1166: {
1167: iRef = p->devIntfRef;
1168: }
1169: else
1170: {
1171: p = nil;
1172: iRef = pb->usbReference;
1173: }
1174: pb->usbStatus = findInterface(iRef, &intrfc);
1175: if(pb->usbStatus != noErr)
1176: {
1177: uslCompleteInternalStages(pb);
1178: return;
1179: }
1180:
1181: /* ref was an interface or pipe ref (with interface container). */
1182: /* p not nil if pipe, intrfc set */
1183:
1184: dev = getDevicePtr(iRef);
1185: if(dev == nil)
1186: {
1187: pb->usbStatus = kUSBUnknownDeviceErr;
1188: uslCompleteInternalStages(pb);
1189: return;
1190: }
1191:
1192: pb->usb.cntl.WIndex = intrfc->interfaceNum;
1193: pb->usb.cntl.WValue = dev->currentConfiguration;
1194: descType = pb->usbOther;
1195: pb->usbOther = intrfc->alt;
1196: pb->usbStatus = USBFindInterfaceDescriptorImmedite(pb);
1197: if(pb->usbStatus != noErr)
1198: {
1199: uslCompleteInternalStages(pb);
1200: return;
1201: }
1202:
1203: if(p != nil)
1204: {
1205: pb->usbReqCount = pb->usbActCount;
1206: pb->usbFlags = kUSBAnyDirn;
1207: pb->usbClassType = kUSBAnyType;
1208: pb->usbOther = p->endPt;
1209: pb->usbStatus = USBFindNextEndpointDescriptorImmediate(pb);
1210: if(pb->usbStatus != noErr)
1211: {
1212: uslCompleteInternalStages(pb);
1213: return;
1214: }
1215: }
1216:
1217: /* we're now pointing to the relevant descriptor to start with */
1218: pb->usb.cntl.WIndex = pb->wIndexStash;
1219:
1220: count = 0;
1221: desc = pb->usbBuffer;
1222: while(count < pb->usb.cntl.WIndex)
1223: {
1224: desc = nextDescriptor(desc);
1225: if(noMoreDescriptors(desc, end, (p != nil)))
1226: {
1227: pb->usbStatus = kUSBNotFound;
1228: uslCompleteInternalStages(pb);
1229: return;
1230: }
1231: count++;
1232: }
1233:
1234: pb->usb.cntl.WIndex++; /* Next descriptor */
1235:
1236: if(descType != 0)
1237: {
1238: while(desc->descriptorType != descType)
1239: {
1240: desc = nextDescriptor(desc);
1241: pb->usb.cntl.WIndex++;
1242: if(noMoreDescriptors(desc, end, (p != nil)) ||
1243: (pb->usb.cntl.WIndex > 0x7ffe) ) // BT 2Jul98, if something goes wrong stop
1244: {
1245: pb->usbStatus = kUSBNotFound;
1246: uslCompleteInternalStages(pb);
1247: return;
1248: }
1249: }
1250: }
1251:
1252: /* now desc points to the descriptor to return */
1253: pb->usbOther = desc->descriptorType;
1254: pb->usbBuffer = (void *)pb->addrStash;
1255: pb->usbReqCount = pb->wValueStash;
1256: pb->usbActCount = desc->length;
1257:
1258: if(pb->usbActCount > pb->usbReqCount)
1259: {
1260: pb->usbActCount = pb->usbReqCount;
1261: }
1262:
1263: pb->wIndexStash = pb->usb.cntl.WIndex;
1264: pb->usb.cntl.WValue = 0;
1265: usb_BlockMoveData(desc, pb->usbBuffer, pb->usbActCount);
1266:
1267: uslCompleteInternalStages(pb);
1268: return;
1269:
1270: }
1271:
1272: OSStatus USBFindNextAssociatedDescriptor(USBPB *pb)
1273: {
1274: // --> usbReference Interface/Endpoint
1275: // <--> usb.cntl.WIndex Descriptor index (magic cookie) start at zero
1276: // --> usbBuffer Descriptor buffer
1277: // --> usbReqCount size of buffer
1278: // <-- usbActCount size of descriptor returned
1279: // <--> usbOther Descriptor type (zero matches any)
1280:
1281:
1282: if(!checkPBVersion(pb, 0))
1283: {
1284: return(pb->usbStatus);
1285: }
1286:
1287: /* check interface/endpoint here */
1288:
1289: pb->usbStatus = noErr;
1290: pb->wIndexStash = pb->usb.cntl.WIndex;
1291: pb->addrStash = (UInt32)pb->usbBuffer;
1292: pb->wValueStash = pb->usbReqCount;
1293: if(pb->usbReqCount > 0x7fff)
1294: {
1295: pb->wValueStash = 0x7fff;
1296: }
1297: uslInitialiseInternalStages(pb, uslFindNextAssociatedDescriptor);
1298: return(kUSBPending);
1299: }
1300:
1301: #if 0
1302: OSStatus USBOpenDevice(USBPB *pb);
1303:
1304: --> usbReference device
1305: --> usb.cntl.WValue configuration number (preserved)
1306: --> usbFlags Open interfaces immediately
1307: -- usb.cntl.WIndex is preserved (unusually)
1308: <-- usbValue4 number of interfaces in configuration
1309: #endif
1310:
1311: /* xxxx Check device power before config */
1312: static void uslSetDeviceConfig(USBPB *pb)
1313: {
1314: // <--> usbBuffer --> Config desc
1315: // --> usb.cntl.WValue Config number
1316: int stage;
1317: usbDevice *dev;
1318: USBConfigurationDescriptor *conf;
1319:
1320: if(pb->usbStatus != noErr)
1321: {
1322: uslCompleteInternalStages(pb);
1323: return;
1324: }
1325:
1326: stage = uslFindInternalStageAndIncriment(pb);
1327:
1328: do{switch(stage)
1329: {
1330: case 1:
1331: pb->usbReqCount = 0;
1332: // pb->usbBuffer = nil; // preserve config desc
1333:
1334: pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBNone, kUSBStandard, kUSBDevice);
1335: pb->usb.cntl.BRequest = kUSBRqSetConfig;
1336: // pb->usb.cntl.WValue = confNum; // input param
1337: pb->usb.cntl.WIndex = 0;
1338: if(immediateError(uslDeviceRequest(pb)))
1339: {
1340: uslCompleteInternalStages(pb);
1341: }
1342: break;
1343:
1344: case 2:
1345: dev = getDev(pb);
1346: if(dev == nil)
1347: {
1348: pb->usbStatus = kUSBUnknownDeviceErr;
1349: }
1350: /* We've configured the device, so what? */
1351: else
1352: {
1353: conf = pb->usbBuffer;
1354: pb->usbActCount = USBToHostWord(conf->totalLength);
1355: dev->currentConfiguration = pb->wValueStash;
1356: /* note complete stages now implictly unlcoks device */
1357:
1358: }
1359:
1360: /* restore these values, so find interface, getinterface ref works across here */
1361: pb->usb.cntl.WValue = pb->wValueStash;
1362: pb->usb.cntl.WIndex = pb->wIndexStash;
1363:
1364: pb->usbReqCount = 0;
1365: pb->usbActCount = 0;
1366: pb->usbBuffer = 0;
1367:
1368: uslCompleteInternalStages(pb);
1369: break;
1370:
1371: default:
1372: USBExpertStatus(0,"USL - set conf handler, unknown case", 0);
1373: pb->usbStatus = kUSBInternalErr;
1374: pb->usbBuffer = (void *)pb->addrStash; // for dev reqs diverted
1375: uslCompleteInternalStages(pb);
1376: break;
1377: }
1378: break; /* only execute once, unless continue used */
1379: }while(1); /* so case can be reentered with a continue */
1380: return;
1381: }
1382:
1383: /* xxxx Check device power before config */
1384: static void uslOpenDevice2(USBPB *pb)
1385: {
1386: USBConfigurationDescriptor *conf;
1387: usbDevice *dev;
1388:
1389: conf = uslCacheConfigDescriptors(pb);
1390: if(conf == nil)
1391: {
1392: return;
1393: }
1394: dev = getDev(pb);
1395: if(dev == nil)
1396: {
1397: return;
1398: }
1399:
1400: pb->usbReqCount = pb->usbActCount;
1401:
1402: pb->usb.cntl.WValue = pb->wValueStash;
1403: pb->usbStatus = USBFindConfigDescriptorImmedite(pb);
1404:
1405: if(pb->usbStatus != noErr)
1406: {
1407: uslCompleteInternalStages(pb);
1408: return;
1409: }
1410: conf = pb->usbBuffer;
1411:
1412: if(conf->maxPower > dev->powerAvailable)
1413: {
1414: USBExpertStatus(0,"USL - Not enough power. Available:", dev->powerAvailable);
1415: USBExpertStatus(0,"USL - Not enough power. needed:", conf->maxPower);
1416:
1417: pb->usbStatus = kUSBDevicePowerProblem;
1418: USBExpertSetDevicePowerStatus(pb->usbReference, 0, 0, kUSBDevicePower_BusPowerInsufficient, dev->powerAvailable, conf->maxPower); // TC: <USB67>
1419: uslCompleteInternalStages(pb);
1420: return;
1421: }
1422: // pb->usb.cntl.WValue already set up. USBFindConfigDescriptorImmedite doesn't change it
1423:
1424: pb->usbOther = conf->numInterfaces; // eventual output
1425: pb->usbCompletion = (void *)pb->reserved2; /* restore users handler */
1426: uslInitialiseInternalStages(pb, uslSetDeviceConfig);
1427: return;
1428:
1429: }
1430:
1431: OSStatus uslOpenDevice(USBPB *pb)
1432: {
1433: usbDevice *dev;
1434: /* This is called by dev req when a set config is requested */
1435: /* thats stashed the buffer, we need to restore the buffer */
1436: /* if stashed */
1437: dev = getDev(pb);
1438: if(dev == nil)
1439: {
1440: return(kUSBUnknownDeviceErr);
1441: }
1442: if(!CompareAndSwap(0, 1, &dev->configLock)) /* complete stages now unlocks */
1443: {
1444: USBExpertStatus(0, "USL - Attempt to open busy device", dev->usbAddress);
1445: return(kUSBDeviceBusy);
1446: }
1447:
1448: uslUnconfigureDevice(dev);
1449:
1450: pb->usbStatus = noErr;
1451: pb->wValueStash = pb->usb.cntl.WValue;
1452: pb->wIndexStash = pb->usb.cntl.WIndex;
1453: uslInitialiseInternalStages(pb, uslOpenDevice2);
1454: return(kUSBPending);
1455: }
1456:
1457: /* xxxx Check device power before config */
1458: /* xxxx sort out config value in usb.cntl.WValue or usbValue4 */
1459: OSStatus USBOpenDevice(USBPB *pb)
1460: {
1461: if(!checkPBVersion(pb, 0))
1462: {
1463: return(pb->usbStatus);
1464: }
1465: if(checkZeroBuffer(pb))
1466: {
1467: return(paramErr);
1468: }
1469: pb->addrStash = 0; // so crap doesn't get restored
1470: return(uslOpenDevice(pb));
1471: }
1472:
1473: #if 0
1474: OSStatus USBNewInterfaceRef(USBPB *pb)
1475:
1476: // <--> usbReference --> device <-- interface
1477: // --> usb.cntl.WIndex InterfaceNumber
1478: #endif
1479:
1480: /* xxxx sort out alt usage */
1481: static void uslNewInterfaceRef(USBPB *pb)
1482: {
1483: USBConfigurationDescriptor *conf;
1484: uslInterface *intrfc;
1485: usbDevice *dev;
1486: UInt8 oldOther;
1487:
1488: conf = uslCacheConfigDescriptors(pb);
1489: if(conf == nil)
1490: {
1491: return;
1492: }
1493: dev = getDev(pb);
1494: if(dev == nil)
1495: {
1496: return;
1497: }
1498:
1499: pb->usbReqCount = pb->usbActCount;
1500: pb->usb.cntl.WValue = dev->currentConfiguration;
1501: //WIndex is a param
1502: oldOther = pb->usbOther;
1503: pb->usbOther = 0xff; // Ignore alt
1504: pb->usbStatus = USBFindInterfaceDescriptorImmedite(pb);
1505: pb->usbOther = oldOther;
1506:
1507: if(pb->usbStatus != noErr)
1508: {
1509: uslCompleteInternalStages(pb);
1510: return;
1511: }
1512:
1513: /* Specified interface does exist */
1514:
1515: intrfc = AllocInterface(pb->usbReference);
1516: if(intrfc == 0)
1517: {
1518: pb->usbStatus = kUSBOutOfMemoryErr;
1519: uslCompleteInternalStages(pb);
1520: return;
1521: }
1522:
1523: pb->usbReference = intrfc->ref;
1524: intrfc->interfaceNum = pb->wIndexStash;
1525:
1526: pb->usbStatus = noErr;
1527: pb->usbReqCount = 0;
1528: pb->usbActCount = 0;
1529: pb->usbBuffer = 0;
1530:
1531: /* note complete stages now unlocks device */
1532: uslCompleteInternalStages(pb);
1533: }
1534:
1535: #if 0
1536: OSStatus USBNewInterfaceRef(USBPB *pb);
1537:
1538:
1539: <--> usbReference --> device <-- interface
1540: --> usb.cntl.WIndex InterfaceNumber
1541: --> usbFlags
1542: #endif
1543:
1544: /* xxxx sort out alt usage */
1545: OSStatus USBNewInterfaceRef(USBPB *pb)
1546: {
1547: usbDevice *dev;
1548: uslInterface *intrfc;
1549:
1550: if(!checkPBVersion(pb, 0))
1551: {
1552: return(pb->usbStatus);
1553: }
1554: if(checkZeroBuffer(pb))
1555: {
1556: return(paramErr);
1557: }
1558: pb->usbStatus = findInterface(pb->usbReference, &intrfc);
1559: if(pb->usbStatus == noErr)
1560: { // BT 2Jul98, don't allow interface ref here, device ref only.
1561: pb->usbStatus = kUSBUnknownDeviceErr;
1562: return(kUSBUnknownDeviceErr);
1563: }
1564: dev = getDev(pb);
1565: if(dev == nil)
1566: {
1567: return(kUSBUnknownDeviceErr);
1568: }
1569: if(!CompareAndSwap(0, 1, &dev->configLock))
1570: {
1571: USBExpertStatus(0, "USL - USBNewInterfaceRef, device busy", dev->usbAddress);
1572: return(kUSBDeviceBusy);
1573: }
1574:
1575: pb->usbStatus = noErr;
1576: pb->wIndexStash = pb->usb.cntl.WIndex;
1577:
1578: uslInitialiseInternalStages(pb, uslNewInterfaceRef);
1579: return(kUSBPending);
1580: }
1581:
1582: /* xxxx sort out alt usage */
1583: static void uslConfigureInterface(USBPB *pb)
1584: {
1585: USBConfigurationDescriptor *conf;
1586: uslInterface *intrfc;
1587: usbDevice *dev;
1588: UInt16 pipeCount;
1589:
1590: conf = uslCacheConfigDescriptors(pb);
1591: if(conf == nil)
1592: {
1593: return;
1594: }
1595: pb->usbStatus = findInterface(pb->usbReference, &intrfc);
1596: if(pb->usbStatus != noErr)
1597: {
1598: uslCompleteInternalStages(pb);
1599: return;
1600: }
1601: dev = getDev(pb);
1602: if(dev == nil)
1603: {
1604: return;
1605: }
1606:
1607: uslCloseInterfacePipes(intrfc->ref, dev);
1608:
1609: pb->usb.cntl.WValue = pb->wValueStash;
1610:
1611: pb->usbReqCount = pb->usbActCount;
1612: pb->usb.cntl.WValue = dev->currentConfiguration;
1613: pb->usb.cntl.WIndex = intrfc->interfaceNum;
1614: pb->usbStatus = USBFindInterfaceDescriptorImmedite(pb);
1615:
1616: if(pb->usbStatus != noErr)
1617: {
1618: uslCompleteInternalStages(pb);
1619: return;
1620: }
1621:
1622: intrfc->alt = pb->usbOther; // remember alt
1623: pb->usbOther = 0; // count of endpoints in interface
1624: pb->usbReqCount = pb->usbActCount;
1625:
1626: pipeCount = 0;
1627: do{
1628: pb->usbFlags = kUSBAnyDirn;
1629: pb->usbClassType = kUSBAnyType;
1630: pb->usbOther = 0; // don't match against endpoint number
1631:
1632: pb->usbStatus = USBFindNextEndpointDescriptorImmediate(pb);
1633: if(pb->usbStatus == noErr)
1634: {
1635: pb->usbStatus = uslOpenPipeImmed(intrfc->ref, pb->usbBuffer);
1636: if(pb->usbStatus == noErr)
1637: {
1638: pipeCount++;
1639: }
1640: else
1641: {
1642:
1643: pb->usbReqCount = 0;
1644: pb->usbActCount = 0;
1645: pb->usbBuffer = 0;
1646:
1647: uslCompleteInternalStages(pb);
1648: return;
1649: }
1650: }
1651:
1652: }while(pb->usbStatus == noErr);
1653:
1654: pb->usbStatus = noErr;
1655:
1656: pb->usbReqCount = 0;
1657: pb->usbActCount = 0;
1658: pb->usbBuffer = 0;
1659:
1660: pb->usbOther = pipeCount;
1661:
1662: uslCompleteInternalStages(pb);
1663: }
1664:
1665: /* xxxx sort out alt usage */
1666: OSStatus USBConfigureInterface(USBPB *pb)
1667: {
1668: // <--> usbReference interface
1669: // --> usbW??? alt
1670: // --> usbFlags
1671: // <-- usbOther Number of pipes in interface
1672: uslInterface *intrfc;
1673:
1674: if(!checkPBVersion(pb, 0))
1675: {
1676: return(pb->usbStatus);
1677: }
1678: if(checkZeroBuffer(pb))
1679: {
1680: return(paramErr);
1681: }
1682:
1683: pb->usbStatus = findInterface(pb->usbReference, &intrfc);
1684: if(pb->usbStatus != noErr)
1685: {
1686: return(pb->usbStatus);
1687: }
1688: pb->usbStatus = noErr;
1689: pb->wValueStash = pb->usb.cntl.WValue;
1690: uslInitialiseInternalStages(pb, uslConfigureInterface);
1691: return(kUSBPending);
1692:
1693: }
1694:
1695: /* xxxx test this with mor ethan one interface */
1696: OSStatus USBFindNextPipe(USBPB *pb)
1697: {
1698:
1699: // <--> usbReference --> interface/pipe <-- Pipe
1700: // <--> usbFLags direction/wild card
1701: // <--> usbValue1 Endpoint type/wild card
1702: uslInterface *intrfc;
1703: usbDevice *dev;
1704: pipe *p;
1705: USBReference container;
1706: int idx;
1707:
1708:
1709: if(!checkPBVersion(pb, kUSBAnyDirn))
1710: {
1711: return(pb->usbStatus);
1712: }
1713: if(checkZeroBuffer(pb))
1714: {
1715: return(paramErr);
1716: }
1717:
1718: pb->usbStatus = findInterface(pb->usbReference, &intrfc);
1719: if(pb->usbStatus == noErr)
1720: {
1721: idx = 0;
1722: dev = getDev(pb);
1723: if(dev == nil)
1724: {
1725: return(kUSBUnknownDeviceErr);
1726: }
1727: container = pb->usbReference;
1728: }
1729: else
1730: {
1731: pb->usbStatus = findPipe(pb->usbReference, &p);
1732: if(p == nil)
1733: {
1734: return(pb->usbStatus);
1735: }
1736: container = p->devIntfRef;
1737: dev = getDevicePtr(container);
1738: if(dev == nil)
1739: {
1740: return(kUSBUnknownPipeErr);
1741: }
1742:
1743: idx = makeDevPipeIdx(p->endPt, p->direction)+1;
1744: if(idx > kUSBMaxEndptPerDevice)
1745: {
1746: return(kUSBNotFound);
1747: }
1748: }
1749:
1750: /* Now have a starting point in devices pipe table */
1751:
1752: for(; idx < kUSBMaxEndptPerDevice; idx++)
1753: {
1754: if(dev->pipes[idx] != -1)
1755: {
1756: p = getPipeByIdx(dev->pipes[idx]);
1757: if(p == nil)
1758: {
1759: return(kUSBInternalErr);
1760: }
1761: if( (container == p->devIntfRef) &&
1762: ((pb->usbFlags == kUSBAnyDirn) || (pb->usbFlags == p->direction)) &&
1763: ((pb->usbClassType == kUSBAnyType) || (pb->usbClassType == p->type)) )
1764: {
1765: pb->usbStatus = noErr;
1766: pb->usbReference = p->ref;
1767: pb->usbFlags = p->direction;
1768: pb->usbClassType = p->type;
1769: pb->usb.cntl.WValue = p->maxPacket;
1770:
1771: pb->usbReqCount = 0;
1772: pb->usbActCount = 0;
1773: pb->usbBuffer = 0;
1774:
1775: (*pb->usbCompletion)(pb);
1776:
1777: return(kUSBPending);
1778: }
1779: }
1780: }
1781: pb->usbReqCount = 0;
1782: pb->usbActCount = 0;
1783: pb->usbBuffer = 0;
1784: pb->usb.cntl.WValue = 0;
1785: return(kUSBNotFound);
1786:
1787: }
1788:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.