|
|
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.