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