Annotation of XNU/iokit/Families/IOUSBBus/IOUSBNub.cpp, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.