|
|
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: usl.c
27:
28: Contains: USB Services Library source code.
29:
30: Version: Neptune 1.0
31:
32: Copyright: � 1997-1998 by Apple Computer, Inc., all rights reserved.
33:
34: File Ownership:
35:
36: DRI: Barry Twycross
37:
38: Other Contact: xxx put other contact here xxx
39:
40: Technology: USB
41:
42: Writers:
43:
44: (DF) David Ferguson
45: (TC) Tom Clark
46: (BG) Bill Galcher
47: (DKF) David Ferguson
48: (CJK) Craig Keithley
49: (BT) Barry Twycross
50:
51: Change History (most recent first):
52:
53: <USB76> 11/25/98 TC Add calls to USBExpertStatusLevel.
54: <USB75> 11/16/98 BT Mark pipe stalled on allocate to check open pipe is clearing it
55: properly.
56: <USB74> 11/8/98 TC We need to assign a unique DeviceRef for UIM's. So when creating
57: DeviceRefs, don't return one that matches kUIMRefID.
58: <USB73> 11/6/98 TC Formalize parameter names for uslRefToBus.
59: <USB72> 11/6/98 BT ref to bus function
60: <USB71> 10/29/98 BT Close old configurations on reset or reconfiguration.
61: <USB70> 10/21/98 DF Add uslDeviceAddrToBus function
62: <USB69> 10/7/98 BT Fix hub not killing children
63: <USB68> 9/17/98 BT 1.1 rules for captive devices.
64: <USB67> 8/24/98 BT Eliminate old checkPB version, add new one for Isoc
65: <USB66> 8/13/98 BT Add multibus support
66: <USB65> 7/10/98 BT Device zero has a valid ref, delete device deletes mem even
67: after trashing device and ref.
68: <USB64> 7/9/98 BT Fix previous fixes. Device refs can also be validated
69: <USB63> 7/9/98 BT Clean up after delete device and config clash.
70: <USB62> 6/13/98 BT Eliminate V1 param blocks
71: <USB61> 6/10/98 CJK add uslGetDeviceRefByID function (thanks Barry!)
72: <USB60> 6/5/98 BT Delete mem properly in delete device
73: <USB59> 6/5/98 TC Change uxBusRef to USBBusRef.
74: <USB58> 6/3/98 BT Make dispose interface ref able to ignore call back
75: <USB57> 5/21/98 BT Don't initialise redundant firstConf field in dev structure
76: <USB56> 5/20/98 BT Add check for V2 param block function
77: <USB55> 5/19/98 BG Fixed ZeroMem() be a little easier for MrC to swallow.
78: <USB54> 5/17/98 BT Impliment new interface ref correctly, add some functions to
79: support config stuff
80: <USB53> 5/12/98 BT New interface handling
81: <USB52> 5/8/98 BT Add open interface for Tom
82: <USB51> 4/26/98 BT Add pipe state control
83: <USB50> 4/24/98 BT Add clear endpoint stall
84: <USB49> 4/24/98 CJK change string for status message
85: <USB48> 4/21/98 BT Allow requests to device zero, pipe zero.
86: <USB47> 4/20/98 BT Add abort pipe
87: <USB46> 4/16/98 BT Add back UIMpriv prototypes
88: <USB45> 4/15/98 BT Remove redundant diagnostic
89: <USB44> 4/15/98 BT Fix wrong flags check.
90: <USB43> 4/14/98 BT Impliment device remove
91: <USB42> 4/9/98 CJK remove uimpriv.h
92: <USB41> 4/9/98 BT Use USB.h
93: <40> 4/8/98 BT More error checking
94: <39> 4/6/98 BT Change w names
95: <38> 4/6/98 BT New param block names
96: <37> 4/2/98 BT Start on config/interface/endpoint stuff. First caching config
97: descriptors.
98: <36> 3/24/98 BT Record device speed in device structure. (Fixes low speed int
99: pipe problems.)
100: <35> 3/24/98 BT Fix recording of Maxpacketsize
101: <34> 3/19/98 BT Stop double inititialisation
102: <33> 3/19/98 BT Open bulk takes max poacket size in usbValue.
103: <32> 3/18/98 BT Add remove device.
104: <31> 3/5/98 BT Add interrupt pipe
105: <USB30> 2/17/98 DKF Fix a typo in the error codes
106: <29> 2/16/98 BT Direct notifications to expert
107: <28> 2/9/98 BT Add add interface stuff
108: <27> 2/8/98 BT Power Allocation stuff
109: <26> 2/5/98 BT Add status notification stuff
110: <25> 2/4/98 BT Add ref/port info to expert notify]
111: <24> 2/4/98 BT More USBprobe support
112: <23> 2/3/98 BT Fix uslControlPacket to have errors. Add mnore support for
113: usbProbe. Also add USBExpertNotify
114: <22> 2/2/98 BT Add bulk stuff
115: <21> 1/29/98 BT Utility stuff split off
116: <20> 1/26/98 CJK Change to use USBDeviceDescriptor (instead of just
117: deviceDescriptor)
118: <19> 1/26/98 BT Mangle names after design review, finish up
119: <18> 1/26/98 BT Mangle names after design review
120: <17> 1/26/98 BT Make expert notify public
121: <16> 1/26/98 BT Fix status in USB delay function
122: <15> 1/23/98 BT Add USB delay function
123: <14> 1/20/98 BT Increase number of timers
124: <13> 1/19/98 BT Fix race condition
125: <12> 1/15/98 BT Use new USBClassDrivers.h
126: <11> 1/14/98 BT Remove outdated expert stuff
127: <10> 1/13/98 BT User timer services for task time, starting implimenting Int
128: transactions (not finished)
129: <9> 12/23/97 BT Remove obsolete include
130: <8> 12/19/97 BT Add add and remove bus.
131: <7> 12/19/97 BT UIM now a Shared lib
132: <6> 12/18/97 BT Changed expert proc declaratiopn in USLInitialise
133: <5> 12/18/97 BT Fix header dependancies, add expert call back
134: <4> 12/17/97 BT Fix header
135: <3> 12/17/97 BT First checking to BBS
136: */
137:
138:
139:
140: /* ************* Includes ************* */
141: #include "../USB.h"
142: #include "../USBpriv.h"
143: #include "../driverservices.h"
144:
145: #include "uslpriv.h"
146: #include "../uimpriv.h" // This does need to be included. It contains prototypes
147: // Stupid MPW just doesn't tell
148: /*****************************************************************************
149:
150: Data Structures
151:
152: There is an array of devices.
153:
154: Each device entry has information specific to it. It also holds and array of
155: indexes of pipes (open endpoints) for the device.
156:
157: Each open pipe holds information specific to it.
158:
159: Devices are refrenced by device IDs, which are currently an index in tot the
160: devices table in the lower bits and random number in the high bits. This
161: knowledge is kept to a few functions and could be changed.
162:
163: The pipe refs are similarly indexes in to the pipes array.
164:
165: ******************************************************************************/
166:
167: static pipe AllPipes[kUSBMaxPipes];
168: static usbDevice devices[kUSBMaxDevices];
169:
170: enum{
171: kUSBInterfaceShift = 8,
172: kUSBMaxInterface = 1 << kUSBInterfaceShift,
173: kUSBIntefaceMask = kUSBMaxInterface-1
174: };
175: static uslInterface interfaces[kUSBMaxInterface];
176:
177: //static usbDevice *devices;
178:
179: static Boolean initialised;
180:
181:
182: /* ************* CallBack prototyopes. ************* */
183: /* These need to be referenced before the properplace for their definition */
184: static void controlCallBack(
185: UInt32 refcon, /* General Purpose reference supplied by call */
186: OSStatus status, /* normal or error condition */
187: short shortFall); /* how much less than requested transferred */
188:
189:
190:
191:
192: /* ************* Actual Code *************** */
193:
194: /* This doesn't work without length bytes in the strings */
195:
196: OSStatus USBServicesGetVersion(UInt32 ID, VersRec *vers, UInt32 versSize)
197: {
198: #if 0
199: static VersRec ID1=
200: #if kOverrideIndividualVersions
201: {
202: {kPKGHexMajorVers, kPKGHexMinorVers, kPKGCurrentRelease, kPKGReleaseStage},
203: 0, /* Country code */
204: "\p"kPKGStringVersShort, "\p"kPKGStringVers1Long
205:
206: },
207: #else
208: {
209: {kSRVHexMajorVers, kSRVHexMinorVers, kSRVCurrentRelease, kSRVReleaseStage},
210: 0, /* Country code */
211: kMNGRStringVersShort kMNGRStringVers1Long
212:
213: },
214: #endif
215: ID2 = {
216: {kPKGHexMajorVers, kPKGHexMinorVers, kPKGCurrentRelease, kPKGReleaseStage},
217: 0, /* Country code */
218: kPKGStringVersShort kPKGStringVers1Long
219:
220: },
221: *theVers;
222:
223: if( (ID == 0) || (ID > 2) )
224: {
225: return(paramErr);
226: }
227: if(ID == 1)
228: {
229: theVers = &ID1;
230: }
231: else
232: {
233: theVers = &ID2;
234: }
235: if(versSize > sizeof(VersRec) )
236: {
237: versSize = sizeof(VersRec);
238: }
239: usb_BlockMoveData(theVers, vers, versSize);
240: #endif
241: ID = 0;
242: vers = 0;
243: versSize = 0;
244: return(noErr);
245: }
246: /* ******** Interfaces ********** */
247:
248: /* This impliments the arbitrary high bits as a counter. */
249: static USBInterfaceRef MakeInterfaceRef(UInt16 addr)
250: {
251: static long strangeCounter = 0x980508;
252: long shiftedCounter;
253:
254: strangeCounter++;
255: shiftedCounter = strangeCounter << kUSBInterfaceShift;
256: if(shiftedCounter == 0)
257: {
258: shiftedCounter = ++strangeCounter << kUSBInterfaceShift;
259: }
260: return(addr | shiftedCounter | 0x80000000); // high bit is one
261: }
262:
263: /* Given a interfaceRef find the pointer to its structure */
264:
265: OSStatus findInterface(USBInterfaceRef InterfaceRef, uslInterface **p)
266: {
267: InterfacesIdx idx;
268: uslInterface *theInterface;
269:
270: idx = InterfaceRef & kUSBIntefaceMask;
271: theInterface = & interfaces[idx];
272: *p = theInterface;
273: if(theInterface->ref == InterfaceRef)
274: {
275: #if 0
276: if(theInterface->state != kUSBActive)
277: {
278: if(theInterface->state == kUSBIdle)
279: {
280: return(kUSBInterfaceIdleError);
281: }
282: else
283: {
284: return(kUSBInterfaceStalledError);
285: }
286: }
287: #endif
288: return(noErr);
289: }
290: *p = nil;
291: return(kUSBUnknownInterfaceErr);
292: }
293:
294:
295: /* This probably is not the best method for Interfaces */
296: static InterfacesIdx AllocInterfaceIdx(void)
297: {
298: static InterfacesIdx current;
299: InterfacesIdx new;
300: unsigned counted;
301:
302: /* Allocates a Interface. This implimentation has a pointer to */
303: /* the next Interface to be allocated, which is incrimented each */
304: /* time. If that Interface is in use, the list is search linearly */
305: /* from that point for the next free Interface */
306: /* Same as packet allocator */
307:
308: /* Do we need to use atomicTestAndSet for this? */
309: /* Not if transactions are queued */
310:
311: new = current;
312: counted = 0;
313:
314: while(counted < kUSBMaxInterface)
315: {
316: if(interfaces[new].ref == 0) /* Zero not a valid Interface ref */
317: {
318: break;
319: }
320: counted++;
321: new++;
322: if(new > kUSBMaxInterface)
323: {
324: new = 0;
325: }
326:
327: }
328: if(counted < kUSBMaxInterface)
329: {
330: if(counted > 0)
331: {
332: /* maybe keep track of these at some time */
333: }
334: interfaces[new].ref = 0;
335: }
336: else
337: {
338: /* maybe keep track of these at some time */
339: new = -1;
340: }
341:
342: current++;
343: if(current > kUSBMaxInterface)
344: {
345: current = 0;
346: }
347: return(new);
348: }
349:
350: /* Allocate a new Interface structure for the given device and endpoint */
351: uslInterface *AllocInterface(USBDeviceRef device)
352: {
353: long newIdx;
354:
355: newIdx = AllocInterfaceIdx();
356: if(newIdx == -1)
357: {
358: return(nil);
359: }
360: interfaces[newIdx].ref = MakeInterfaceRef(newIdx);
361: interfaces[newIdx].device = device;
362: return(&interfaces[newIdx]);
363: }
364:
365:
366: static void deallocAllDeviceInterfaces(USBDeviceRef ID)
367: {
368: int i;
369: for(i = 0; i<kUSBMaxInterface ; i++)
370: {
371: if(interfaces[i].device == ID)
372: {
373: USBExpertStatusLevel(4, interfaces[i].ref, "USL - Delete undeleted interface", 0);
374:
375: interfaces[i].device = 0;
376: interfaces[i].interfaceNum = 0;
377: interfaces[i].alt = 0;
378: interfaces[i].ref = 0;
379: }
380: }
381:
382:
383: }
384:
385: /* ************* Device Table maintainance internal functions *************/
386: unsigned makeDeviceIdx(USBDeviceRef device)
387: {
388: return(device & kUSBDeviceIDMask);
389: }
390:
391: Boolean uslIsInterfaceRef(USBInterfaceRef interf)
392: {
393: return((interf & 0x80000000) != 0);
394: }
395:
396: usbDevice *getDevicePtrFromIdx(unsigned deviceIndex)
397: {
398: if(deviceIndex > kUSBMaxDevices)
399: {
400: return(nil);
401: }
402: return(&devices[deviceIndex]);
403: }
404:
405: USBDeviceRef uslGetDeviceRefByID(unsigned short deviceID, USBBusRef bus);
406:
407: USBDeviceRef uslGetDeviceRefByID(unsigned short deviceID, USBBusRef bus)
408: {
409: usbDevice *device;
410: if(bus != 1)
411: {
412: return(kUSBUnknownDeviceErr);
413: }
414: device = getDevicePtrFromIdx(deviceID);
415: if(device == nil)
416: {
417: return(kUSBUnknownDeviceErr);
418: }
419: return(device->ID);
420:
421: }
422:
423: usbDevice *getDevicePtr(USBDeviceRef device)
424: {
425: unsigned deviceIndex;
426:
427: if( (device & 0x80000000) != 0)
428: {
429: OSStatus err;
430: uslInterface *intrfc;
431:
432: err = findInterface(device, &intrfc);
433: if(intrfc == nil)
434: {
435: return(nil);
436: }
437: device = intrfc->device;
438: }
439:
440: deviceIndex = makeDeviceIdx(device);
441: if(devices[deviceIndex].ID == device)
442: {
443: return(&devices[deviceIndex]);
444: }
445: return(nil);
446: }
447:
448: OSStatus uslRefToBus(USBReference ref, USBBusRef *bus)
449: {
450: usbDevice *dev;
451: dev = getDevicePtr(ref);
452: if(dev != nil)
453: {
454: if(bus != nil)
455: {
456: *bus = dev->bus;
457: }
458: return(noErr);
459: }
460: else
461: {
462: return(kUSBUnknownDeviceErr);
463: }
464:
465: }
466:
467:
468: /* This one is a prober only hack function */
469: UInt32 uslDeviceAddrToBus(UInt16 addr)
470: {
471: unsigned deviceIndex;
472:
473: for(deviceIndex = 0; deviceIndex < kUSBMaxDevices; deviceIndex++)
474: {
475: if ((devices[deviceIndex].ID != 0) && (devices[deviceIndex].usbAddress == addr))
476: {
477: return(devices[deviceIndex].bus);
478: }
479: }
480: return (0xffff); // indicate that we couldn't find a bus
481: }
482:
483:
484:
485: static void initialiseOneDevice(usbDevice *device)
486: { /* Shared by delete device */
487: device->ID = 0;
488: }
489:
490: static void initialiseDevices(void)
491: {
492: unsigned deviceIndex;
493:
494: for(deviceIndex = 0; deviceIndex < kUSBMaxDevices; deviceIndex++)
495: {
496: initialiseOneDevice(&devices[deviceIndex]);
497: }
498:
499: }
500:
501: UInt8 getNewAddress(void)
502: {
503: static int addr = -1;
504: int counted = 1;
505: if(addr == -1)
506: {
507: AbsoluteTime t;
508: t = UpTime();
509: //naga addr = t.lo & 0x7f;
510: addr = t & 0x7f;
511: }
512: do{
513: addr++;
514: if(addr > 127)
515: {
516: addr = 1;
517: }
518: if(devices[addr].ID == 0)
519: {
520: break;
521: }
522: }while(counted++ <= 127);
523:
524: if(counted > 127)
525: {
526: addr = 0;
527: }
528:
529: USBExpertStatusLevel(4, 0, "USL - New device:", addr); // Paging Mr. Twycross
530: kprintf("****getNewAddress returning addr=%d***\n",addr);
531: return(addr);
532: }
533:
534:
535: /* This impliments the arbitrary high bits as a counter. */
536: USBDeviceRef MakeDevRef(UInt32 bus, UInt16 addr)
537: {
538: static long strangeCounter = 0x090263;
539: long shiftedCounter;
540:
541: strangeCounter++;
542: shiftedCounter = strangeCounter << kUSBDeviceIDShift;
543: if(shiftedCounter == 0)
544: {
545: shiftedCounter = ++strangeCounter << kUSBDeviceIDShift;
546: }
547:
548: bus = 0; // currenty not used.
549: return( (addr + shiftedCounter) & 0x7fffffff); // High bit is zero
550: }
551:
552: /* ************* Pipe Table Maintainance internal functions ************* */
553:
554: /* So that stale pipeRefs can not be reused, the pipe ref is */
555: /* the index into the pipe table (the interesting part) */
556: /* and an arbitrary value stuffing the high bits. */
557: /* A pipe ref is only accepted if it matches the pipeRef */
558: /* stored in the pipe structure. */
559:
560: /* This impliments the arbitrary high bits as a counter. */
561: static USBPipeRef MakePipeRef(long pipeIdx)
562: {
563: static long strangeCounter = 0x230259;
564: long shiftedCounter;
565:
566: strangeCounter++;
567: shiftedCounter = strangeCounter << kUSBMaxPipeIDShift;
568: if(shiftedCounter == 0)
569: {
570: shiftedCounter = ++strangeCounter << kUSBMaxPipeIDShift;
571: }
572: return(pipeIdx + shiftedCounter);
573: }
574:
575: /* Given a pipeRef find the pointer to its structure */
576:
577: OSStatus findPipe(USBPipeRef pipeRef, pipe **p)
578: {
579: pipesIdx idx;
580: pipe *thePipe;
581:
582: idx = pipeRef & kUSBPipeIDMask;
583: thePipe = & AllPipes[idx];
584: *p = thePipe;
585: if(thePipe->ref == pipeRef)
586: {
587: if(thePipe->state != kUSBActive)
588: {
589: if(thePipe->state == kUSBIdle)
590: {
591: return(kUSBPipeIdleError);
592: }
593: else
594: {
595: return(kUSBPipeStalledError);
596: }
597: }
598: return(noErr);
599: }
600: *p = nil; // BT some things rely on this being nil if no pipe, oops.
601: return(kUSBUnknownPipeErr);
602: }
603:
604:
605: /* This probably is not the best method for pipes */
606: static pipesIdx AllocPipeIdx(void)
607: {
608: static pipesIdx current;
609: pipesIdx new;
610: unsigned counted;
611:
612: /* Allocates a pipe. This implimentation has a pointer to */
613: /* the next pipe to be allocated, which is incrimented each */
614: /* time. If that pipe is in use, the list is search linearly */
615: /* from that point for the next free pipe */
616: /* Same as packet allocator */
617:
618: /* Do we need to use atomicTestAndSet for this? */
619: /* Not if transactions are queued */
620:
621: new = current;
622: counted = 0;
623:
624: while(counted < kUSBMaxPipes)
625: {
626: if(AllPipes[new].ref == 0) /* Zero not a valid pipe ref */
627: {
628: break;
629: }
630: counted++;
631: new++;
632: if(new > kUSBMaxPipes)
633: {
634: new = 0;
635: }
636:
637: }
638: if(counted < kUSBMaxPipes)
639: {
640: if(counted > 0)
641: {
642: /* maybe keep track of these at some time */
643: }
644: AllPipes[new].ref = 0;
645: AllPipes[new].state = kUSBStalled; // This is just here to tell me an open pipe forgot to set state
646: }
647: else
648: {
649: /* maybe keep track of these at some time */
650: new = -1;
651: }
652:
653: current++;
654: if(current > kUSBMaxPipes)
655: {
656: current = 0;
657: }
658: return(new);
659: }
660:
661: int makeDevPipeIdx( UInt8 endpoint, UInt8 direction)
662: {
663: int devPipeIdx;
664: devPipeIdx = endpoint-1;
665: if(direction != kUSBOut)
666: {
667: devPipeIdx += kUSBMaxEndptPerDevice/2;
668: }
669: return(devPipeIdx);
670: }
671:
672: /* Given a device and an endpoint, wheres the pipe? */
673: pipe *getPipe(usbDevice *device, UInt8 endpoint, UInt8 direction)
674: {
675: pipesIdx index;
676: index = device->pipes[makeDevPipeIdx(endpoint, direction)];
677: if(index == -1)
678: {
679: return(nil);
680: }
681: else
682: {
683: return(&AllPipes[index]);
684: }
685: }
686:
687: pipe *getPipeByIdx(pipesIdx idx)
688: {
689: if(idx > kUSBMaxPipes)
690: {
691: return(nil);
692: }
693:
694: return(&AllPipes[idx]);
695:
696: }
697:
698: /* Allocate a new pipe structure for the given device and endpoint */
699: pipe *AllocPipe(usbDevice *device, UInt8 endpoint, UInt8 direction)
700: {
701: long newIdx;
702:
703: newIdx = AllocPipeIdx();
704: if(newIdx == -1)
705: {
706: return(nil);
707: }
708: device->pipes[makeDevPipeIdx(endpoint, direction)] = newIdx;
709: AllPipes[newIdx].ref = MakePipeRef(newIdx);
710: return(&AllPipes[newIdx]);
711: }
712:
713:
714: /* XXXXXXXX More to be done */
715: void deallocPipe(usbDevice *device, UInt8 endpoint, UInt8 direction)
716: {
717: pipesIdx index;
718: int devPipeIdx;
719:
720: devPipeIdx = makeDevPipeIdx(endpoint, direction);
721: index = device->pipes[devPipeIdx];
722: AllPipes[index].ref = 0;
723: AllPipes[index].state = kUSBStalled; // This is just here to tell me an open pipe forgot to set state
724: device->pipes[devPipeIdx] = -1;
725: }
726:
727:
728: OSStatus uslClosePipe(pipesIdx pipe)
729: {
730: OSStatus err;
731: if(pipe == -1)
732: {
733: return(noErr);
734: }
735: if(AllPipes[pipe].type == kUSBControl)
736: {
737: kprintf("uslClosePipe:calling UIMControlEDDelete\n");
738: err = UIMControlEDDelete(AllPipes[pipe].bus, AllPipes[pipe].devAddress, AllPipes[pipe].endPt);
739: }
740: else
741: {
742: err = UIMEDDelete(AllPipes[pipe].bus, AllPipes[pipe].devAddress, AllPipes[pipe].endPt, AllPipes[pipe].direction);
743: }
744:
745: AllPipes[pipe].ref = 0;
746: AllPipes[pipe].state = kUSBStalled; // This is just here to tell me an open pipe forgot to set state
747: return(noErr);
748: }
749:
750: void uslCloseNonDefaultPipes(usbDevice *deviceP)
751: {
752: int i;
753: for(i = 0; i< kUSBMaxEndptPerDevice; i++)
754: {
755: uslClosePipe(deviceP->pipes[i]);
756: deviceP->pipes[i] = -1;
757: }
758: }
759:
760: void uslCloseInterfacePipes(USBInterfaceRef iRef, usbDevice *deviceP)
761: {
762: int i;
763: for(i = 0; i< kUSBMaxEndptPerDevice; i++)
764: {
765: if(AllPipes[deviceP->pipes[i]].devIntfRef == iRef)
766: {
767: uslClosePipe(deviceP->pipes[i]);
768: deviceP->pipes[i] = -1;
769: }
770: }
771: }
772:
773:
774: OSStatus validateRef(USBReference ref, UInt32 *bus)
775: {
776: OSStatus err;
777: usbDevice *dev;
778: pipe *p;
779:
780: dev = getDevicePtr(ref);
781: if(dev != nil)
782: {
783: if(bus != nil)
784: {
785: *bus = dev->bus;
786: }
787: return(noErr);
788: }
789: err = findPipe(ref, &p);
790: if(p != nil)
791: {
792: if(bus != nil)
793: {
794: *bus = p->bus;
795: }
796: return(noErr);
797: }
798: if(uslHubValidateDevZero(ref, bus))
799: {
800: return(noErr);
801: }
802: USBExpertStatusLevel(2, ref, "USL - Invalid ref passed to USL", 0);
803:
804: return(kUSBUnknownDeviceErr);
805: }
806:
807: Boolean isSameDevice(USBReference ref, USBDeviceRef devRef)
808: { // true if the ref refers to the device
809: usbDevice *dev;
810: OSStatus err;
811: pipe *p;
812:
813: dev = getDevicePtr(ref);
814: if(dev == nil)
815: {
816: err = findPipe(ref, &p);
817: if(p == nil)
818: {
819: return(false);
820: }
821:
822: dev = getDevicePtr(p->devIntfRef);
823: }
824: if(dev != nil)
825: {
826: if(dev->ID == devRef)
827: {
828: return(true);
829: }
830: }
831: return(false);
832: }
833:
834: static void ZeroMem(void *addr, UInt32 len)
835: {
836: UInt8 *byteAddr;
837:
838: if(len == 0)
839: return;
840:
841: byteAddr = (UInt8 *) addr;
842: while(len--)
843: {
844: *byteAddr++ = 0;
845: }
846: }
847:
848:
849: void uslUnconfigureDevice(usbDevice *device)
850: {
851: uslCloseNonDefaultPipes(device);
852: deallocAllDeviceInterfaces(device->ID);
853: device->currentConfiguration = 0;
854: }
855:
856: OSStatus uslDeleteDevice(USBPB *pb, usbDevice *device)
857: { /* All pipes are closed, kill off the device */
858: OSStatus retVal = noErr;
859: void *allConfDesc;
860:
861: if(device->configLock != 0)
862: {
863: USBExpertStatusLevel(2, device->ID, "USL - Device busy when deleting: Address ==", device->usbAddress);
864: device->killMe = true;
865: if(device->configLock != 0)
866: { // Make sure it hasn't been asynchronously unlocked
867: return(noErr);
868: }
869: USBExpertStatusLevel(2, device->ID, "USL - Device no longer busy: Address ==", device->usbAddress);
870: }
871:
872: USBExpertStatusLevel(4, 0, "USL - Deleting device: Address ==", device->usbAddress);
873:
874: allConfDesc = device->allConfigDescriptors;
875:
876: deallocAllDeviceInterfaces(device->ID);
877:
878: /* Zero out the structure, not strictly necessary, but prudent */
879: /* This bit relies on allConfigDescriptors being the second field after ID */
880: ZeroMem(&device->allConfigDescriptors, sizeof(usbDevice)-OFFSET(usbDevice, allConfigDescriptors));
881:
882: initialiseOneDevice(device);
883:
884: if(allConfDesc != nil)
885: {
886: if(CurrentExecutionLevel() != kTaskLevel)
887: {
888: if(pb->usbCompletion == kUSBNoCallBack)
889: {
890: retVal = kUSBCompletionError;
891: }
892: else
893: {
894: pb->usbBuffer = allConfDesc;
895: retVal = kUSBPending;
896: uslDeallocMem(pb);
897: }
898: }
899: else
900: {
901: PoolDeallocate(device->allConfigDescriptors);
902: }
903: }
904:
905: return(retVal);
906: }
907:
908:
909: /* Given a pipeRef, whats the pipe index? */
910: long recoverPipeIdx(USBPipeRef pipeRef)
911: {
912: if(pipeRef == 0)
913: {
914: return(-1);
915: }
916:
917: return(pipeRef & kUSBPipeIDMask);
918: }
919:
920:
921: /* GIven a pipeRef, find the pipe structure */
922: pipe *GetPipePtr(USBPipeRef pipeRef)
923: {
924: pipe *retPipe = nil;
925: long pipeIdx;
926: do{
927: pipeIdx = recoverPipeIdx(pipeRef);
928: if(pipeIdx == -1)
929: {
930: break;
931: }
932:
933: retPipe = &AllPipes[pipeIdx];
934:
935: if(pipeRef != retPipe->ref)
936: {
937: retPipe = nil;
938: break;
939: }
940:
941: }while(0);
942:
943: return(retPipe);
944: }
945:
946: /* Mark all pipes unused */
947: static void initialisePipes(void)
948: {
949: long index, index2;
950:
951: /* Mark all pipes close */
952: for(index = 0; index < kUSBMaxDevices; index++)
953: {
954: for(index2 = 0; index2 < kUSBMaxEndptPerDevice; index2++)
955: {
956: devices[index].pipes[index2] = -1;
957: }
958: }
959:
960:
961: }
962: #define kUIMRefID 0x061563
963: /* This needs to take account of bus in some manner */
964: USBDeviceRef addNewDevice(UInt32 bus, UInt16 addr, UInt8 speed, UInt8 maxPacket, UInt32 power)
965: {
966: USBDeviceRef new;
967: usbDevice *dev;
968: long pipeIdx;
969: pipe *pipe0;
970:
971: new = 0;
972:
973: do{ /* for error checking */
974:
975: if( (addr == 0) || (addr > kUSBMaxDevice) )
976: {
977: break;
978: }
979:
980: if(UIMControlEDCreate(bus, addr, 0, maxPacket, speed) != noErr)
981: {
982: break;
983: }
984:
985:
986: dev = &devices[addr];
987: if(dev->ID != 0)
988: {
989: break;
990: }
991:
992: do
993: {
994: new = MakeDevRef(bus, addr);
995: }while (new == kUIMRefID);
996:
997: dev->bus = bus;
998: dev->ID = new;
999: dev->usbAddress = addr;
1000: dev->speed = speed;
1001: dev->powerAvailable = power;
1002: USBExpertStatusLevel(4, dev->ID, "USL - New device power:", power);
1003:
1004: pipeIdx = AllocPipeIdx();
1005: if(pipeIdx == -1)
1006: {
1007: break;
1008: }
1009: dev->pipe0 = pipeIdx;
1010: pipe0 = &AllPipes[pipeIdx];
1011:
1012: /* this is repeated with open control endpoint. Should be consolodated */
1013: pipe0->bus = bus;
1014: pipe0->devIntfRef = new;
1015: pipe0->endPt = 0;
1016: pipe0->ref = MakePipeRef(pipeIdx);
1017: pipe0->devAddress = addr;
1018: pipe0->type = kUSBControl;
1019: pipe0->state = kUSBActive;
1020: for(pipeIdx = 0; pipeIdx < kUSBMaxEndptPerDevice; pipeIdx++)
1021: {
1022: dev->pipes[pipeIdx] = -1;
1023: }
1024:
1025: }while(0);
1026:
1027: return(new);
1028: }
1029:
1030:
1031:
1032: /* ************* Functions dealing with transactions ************* */
1033:
1034: /* Each pipe has a number of possible transactions outstanding */
1035: /* on it at one time. The pipe structure has 2 tables one of the */
1036: /* UIM transaction ref for these and another parallel one which */
1037: /* has the index of the packet its using */
1038:
1039:
1040:
1041: /* ************* Actual Functions ************* */
1042:
1043:
1044:
1045:
1046:
1047: USBPipeRef getPipeZero(USBDeviceRef device)
1048: {
1049: usbDevice *deviceP;
1050: pipesIdx pipe0Idx;
1051: USBPipeRef retVal = 0;
1052:
1053: /* Validate device */
1054: deviceP = getDevicePtr(device);
1055:
1056: if(deviceP == nil)
1057: {
1058: return(0);
1059: }
1060: pipe0Idx = deviceP->pipe0;
1061: if( (pipe0Idx < 0) || (pipe0Idx > kUSBMaxPipes) )
1062: {
1063: return(0);
1064: }
1065: return(AllPipes[pipe0Idx].ref);
1066: }
1067:
1068:
1069: OSStatus USBServicesInitialise(void *exProc)
1070: {
1071: kprintf("***USBServicesInitialize:calling severel inits***\n");
1072: if(initialised)
1073: {
1074: return(kUSBAlreadyOpenErr);
1075: }
1076: SetExpertFunction(exProc);
1077:
1078: initialiseDevices();
1079: initialisePipes();
1080: initialiseHubs();
1081: initialiseDelays();
1082: initialiseNotifications();
1083:
1084: initialised = true;
1085:
1086: return(noErr);
1087: }
1088:
1089: void USBServicesFinalise(void)
1090: {
1091: if(!initialised)
1092: {
1093: return;//(paramErr);
1094: }
1095: finaliseHubs();
1096: finaliseDelays();
1097: finaliseNotifications();
1098:
1099: initialised = false;
1100: }
1101:
1102:
1103: Boolean checkPBVersionIsoc(USBPB *pb, UInt32 flags)
1104: {
1105: if( ( (pb->pbVersion == 0x109) || (pb->pbVersion == 0x109) )&&
1106: (pb->pbLength >= sizeof(USBPB)) &&
1107: ( (pb->usbCompletion != nil) && (pb->usbCompletion != (void *)-1) ) &&
1108: ((pb->usbFlags & ~flags) == 0) )
1109: {
1110: pb->usbStatus = noErr;
1111: return(true);
1112: }
1113: else
1114: {
1115: if((pb->pbVersion != 0x109) && (pb->pbVersion != 0x109) )
1116: {
1117: USBExpertStatusLevel(2, pb->usbReference, "USL error - Bad param block version", pb->pbVersion);
1118: pb->usbStatus = kUSBPBVersionError;
1119: }
1120: else if(pb->pbLength < sizeof(USBPB))
1121: {
1122: USBExpertStatusLevel(2, pb->usbReference, "USL error - small param block version", pb->pbLength);
1123: pb->usbStatus = kUSBPBLengthError;
1124: }
1125: else if( (pb->usbCompletion == nil) || (pb->usbCompletion == (void *)-1) )
1126: {
1127: USBExpertStatusLevel(2, pb->usbReference, "USL error - bad completion function", (UInt32)pb->usbCompletion);
1128: pb->usbStatus = kUSBCompletionError;
1129: }
1130: else if((pb->usbFlags & ~flags) != 0)
1131: {
1132: USBExpertStatusLevel(2, pb->usbReference, "USL error - bad flags", pb->usbFlags & ~flags);
1133: pb->usbStatus = kUSBFlagsError;
1134: }
1135: else
1136: {
1137: USBExpertStatusLevel(2, pb->usbReference, "USL error - What??", 0);
1138: pb->usbStatus = paramErr;
1139: }
1140: return(false);
1141: }
1142: }
1143:
1144: Boolean checkPBVersion(USBPB *pb, UInt32 flags)
1145: {
1146: if( ( (pb->pbVersion == 2) || (pb->pbVersion == 0x100) || (pb->pbVersion == 0x109))&&
1147: (pb->pbLength >= sizeof(USBPB)) &&
1148: ( (pb->usbCompletion != nil) && (pb->usbCompletion != (void *)-1) ) &&
1149: ((pb->usbFlags & ~flags) == 0) )
1150: {
1151: pb->usbStatus = noErr;
1152: return(true);
1153: }
1154: else
1155: {
1156: if((pb->pbVersion != 2) && (pb->pbVersion != 0x100) && (pb->pbVersion != 0x109) )
1157: {
1158: USBExpertStatusLevel(2, pb->usbReference, "USL error - Bad param block version", pb->pbVersion);
1159: pb->usbStatus = kUSBPBVersionError;
1160: }
1161: else if(pb->pbLength < sizeof(USBPB))
1162: {
1163: USBExpertStatusLevel(2, pb->usbReference, "USL error - small param block version", pb->pbLength);
1164: pb->usbStatus = kUSBPBLengthError;
1165: }
1166: else if( (pb->usbCompletion == nil) || (pb->usbCompletion == (void *)-1) )
1167: {
1168: USBExpertStatusLevel(2, pb->usbReference, "USL error - bad completion function", (UInt32)pb->usbCompletion);
1169: pb->usbStatus = kUSBCompletionError;
1170: }
1171: else if((pb->usbFlags & ~flags) != 0)
1172: {
1173: USBExpertStatusLevel(2, pb->usbReference, "USL error - bad flags", pb->usbFlags & ~flags);
1174: pb->usbStatus = kUSBFlagsError;
1175: }
1176: else
1177: {
1178: USBExpertStatusLevel(2, pb->usbReference, "USL error - What??", 0);
1179: pb->usbStatus = paramErr;
1180: }
1181: return(false);
1182: }
1183: }
1184:
1185:
1186:
1187: UInt8 USBMakeBMRequestType(USBDirection direction, USBRqType type, USBRqRecipient recipient)
1188: {
1189: UInt8 rq = 0xff;
1190: do{
1191: if(direction == kUSBNone)
1192: {
1193: direction = kUSBOut;
1194: }
1195: if(direction != kUSBOut && direction != kUSBIn)
1196: {
1197: break;
1198: }
1199: if(type < kUSBStandard || type > kUSBVendor)
1200: {
1201: break;
1202: }
1203: if(recipient < kUSBDevice || recipient > kUSBOther)
1204: {
1205: break;
1206: }
1207:
1208: rq = recipient + (type << kUSBRqTypeShift) + (direction << kUSBRqDirnShift);
1209:
1210: }while(0);
1211: return(rq);
1212: }
1213:
1214:
1215:
1216: OSStatus USBDisposeInterfaceRef(USBPB *pb)
1217: {
1218: // --> usbReference --> interface
1219: OSStatus err;
1220: uslInterface *intfrc;
1221: Boolean nocallBack = false;
1222:
1223: if(pb->usbCompletion == kUSBNoCallBack)
1224: {
1225: nocallBack = true;
1226: pb->usbCompletion = (void *)-2;
1227: }
1228:
1229: if(!checkPBVersion(pb, 0))
1230: {
1231: return(pb->usbStatus);
1232: }
1233: err = findInterface(pb->usbReference, &intfrc);
1234: if(intfrc == nil)
1235: {
1236: USBExpertStatusLevel(4, pb->usbReference, "USL - Interface to dispose not found", 0);
1237: return(kUSBUnknownInterfaceErr);
1238: }
1239: intfrc->device = 0;
1240: intfrc->interfaceNum = 0;
1241: intfrc->alt = 0;
1242: intfrc->ref = 0;
1243:
1244: if(nocallBack)
1245: {
1246: pb->usbCompletion = kUSBNoCallBack;
1247: }
1248: else
1249: {
1250: (*pb->usbCompletion)(pb);
1251: }
1252: return(kUSBPending);
1253: }
1254:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.