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