Annotation of XNU/iokit/Families/IOUSBBus/IOUSBDevice.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/IOUSBDevice.h>
                     39: #include <IOKit/usb/IOUSBInterface.h>
                     40: #include <IOKit/usb/IOUSBPipe.h>
                     41: 
                     42: #include "IOUSBUserClient.h"
                     43: #include "IOUSBHub.h"
                     44: 
                     45: #define super IOUSBNub
                     46: 
                     47: static int devdebug = 0;
                     48: #define DEBUGLOG if (devdebug) kprintf
                     49: 
                     50: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     51: 
                     52: OSDefineMetaClassAndStructors(IOUSBDevice, IOUSBNub)
                     53: 
                     54: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     55: 
                     56: void IOUSBDevice::setPort(IOUSBHubPort *port)
                     57: {
                     58:     _port = port;
                     59: }
                     60: 
                     61: bool IOUSBDevice::init(OSDictionary * propTable)
                     62: {
                     63:     if(!IOUSBNub::init(propTable))
                     64:        return false;
                     65:     if(_descriptor.numConf) {
                     66:         _configList = (UInt8 **)IOMalloc(sizeof(UInt8 *) * _descriptor.numConf);
                     67:         if(!_configList)
                     68:             return false;
                     69:         bzero(_configList, sizeof(UInt8 *) * _descriptor.numConf);
                     70:     }
                     71:     return true;
                     72: }
                     73: 
                     74: void IOUSBDevice::free()
                     75: {
                     76:     if(_configList) {
                     77:        int i;
                     78:         for(i=0; i<_descriptor.numConf; i++) {
                     79:             if(_configList[i]) {
                     80:                 int len = OSReadLittleInt16(&((IOUSBConfigurationDescriptor *)_configList[i])->totalLength, 0);
                     81:                 IOFree(_configList[i], len+2);
                     82:                _configList[i] = NULL;
                     83:             }
                     84:        }
                     85:         IOFree(_configList, sizeof(UInt8 *) * _descriptor.numConf);
                     86:     }
                     87:     IOUSBNub::free();
                     88: }
                     89: 
                     90: bool IOUSBDevice::attach(IOService *provider)
                     91: {
                     92:     IOReturn err;
                     93:     char name[128];
                     94: 
                     95:     if( !IOUSBNub::attach(provider))
                     96:         return (false);
                     97:     // Set controller if we weren't given one earlier.
                     98:     if(_controller == NULL)
                     99:        _controller = OSDynamicCast(IOUSBController, provider);
                    100:     if(_controller == NULL)
                    101:        return false;
                    102: 
                    103:     // Don't do this until we have a controller
                    104:     _endpointZero.length = sizeof(_endpointZero);
                    105:     _endpointZero.descriptorType = kUSBEndpointDesc;
                    106:     _endpointZero.endpointAddress = 0;
                    107:     _endpointZero.attributes = kUSBControl;
                    108:     OSWriteLittleInt16(&_endpointZero.maxPacketSizeLo, 0, _descriptor.maxPacketSize);  
                    109:     _endpointZero.interval = 0;
                    110: 
                    111:     _pipeZero = IOUSBPipe::toEndpoint(&_endpointZero, _speed, _address, _controller);
                    112: 
                    113:     if(_descriptor.prodIdx) {
                    114:         err = GetStringDescriptor(_descriptor.prodIdx, name, sizeof(name));
                    115:        if(err == kIOReturnSuccess) {
                    116:             setName(name);
                    117:             setProperty("USB Product Name", name);
                    118:        }
                    119:     }
                    120:     if(_descriptor.manuIdx) {
                    121:         err = GetStringDescriptor(_descriptor.manuIdx, name, sizeof(name));
                    122:         if(err == kIOReturnSuccess) {
                    123:             setProperty("USB Vendor Name", name);
                    124:        }
                    125:     }
                    126:     if(_descriptor.serialIdx) {
                    127:         err = GetStringDescriptor(_descriptor.serialIdx, name, sizeof(name));
                    128:         if(err == kIOReturnSuccess) {
                    129:             setProperty("USB Serial Number", name);
                    130:         }
                    131:     }
                    132:     return true;
                    133: }
                    134: 
                    135: // Stop all activity, reset device, restart.
                    136: IOReturn IOUSBDevice::resetDevice()
                    137: {
                    138:     IOReturn err;
                    139: 
                    140:     if(_pipeZero) {
                    141:         _pipeZero->release();
                    142:         _pipeZero = NULL;
                    143:     }
                    144:     err = _port->resetDevice();
                    145: 
                    146:     // Recreate pipe 0 object
                    147:     if(err == kIOReturnSuccess) {
                    148:         _pipeZero = IOUSBPipe::toEndpoint(&_endpointZero, _speed, _address, _controller);
                    149:         if(!_pipeZero)
                    150:             err = kIOReturnNoMemory;
                    151:     }
                    152: 
                    153:     return err;
                    154: }
                    155: 
                    156: /******************************************************
                    157:  * Helper Methods
                    158:  ******************************************************/
                    159: 
                    160: const IOUSBConfigurationDescriptor *
                    161: IOUSBDevice::findConfig(UInt8 configValue, int *configIndex)
                    162: {
                    163:     int i;
                    164:     const IOUSBConfigurationDescriptor *cd = NULL;
                    165: 
                    166:     for(i = 0; i < _descriptor.numConf; i++) {
                    167:         cd = getFullConfigurationDescriptor(i);
                    168:         if(!cd)
                    169:             continue;
                    170:         if(cd->configValue == configValue)
                    171:             break;
                    172:     }
                    173:     if(cd && configIndex)
                    174:        *configIndex = i;
                    175: 
                    176:     return cd;
                    177: }
                    178: 
                    179: // Finding the correct interface
                    180: /*
                    181:  * findNextInterface
                    182:  * This method should really be rewritten to use iterators or
                    183:  * be broken out into more functions without a request structure.
                    184:  * Or even better, make the interfaces and endpoint objects that
                    185:  * have their own methods for this stuff.
                    186:  *
                    187:  * returns:
                    188:  *   next interface matching criteria.  0 if no matches
                    189:  */
                    190: IOUSBInterface *
                    191: IOUSBDevice::findNextInterface(IOUSBInterface *current,
                    192:                                FindInterfaceRequest *request)
                    193: {
                    194:     const IOUSBConfigurationDescriptor *cd;
                    195:     const IOUSBInterfaceDescriptor *   id;
                    196:     const IOUSBDescriptorHeader *      pos = NULL;
                    197:     bool                               found;
                    198:     int                                        configIndex;
                    199:     if(current == NULL) {
                    200:        configIndex = 0;
                    201:         cd = getFullConfigurationDescriptor(configIndex);
                    202:         if(!cd)
                    203:             return NULL;
                    204:         pos = (IOUSBDescriptorHeader *)cd;
                    205:     }
                    206:     else {
                    207:         cd = findConfig(current->getConfigValue(), &configIndex);
                    208:         if(!cd)
                    209:             return NULL;
                    210:         pos = (IOUSBDescriptorHeader *)cd;
                    211:         while((pos = findNextDescriptor(pos, kUSBInterfaceDesc))) {
                    212:             if(bcmp(pos, current->interfaceDescriptor(),
                    213:                           sizeof(IOUSBInterfaceDescriptor)) == 0) {
                    214:                 break;
                    215:             }
                    216:         }
                    217:     }
                    218:     while (configIndex < _descriptor.numConf)
                    219:     {
                    220:         pos = findNextDescriptor(pos, kUSBInterfaceDesc);
                    221:         if(pos == NULL) {
                    222:             // End of that configuration
                    223:             configIndex++;
                    224:             if(configIndex >= _descriptor.numConf)
                    225:                 break;
                    226: 
                    227:             cd = getFullConfigurationDescriptor(configIndex);
                    228:             continue;
                    229:        }
                    230:         id = (const IOUSBInterfaceDescriptor *)pos;
                    231: 
                    232:         // check the request parameters
                    233:        found = true;
                    234:         if (request->theClass != 0 && request->theClass != id->interfaceClass)
                    235:             found = false;             // this is not it
                    236:         if (request->subClass != 0 && request->subClass != id->interfaceSubClass)
                    237:             found = false;             // this is not it
                    238:         if (request->protocol != 0 && request->protocol != id->interfaceProtocol)
                    239:             found = false;             // this is not it
                    240:         if (request->maxPower != 0 && request->maxPower < cd->maxPower)
                    241:             found = false;             // draws too much power
                    242:         if (id->alternateSetting != 0)
                    243:             found = false;             // Only want main setting
                    244: 
                    245:         if (found)
                    246:         {
                    247:             request->theClass = id->interfaceClass;
                    248:             request->subClass = id->interfaceSubClass;
                    249:             request->protocol = id->interfaceProtocol;
                    250:             request->maxPower = cd->maxPower;
                    251:             request->busPowered = cd->attributes & kUSBAtrBusPowered ? 2 : 1;
                    252:             request->selfPowered = cd->attributes & kUSBAtrSelfPowered ? 2 : 1;
                    253:             request->remoteWakeup = cd->attributes & kUSBAtrRemoteWakeup ? 2 : 1;
                    254:              return(GetInterface(id, cd));
                    255:         }
                    256:     }
                    257:     return(0);
                    258: }
                    259: 
                    260: const IOUSBConfigurationDescriptor *IOUSBDevice::getFullConfigurationDescriptor(UInt8 index)
                    261: {
                    262:     IOReturn err;
                    263: 
                    264:     if(_configList[index] == NULL) {
                    265:         int len;
                    266:         IOUSBConfigurationDescriptor temp;
                    267:         err = GetConfigDescriptor(index, &temp, sizeof(temp));
                    268:         if (err) {
                    269:             DEBUGLOG("getFullConfigurationDescriptor: Error 0x%x getting configuration descriptor\n", err);
                    270:             return(0);
                    271:         }
                    272:         len = OSReadLittleInt16(&temp.totalLength, 0);
                    273:         _configList[index] = (UInt8 *)IOMalloc(len + 2);
                    274:         if(_configList[index] == NULL)
                    275:             return 0;
                    276:         err = GetConfigDescriptor(index, _configList[index], len);
                    277:         if (err) {
                    278:             DEBUGLOG("getFullConfigurationDescriptor: Error %d getting full configuration\n", err);
                    279:             return(0);
                    280:         }
                    281:         *(_configList[index]+len) = 0; // A Known ~Elephant.
                    282:         *(_configList[index]+len+1) = 0;// A Known ~Elephant.
                    283:     }
                    284:     return (IOUSBConfigurationDescriptor *)_configList[index];
                    285: }
                    286: 
                    287: /*
                    288:  * GetConfigDescriptor:
                    289:  *     In: pointer to buffer for config descriptor, length to get
                    290:  * Assumes: desc is has enough space to put it all
                    291:  */
                    292: IOReturn IOUSBDevice::GetConfigDescriptor(UInt8 configIndex,
                    293:                                           void *desc, int len)
                    294: {
                    295:     IOReturn           err = kIOReturnSuccess;
                    296:     IOUSBDevRequest    request;
                    297: 
                    298:     DEBUGLOG("********** GET CONFIG DESCRIPTOR (%d)**********\n", len);
                    299: 
                    300:     /*
                    301:      * with config descriptors, the device will send back all descriptors,
                    302:      * if the request is big enough.
                    303:      */
                    304: 
                    305:     request.rqDirection = kUSBIn;
                    306:     request.rqType = kUSBStandard;
                    307:     request.rqRecipient = kUSBDevice;
                    308:     request.bRequest = kUSBRqGetDescriptor;
                    309:     OSWriteLittleInt16(&request.wValue, 0, (kUSBConfDesc << 8) + configIndex);
                    310:     OSWriteLittleInt16(&request.wIndex, 0, 0);
                    311:     OSWriteLittleInt16(&request.wLength, 0, len);
                    312:     request.pData = desc;
                    313: 
                    314:     err = deviceRequest(&request);
                    315: 
                    316:     if (err)
                    317:     {
                    318:         DEBUGLOG("%s: error getting device config descriptor. err=0x%x\n", getName(), err);
                    319:     }
                    320: 
                    321:     return(err);
                    322: }
                    323: 
                    324: IOReturn IOUSBDevice::SetConfiguration(UInt8 configNumber)
                    325: {
                    326:     IOReturn           err = kIOReturnSuccess;
                    327:     IOUSBDevRequest    request;
                    328: 
                    329:     DEBUGLOG("********** SET CONFIGURATION TO %d **********\n", configNumber);
                    330: 
                    331:     request.rqDirection = kUSBOut;
                    332:     request.rqType = kUSBStandard;
                    333:     request.rqRecipient = kUSBDevice;
                    334:     request.bRequest = kUSBRqSetConfig;
                    335:     OSWriteLittleInt16(&request.wValue, 0, configNumber);
                    336:     OSWriteLittleInt16(&request.wIndex, 0, 0);
                    337:     OSWriteLittleInt16(&request.wLength, 0, 0);
                    338:     request.pData = 0;
                    339: 
                    340:     err = deviceRequest(&request);
                    341: 
                    342:     if (err)
                    343:     {
                    344:         DEBUGLOG("%s: error setting config. err=%d\n", getName(), err);
                    345:     }
                    346: 
                    347:     return(err);
                    348: }
                    349: 
                    350: IOUSBInterface * IOUSBDevice::GetInterface(const IOUSBInterfaceDescriptor *interface,
                    351:                                                     const IOUSBConfigurationDescriptor *config)
                    352: {
                    353:     OSDictionary *             propTable = 0;
                    354:     OSArray *                  epArray = 0;
                    355:     IOUSBInterface *           newDevice = 0;
                    356:     OSData *                   data;
                    357:     OSNumber *                 offset;
                    358:     int                                i;
                    359:     char                       location[8];
                    360:     OSIterator *               clients;
                    361:     /*
                    362:      * First see if the interface has already been created,
                    363:      * ie. there's already one with the given interface descriptor and config descriptor
                    364:      */
                    365:     clients = getClientIterator();
                    366:     if(clients) {
                    367:         OSObject *next;
                    368:         while((next = clients->getNextObject())) {
                    369:             IOUSBInterface *testIt = OSDynamicCast(IOUSBInterface, next);
                    370:             if(testIt) {
                    371:                 if(config->configValue == testIt->getConfigValue() &&
                    372:                    bcmp(interface, testIt->interfaceDescriptor(), sizeof(IOUSBInterfaceDescriptor)) == 0) {
                    373:                     newDevice = testIt;
                    374:                     break;
                    375:                }
                    376:             }
                    377:        }
                    378:        clients->release();
                    379:     }
                    380:     if(newDevice) {
                    381:        newDevice->retain();
                    382:        return newDevice;
                    383:     }
                    384:     do {
                    385:         propTable = OSDictionary::withCapacity(13);
                    386:         if (!propTable)
                    387:             continue;
                    388: 
                    389:         data = OSData::withBytes( &_descriptor, sizeof( _descriptor ));
                    390:         if (data) {
                    391:             propTable->setObject("device descriptor", data);
                    392:             data->release();
                    393:         }
                    394:         offset = OSNumber::withNumber(interface->interfaceClass, 8);
                    395:         if(offset) {
                    396:             propTable->setObject("class", offset);
                    397:             offset->release();
                    398:         }
                    399:         offset = OSNumber::withNumber(interface->interfaceSubClass, 8);
                    400:         if(offset) {
                    401:             propTable->setObject("subClass", offset);
                    402:             offset->release();
                    403:         }
                    404:         offset = OSNumber::withNumber(interface->interfaceProtocol, 8);
                    405:         if(offset) {
                    406:             propTable->setObject("protocol", offset);
                    407:             offset->release();
                    408:         }
                    409:         offset = OSNumber::withNumber(OSReadLittleInt16(&_descriptor.vendor, 0), 16);
                    410:         if(offset) {
                    411:             propTable->setObject("vendor", offset);
                    412:             offset->release();
                    413:         }
                    414:         offset = OSNumber::withNumber(OSReadLittleInt16(&_descriptor.product, 0), 16);
                    415:         if(offset) {
                    416:             propTable->setObject("product", offset);
                    417:             offset->release();
                    418:         }
                    419:         offset = OSNumber::withNumber(OSReadLittleInt16(&_descriptor.devRel, 0), 16);
                    420:         if(offset) {
                    421:             propTable->setObject("version", offset);
                    422:             offset->release();
                    423:         }
                    424:         data = OSData::withBytes(&_address, sizeof( _address ));
                    425:         if (data) {
                    426:             propTable->setObject("device address", data);
                    427:             data->release();
                    428:         }
                    429:         data = OSData::withBytes( config,
                    430:                                   sizeof( *config ));
                    431:         if (data) {
                    432:             propTable->setObject("configuration descriptor", data);
                    433:             data->release();
                    434:         }
                    435:         data = OSData::withBytes( interface,
                    436:                                    sizeof(*interface));
                    437:         if (data) {
                    438:             propTable->setObject("interface descriptor", data);
                    439:             data->release();
                    440:         }
                    441:         data = OSData::withBytes(&_busPowerAvailable, sizeof(_busPowerAvailable));
                    442:         if (data) {
                    443:             propTable->setObject("bus power available", data);
                    444:             data->release();
                    445:         }
                    446:         data = OSData::withBytes(&_speed, sizeof(_speed));
                    447:         if (data) {
                    448:             propTable->setObject("low speed device", data);
                    449:             data->release();
                    450:         }
                    451: 
                    452:         epArray = OSArray::withCapacity(interface->numEndpoints);
                    453:         if (!epArray)
                    454:             continue;
                    455:         IOUSBEndpointDescriptor *ep = (IOUSBEndpointDescriptor *)interface;
                    456:         for(i=0; i<interface->numEndpoints; i++) {
                    457:             ep = (IOUSBEndpointDescriptor *)findNextDescriptor(ep, kUSBEndpointDesc);
                    458:             if(!ep)
                    459:                break;
                    460:             data = OSData::withBytes(ep, sizeof(IOUSBEndpointDescriptor));
                    461:             if (data) {
                    462:                 epArray->setObject(i, data);
                    463:                 data->release();
                    464:             }
                    465:        }
                    466:         propTable->setObject("Endpoints", epArray);
                    467:         epArray->release();
                    468: 
                    469:         newDevice = createInterface(propTable, config, interface);
                    470: 
                    471:         if (!newDevice )
                    472:             continue;
                    473: 
                    474:         propTable->release();  // done with it after init
                    475:         propTable = 0;
                    476: 
                    477:         sprintf( location, "%x", _address );
                    478:         newDevice->setLocation(location);
                    479:         if (!newDevice->attach(this))
                    480:             break;
                    481: 
                    482:         return(newDevice);
                    483: 
                    484:     } while (false);
                    485: 
                    486:     if (propTable)
                    487:         propTable->release();
                    488:     if (epArray)
                    489:        epArray->release();
                    490:     if (newDevice)
                    491:         newDevice->release();
                    492: 
                    493:     return(NULL);
                    494: }
                    495: 
                    496: IOUSBInterface *
                    497: IOUSBDevice::createInterface(OSDictionary *table,
                    498:                    const IOUSBConfigurationDescriptor *config,
                    499:                                         const IOUSBInterfaceDescriptor *interface)
                    500: {
                    501:     IOUSBInterface *newIface;
                    502: 
                    503:     newIface = new IOUSBInterface;
                    504:     if(!newIface)
                    505:        return NULL;
                    506:     if(!newIface->init(table, config, interface)) {
                    507:         newIface->release();
                    508:         newIface = NULL;
                    509:     }
                    510:     return newIface;
                    511: }
                    512: 
                    513: // Copy data into supplied buffer, up to 'len' bytes.
                    514: IOReturn IOUSBDevice::getConfigurationDescriptor(UInt8 configValue, void *data, UInt32 len)
                    515: {
                    516:     unsigned int toCopy;
                    517:     const IOUSBConfigurationDescriptor *cd;
                    518:     cd = findConfig(configValue);
                    519:     if(!cd)
                    520:         return kIOUSBConfigNotFound;
                    521: 
                    522:     toCopy = OSReadLittleInt16(&cd->totalLength, 0);
                    523:     if(len < toCopy)
                    524:        toCopy = len;
                    525:     bcopy(cd, data, toCopy);
                    526:     return kIOReturnSuccess;
                    527: }
                    528: 
                    529: 
                    530: /**
                    531:  ** IOUserClient methods
                    532:  **/
                    533: 
                    534: IOReturn IOUSBDevice::newUserClient(  task_t           owningTask,
                    535:                                       void *           /* security_id */,
                    536:                                       UInt32           type,
                    537:                                       IOUserClient **  handler )
                    538: 
                    539: {
                    540:     IOReturn                   err = kIOReturnSuccess;
                    541:     IOUSBDeviceUserClient *    client;
                    542: 
                    543:     if( type != kIOUSBDeviceConnectType)
                    544:         return( kIOReturnBadArgument);
                    545: 
                    546:     client = IOUSBDeviceUserClient::withTask(owningTask);
                    547: 
                    548:     if( !client || (false == client->attach( this )) ||
                    549:         (false == client->start( this )) ) {
                    550:         if(client) {
                    551:             client->detach( this );
                    552:             client->release();
                    553:         }
                    554:         err = kIOReturnNoMemory;
                    555:     }
                    556: 
                    557:     *handler = client;
                    558:     return( err );
                    559: }
                    560: 
                    561: 

unix.superglobalmegacorp.com

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