Annotation of XNU/iokit/Families/IOUSBBus/IOUSBNub.cpp, revision 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.