|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * HISTORY ! 26: * 08 Dec 98 ehewitt created. ! 27: * ! 28: */ ! 29: ! 30: #include <libkern/OSByteOrder.h> ! 31: ! 32: #include <libkern/c++/OSDictionary.h> ! 33: #include <IOKit/IOMemoryDescriptor.h> ! 34: #include <libkern/c++/OSData.h> ! 35: ! 36: #include <IOKit/usb/USB.h> ! 37: #include <IOKit/usb/IOUSBController.h> ! 38: #include <IOKit/usb/IOUSBNub.h> ! 39: #include <IOKit/usb/IOUSBPipe.h> ! 40: ! 41: #include "IOUSBUserClient.h" ! 42: #include "IOUSBHub.h" ! 43: ! 44: static int devdebug = 0; ! 45: #define DEBUGLOG if (devdebug) kprintf ! 46: ! 47: static const IOUSBDescriptorHeader *nextDescriptor(const void *desc) ! 48: { ! 49: const UInt8 *next = (const UInt8 *)desc; ! 50: UInt8 length = next[0]; ! 51: next = &next[length]; ! 52: return((const IOUSBDescriptorHeader *)next); ! 53: } ! 54: ! 55: const IOUSBDescriptorHeader * ! 56: IOUSBNub::findNextDescriptor(const void *cur, UInt8 descType) ! 57: { ! 58: const IOUSBDescriptorHeader *hdr; ! 59: hdr = (const IOUSBDescriptorHeader *)cur; ! 60: do { ! 61: hdr = nextDescriptor(hdr); ! 62: if(hdr->length == 0) ! 63: break; ! 64: if(descType == 0) ! 65: return hdr; // type 0 is wildcard. ! 66: else if(hdr->descriptorType == descType) ! 67: return hdr; ! 68: } ! 69: while(true); ! 70: ! 71: return NULL; // Fell off end of list ! 72: } ! 73: ! 74: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 75: ! 76: OSDefineMetaClass( IOUSBNub, IOService ) ! 77: OSDefineAbstractStructors(IOUSBNub, IOService) ! 78: ! 79: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 80: ! 81: bool IOUSBNub::init(OSDictionary * propTable) ! 82: { ! 83: OSData * addressProperty; ! 84: OSData * descProperty; ! 85: OSData * powerProperty; ! 86: OSData * speedProperty; ! 87: ! 88: if( !IOService::init(propTable)) ! 89: return (false); ! 90: ! 91: addressProperty = (OSData *) propTable->getObject("device address"); ! 92: descProperty = (OSData *) propTable->getObject("device descriptor"); ! 93: powerProperty = (OSData *) propTable->getObject("bus power available"); ! 94: speedProperty = (OSData *) propTable->getObject("low speed device"); ! 95: if (!addressProperty || !powerProperty || !speedProperty || !descProperty) ! 96: { ! 97: IOLog("%s: Unable to initialize\n", getName()); ! 98: return (false); ! 99: } ! 100: _address = *((USBDeviceAddress *) addressProperty->getBytesNoCopy()); ! 101: ! 102: bcopy(descProperty->getBytesNoCopy(), &_descriptor, ! 103: descProperty->getLength()); ! 104: ! 105: _busPowerAvailable = *((UInt32 *) powerProperty->getBytesNoCopy()); ! 106: _speed = *((UInt8 *) speedProperty->getBytesNoCopy()); ! 107: DEBUGLOG("%s @ %d (%ldmA available, %s speed)\n", getName(), _address,_busPowerAvailable*2, _speed ? "low" : "high"); ! 108: ! 109: #if (devdebug > 0) ! 110: printDeviceDescriptor(&_descriptor); ! 111: #endif ! 112: ! 113: return (true); ! 114: } ! 115: ! 116: bool IOUSBNub::finalize(IOOptionBits options) ! 117: { ! 118: if(_pipeZero) { ! 119: _pipeZero->release(); ! 120: _pipeZero = NULL; ! 121: } ! 122: return(IOService::finalize(options)); ! 123: } ! 124: ! 125: USBDeviceAddress IOUSBNub::address(void) ! 126: { ! 127: return(_address); ! 128: } ! 129: ! 130: const IOUSBDeviceDescriptor * IOUSBNub::deviceDescriptor(void) ! 131: { ! 132: return(&_descriptor); ! 133: } ! 134: ! 135: IOUSBController * IOUSBNub::bus(void) ! 136: { ! 137: return(_controller); ! 138: } ! 139: ! 140: UInt32 IOUSBNub::busPowerAvailable( void ) ! 141: { ! 142: return(_busPowerAvailable); ! 143: } ! 144: ! 145: IOUSBPipe * IOUSBNub::pipeZero() ! 146: { ! 147: return _pipeZero; ! 148: } ! 149: ! 150: // Lowlevel requests for non-standard device requests ! 151: IOReturn IOUSBNub::deviceRequest(IOUSBDevRequest *request, ! 152: IOUSBCompletion *completion = 0) ! 153: { ! 154: UInt16 theRequest; ! 155: theRequest = EncodeRequest(request->bRequest, request->rqDirection, ! 156: request->rqType, request->rqRecipient); ! 157: if (theRequest == kSetAddress) { ! 158: DEBUGLOG("\tignoring kSetAddress\n"); ! 159: return kIOReturnNotPermitted; ! 160: } ! 161: return(_pipeZero->controlRequest(request, completion)); ! 162: } ! 163: ! 164: IOReturn IOUSBNub::deviceRequest(IOUSBDevRequestDesc *request, ! 165: IOUSBCompletion *completion = 0) ! 166: { ! 167: UInt16 theRequest; ! 168: theRequest = EncodeRequest(request->bRequest, request->rqDirection, ! 169: request->rqType, request->rqRecipient); ! 170: if (theRequest == kSetAddress) { ! 171: DEBUGLOG("\tignoring kSetAddress\n"); ! 172: return kIOReturnNotPermitted; ! 173: } ! 174: return(_pipeZero->controlRequest(request, completion)); ! 175: } ! 176: ! 177: ! 178: IOReturn IOUSBNub::GetConfiguration(UInt8 *configNumber) ! 179: { ! 180: IOReturn err = kIOReturnSuccess; ! 181: IOUSBDevRequest request; ! 182: ! 183: DEBUGLOG("************ GET CONFIGURATION *************\n"); ! 184: ! 185: request.rqDirection = kUSBIn; ! 186: request.rqType = kUSBStandard; ! 187: request.rqRecipient = kUSBDevice; ! 188: request.bRequest = kUSBRqGetConfig; ! 189: OSWriteLittleInt16(&request.wValue, 0, 0); ! 190: OSWriteLittleInt16(&request.wIndex, 0, 0); ! 191: OSWriteLittleInt16(&request.wLength, 0, sizeof(*configNumber)); ! 192: request.pData = configNumber; ! 193: ! 194: err = deviceRequest(&request); ! 195: ! 196: if (err) ! 197: { ! 198: DEBUGLOG("%s: error getting config. err=%d\n", getName(), err); ! 199: } ! 200: ! 201: return(err); ! 202: } ! 203: ! 204: IOReturn IOUSBNub::GetDeviceStatus(USBStatus *status) ! 205: { ! 206: IOReturn err = kIOReturnSuccess; ! 207: IOUSBDevRequest request; ! 208: ! 209: DEBUGLOG("*********** GET DEVICE STATUS ***********\n"); ! 210: ! 211: request.rqDirection = kUSBIn; ! 212: request.rqType = kUSBStandard; ! 213: request.rqRecipient = kUSBDevice; ! 214: request.bRequest = kUSBRqGetStatus; ! 215: OSWriteLittleInt16(&request.wValue, 0, 0); ! 216: OSWriteLittleInt16(&request.wIndex, 0, 0); ! 217: OSWriteLittleInt16(&request.wLength, 0, sizeof(*status)); ! 218: request.pData = status; ! 219: ! 220: err = deviceRequest(&request); ! 221: ! 222: if (err) ! 223: IOLog("%s: error getting device status. err=%d\n", getName(), err); ! 224: ! 225: return(err); ! 226: } ! 227: ! 228: IOReturn IOUSBNub::GetStringDescriptor(UInt8 index, ! 229: char *buf, int maxLen, UInt16 lang) ! 230: { ! 231: IOReturn err; ! 232: UInt8 desc[256]; // Max possible descriptor length ! 233: IOUSBDevRequest request; ! 234: int i, len; ! 235: ! 236: DEBUGLOG("*********** GET STRING DESCRIPTOR %d, lang 0x%x***********\n", index, lang); ! 237: ! 238: // First get actual length (lame devices don't like being asked for too much data) ! 239: request.rqDirection = kUSBIn; ! 240: request.rqType = kUSBStandard; ! 241: request.rqRecipient = kUSBDevice; ! 242: request.bRequest = kUSBRqGetDescriptor; ! 243: OSWriteLittleInt16(&request.wValue, 0, (kUSBStringDesc << 8) | index); ! 244: OSWriteLittleInt16(&request.wIndex, 0, lang); ! 245: ! 246: OSWriteLittleInt16(&request.wLength, 0, 2); ! 247: bzero(desc, 2); ! 248: request.pData = &desc; ! 249: ! 250: err = deviceRequest(&request); ! 251: ! 252: if (err != kIOReturnSuccess) ! 253: return(err); ! 254: ! 255: request.rqDirection = kUSBIn; ! 256: request.rqType = kUSBStandard; ! 257: request.rqRecipient = kUSBDevice; ! 258: request.bRequest = kUSBRqGetDescriptor; ! 259: len = desc[0]; ! 260: if(len == 0) ! 261: len = sizeof(desc); // Silly result for small read, try big one. ! 262: OSWriteLittleInt16(&request.wValue, 0, (kUSBStringDesc << 8) | index); ! 263: OSWriteLittleInt16(&request.wIndex, 0, lang); ! 264: OSWriteLittleInt16(&request.wLength, 0, len); ! 265: request.pData = &desc; ! 266: ! 267: err = deviceRequest(&request); ! 268: ! 269: if (err != kIOReturnSuccess) ! 270: return(err); ! 271: DEBUGLOG("*********** Got STRING DESCRIPTOR %d, length 0x%x, got 0x%x***********\n", ! 272: index, desc[0], OSReadLittleInt16(&request.wLength, 0)); ! 273: len = (desc[0]-2)/2; ! 274: if(len > maxLen-1) ! 275: len = maxLen-1; ! 276: for(i=0; i<len; i++) ! 277: buf[i] = desc[2*i+2]; ! 278: buf[len] = 0; ! 279: ! 280: return kIOReturnSuccess; ! 281: } ! 282: ! 283: UInt32 IOUSBNub::GetBandwidthAvailable() ! 284: { ! 285: return _controller->GetBandwidthAvailable(); ! 286: } ! 287: ! 288: UInt64 IOUSBNub::GetFrameNumber() ! 289: { ! 290: return _controller->GetFrameNumber(); ! 291: } ! 292: ! 293: /** ! 294: ** Matching methods ! 295: **/ ! 296: bool IOUSBNub::matchPropertyTable(OSDictionary * table) ! 297: { ! 298: // ! 299: // If the service object wishes to compare some of its properties in its ! 300: // property table against the supplied matching dictionary, ! 301: // it should do so in this method and return truth on success. ! 302: // ! 303: ! 304: if (!IOService::matchPropertyTable(table)) return false; ! 305: ! 306: // We return success if the following expression is true -- individual ! 307: // comparisions evaluate to truth if the named property is not present ! 308: // in the supplied matching dictionary. ! 309: ! 310: return compareProperty(table, "class") && ! 311: compareProperty(table, "subClass") && ! 312: compareProperty(table, "protocol") && ! 313: compareProperty(table, "vendor") && ! 314: compareProperty(table, "product") && ! 315: compareProperty(table, "version"); ! 316: } ! 317: ! 318: #ifdef __cplusplus ! 319: extern "C" { ! 320: #endif ! 321: ! 322: void printDescriptor(IOUSBDescriptorHeader *desc) ! 323: { ! 324: if (!desc) ! 325: return; ! 326: ! 327: switch (desc->descriptorType) ! 328: { ! 329: case kUSBDeviceDesc: ! 330: printDeviceDescriptor((IOUSBDeviceDescriptor *)desc); break; ! 331: case kUSBConfDesc: ! 332: printConfigDescriptor((IOUSBConfigurationDescriptor *)desc); break; ! 333: case kUSBInterfaceDesc: ! 334: printInterfaceDescriptor((IOUSBInterfaceDescriptor *)desc); break; ! 335: case kUSBEndpointDesc: ! 336: printEndpointDescriptor((IOUSBEndpointDescriptor *)desc); break; ! 337: default: ! 338: DEBUGLOG("printDescriptor: unknown descriptor type (%d)\n", ! 339: desc->descriptorType); ! 340: ! 341: } ! 342: } ! 343: ! 344: // for debugging. Should print generic ! 345: // descriptor based on descriptor type. ! 346: void printDeviceDescriptor(IOUSBDeviceDescriptor *desc) ! 347: { ! 348: if (!desc) ! 349: return; ! 350: ! 351: DEBUGLOG("device descriptor: v0x%x (%d bytes) type = %d %d configs\n", ! 352: OSReadLittleInt16(&desc->usbRel, 0), desc->length, desc->descType, ! 353: desc->numConf); ! 354: DEBUGLOG("\tclass = [%d:%d:%d] maxPacketSize = %d\n", desc->deviceClass, ! 355: desc->deviceSubClass, desc->protocol, desc->maxPacketSize); ! 356: DEBUGLOG("\tvendor = [%x:%x:%x] idx's = [%d:%d:%d]\n", ! 357: OSReadLittleInt16(&desc->vendor, 0), USBToHostWord(desc->product), ! 358: OSReadLittleInt16(&desc->devRel, 0), desc->manuIdx, desc->prodIdx, ! 359: desc->serialIdx); ! 360: } ! 361: ! 362: // for debugging -- nothing yet. Should print generic ! 363: // descriptor based on descriptor type. ! 364: void printConfigDescriptor(IOUSBConfigurationDescriptor *cd) ! 365: { ! 366: void *end; ! 367: const IOUSBDescriptorHeader *dp; ! 368: ! 369: if (!cd) ! 370: return; ! 371: ! 372: DEBUGLOG("CONFIG #%d: (%d bytes) T(%d bytes) ", ! 373: cd->configValue, cd->length, OSReadLittleInt16(&cd->totalLength, 0)); ! 374: DEBUGLOG("descType = %d numInterfaces = %d ", ! 375: cd->descriptorType, cd->numInterfaces); ! 376: DEBUGLOG("attributes = %d maxPower = %d\n", ! 377: cd->attributes, cd->maxPower); ! 378: ! 379: end = (void *)(((UInt8 *)cd) + OSReadLittleInt16(&cd->totalLength, 0)); ! 380: dp = nextDescriptor((const IOUSBDescriptorHeader *)cd); ! 381: ! 382: while(dp < end) ! 383: { ! 384: if (dp->descriptorType == kUSBInterfaceDesc) ! 385: printInterfaceDescriptor((IOUSBInterfaceDescriptor *)dp); ! 386: else if (dp->descriptorType == kUSBEndpointDesc) ! 387: printEndpointDescriptor((IOUSBEndpointDescriptor *)dp); ! 388: else ! 389: DEBUGLOG("Unknown descriptor type %d\n", dp->descriptorType); ! 390: ! 391: dp = nextDescriptor(dp); ! 392: } ! 393: } ! 394: ! 395: void printInterfaceDescriptor(IOUSBInterfaceDescriptor *id) ! 396: { ! 397: if (!id) ! 398: return; ! 399: ! 400: DEBUGLOG("INTERFACE #%d/%d: (%d bytes) type = %d ", ! 401: id->interfaceNumber, id->alternateSetting, id->length, ! 402: id->descriptorType); ! 403: DEBUGLOG("class = [%d:%d:%d] numEndpoints = %d\n", id->interfaceClass, ! 404: id->interfaceSubClass, id->interfaceProtocol, id->numEndpoints); ! 405: } ! 406: ! 407: void printEndpointDescriptor(IOUSBEndpointDescriptor *ed) ! 408: { ! 409: char *eType[] = { "control", "isochronous", "bulk", "interrupt" }; ! 410: if (!ed) ! 411: return; ! 412: ! 413: DEBUGLOG("ENDPOINT #%x (%s): (%d bytes, type %d) type = %d (%s) ", ! 414: ed->endpointAddress & 0x0F, ed->endpointAddress & 0x80 ? "in" : "out", ! 415: ed->length, ed->descriptorType, ed->attributes & 0x03, ! 416: eType[ed->attributes & 0x03]); ! 417: DEBUGLOG("interval = %dms maxPacketSize = %d\n", ! 418: ed->interval, OSReadLittleInt16(&ed->maxPacketSizeLo, 0)); ! 419: } ! 420: ! 421: #ifdef __cplusplus ! 422: } ! 423: #endif ! 424:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.