Annotation of XNU/iokit/Families/IOUSBBus/IOUSBInterface.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:  * 05 Mar 99 ehewitt created.
                     27:  *
                     28:  * IOUSBInterface
                     29:  * In USB there is the concept of a composite device, which means that
                     30:  * each interface in a selected configuration can act as a separate device.
                     31:  * Take for example a combo keyboard/trackball device.  In this example,
                     32:  * we might want a generic keyboard driver to handle the keyboard part and
                     33:  * a generic pointer driver to handle the trackball part.
                     34:  * So what we do is publish a IOUSBInterface for each interface of a
                     35:  * composite device and intercept the few device requests that are not allowed
                     36:  * by an interface, like set address and set configuration.
                     37:  * If another driver handled both functions, or if there was a specific driver
                     38:  * for that device, the matching logic would do the right thing.
                     39:  * 
                     40:  */
                     41: 
                     42: #include <libkern/OSByteOrder.h>
                     43: #include <IOKit/usb/IOUSBDevice.h>
                     44: #include <IOKit/usb/IOUSBController.h>
                     45: #include <IOKit/usb/IOUSBInterface.h>
                     46: #include <libkern/c++/OSDictionary.h>
                     47: #include <libkern/c++/OSData.h>
                     48: #include <IOKit/assert.h>
                     49: 
                     50: #include <IOKit/usb/IOUSBPipe.h>
                     51: #include "IOUSBUserClient.h"
                     52: #define super IOUSBNub
                     53: #define self this
                     54: 
                     55: int devintdebug = 0;
                     56: #define DEBUGLOG if (devintdebug) kprintf
                     57: 
                     58: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     59: 
                     60: OSDefineMetaClassAndStructors(IOUSBInterface, IOUSBNub)
                     61: 
                     62: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     63: 
                     64: bool IOUSBInterface::init(OSDictionary * propTable,
                     65:                           const IOUSBConfigurationDescriptor *cfdesc,
                     66:                                const IOUSBInterfaceDescriptor *ifdesc)
                     67: {
                     68:     if(!ifdesc || !cfdesc)
                     69:         return (false);
                     70: 
                     71:     if( !IOUSBNub::init(propTable))
                     72:         return (false);
                     73:     _configDesc = cfdesc;
                     74:     _interfaceDesc = ifdesc;
                     75: 
                     76:     return (true);
                     77: }
                     78: 
                     79: bool IOUSBInterface::attach(IOService *provider)
                     80: {
                     81:     IOUSBDevice * device = OSDynamicCast(IOUSBDevice, provider);
                     82:     if(!device)
                     83:        return false;
                     84:     if( !IOUSBNub::attach(provider))
                     85:         return false;
                     86:     _device = device;
                     87:     _controller = device->bus();
                     88:     _pipeZero = device->pipeZero();
                     89:     _pipeZero->retain();
                     90: 
                     91:     if(_interfaceDesc->interfaceStrIndex) {
                     92:         IOReturn err;
                     93:         char name[128];
                     94: 
                     95:         err = GetStringDescriptor(_interfaceDesc->interfaceStrIndex, name, sizeof(name));
                     96:         if(err == kIOReturnSuccess)
                     97:             setName(name);
                     98:     }
                     99: 
                    100:     return true;
                    101: }
                    102: 
                    103: bool IOUSBInterface::finalize(IOOptionBits options)
                    104: {
                    105:     cleanPipes();
                    106:     return IOUSBNub::finalize(options);
                    107: }
                    108: 
                    109: /*
                    110:  * deviceRequest
                    111:  *   The idea here is to intercept only the calls that an interface,
                    112:  * thinking it's a driver, might make.  These include setting it's
                    113:  * configuration, getting it's device descriptor, and setting it's address.
                    114:  */
                    115: IOReturn IOUSBInterface::deviceRequest(IOUSBDevRequest *request,
                    116:                                              IOUSBCompletion   *completion = 0)
                    117: {
                    118:     IOReturn           err;
                    119:     UInt16             theRequest;
                    120: 
                    121: 
                    122:     if (!request)
                    123:         return(kIOReturnBadArgument);
                    124:     
                    125:     theRequest = EncodeRequest(request->bRequest, request->rqDirection,
                    126:                                request->rqType,   request->rqRecipient);
                    127: 
                    128:     if (theRequest == kSetConfiguration)
                    129:     {
                    130:         DEBUGLOG("\tignoring kSetConfiguration\n");
                    131:         err = kIOReturnNotPermitted;
                    132:     }
                    133:     else
                    134:     {
                    135:         err = super::deviceRequest(request, completion);
                    136:     }
                    137: 
                    138:     return(err);
                    139: }
                    140: 
                    141: void IOUSBInterface::cleanPipes(void)
                    142: {
                    143:     IOUSBPipe * pipe;
                    144: 
                    145:     for( unsigned int i=0; i < kUSBMaxPipes; i++) {
                    146:         if( (pipe = _pipeList[i])) {
                    147:             pipe->release();
                    148:             _pipeList[i] = 0;
                    149:         }
                    150:     }
                    151: }
                    152: 
                    153: // Open all the pipes.
                    154: bool IOUSBInterface::open(IOService *  forClient,
                    155:                         IOOptionBits   options = 0,
                    156:                         void *         arg = 0 )
                    157: {
                    158:     unsigned int i = 0;
                    159:     const IOUSBDescriptorHeader *pos = NULL;
                    160:     if(!IOUSBNub::open(forClient, options, arg))
                    161:        return false;
                    162: 
                    163:     if(_currentAlt != _interfaceDesc->alternateSetting) {
                    164:         IOUSBDevRequest        request;
                    165:         IOReturn res;
                    166: 
                    167:         request.rqDirection = kUSBOut;
                    168:         request.rqType = kUSBStandard;
                    169:         request.rqRecipient = kUSBInterface;
                    170:         request.bRequest = kUSBRqSetInterface;
                    171:         OSWriteLittleInt16(&request.wValue, 0, _interfaceDesc->alternateSetting);
                    172:         OSWriteLittleInt16(&request.wIndex, 0, _interfaceDesc->interfaceNumber);
                    173:         OSWriteLittleInt16(&request.wLength, 0, 0);
                    174:         request.pData = 0;
                    175:         res = deviceRequest(&request);
                    176:         IOLog("SetInterface (%d, %d) returned 0x%x\n",
                    177:             _interfaceDesc->interfaceNumber, _interfaceDesc->alternateSetting, res);
                    178:         if(res != kIOReturnSuccess) {
                    179:             close(forClient);
                    180:             return false;
                    181:         }
                    182:         _currentAlt = _interfaceDesc->alternateSetting;
                    183:     }
                    184:     while ((pos = findNextAssociatedDescriptor(pos, kUSBEndpointDesc))) {
                    185:         // Don't open twice!
                    186:         if(_pipeList[i] == NULL) {
                    187:             _pipeList[i] = IOUSBPipe::toEndpoint((const IOUSBEndpointDescriptor *)pos,
                    188:                                                             _speed, _address, _controller);
                    189:         }
                    190:         if(_pipeList[i] == NULL) {
                    191:             close(forClient);
                    192:             return false;
                    193:         }
                    194:         i++;
                    195:     }
                    196:     assert(i == _interfaceDesc->numEndpoints);
                    197: 
                    198:     return true;
                    199: }
                    200: 
                    201: void IOUSBInterface::close(IOService * forClient,
                    202:                         IOOptionBits   options = 0 )
                    203: {
                    204:     cleanPipes();
                    205:     IOUSBNub::close(forClient, options);
                    206: }
                    207: 
                    208: const IOUSBInterfaceDescriptor *
                    209: IOUSBInterface::findNextAltInterface(const IOUSBInterfaceDescriptor *current,
                    210:                                 FindInterfaceRequest *request)
                    211: {
                    212:     const IOUSBInterfaceDescriptor *   id;
                    213:     const IOUSBDescriptorHeader *      pos = NULL;
                    214:     bool                               found;
                    215:     if(current == NULL)
                    216:         pos = (IOUSBDescriptorHeader *)_configDesc;
                    217:     else
                    218:         pos = (IOUSBDescriptorHeader *)current;
                    219:     while (pos)
                    220:     {
                    221:         pos = findNextDescriptor(pos, kUSBInterfaceDesc);
                    222:         id = (const IOUSBInterfaceDescriptor *)pos;
                    223:         if(id == NULL || (id->interfaceNumber != _interfaceDesc->interfaceNumber)) {
                    224:             continue;
                    225:         }
                    226: 
                    227:         // check the request parameters
                    228:         found = true;
                    229:         if (request->theClass != 0 && request->theClass != id->interfaceClass)
                    230:             found = false;             // this is not it
                    231:         if (request->subClass != 0 && request->subClass != id->interfaceSubClass)
                    232:             found = false;             // this is not it
                    233:         if (request->protocol != 0 && request->protocol != id->interfaceProtocol)
                    234:             found = false;             // this is not it
                    235:         if (found)
                    236:         {
                    237:             request->theClass = id->interfaceClass;
                    238:             request->subClass = id->interfaceSubClass;
                    239:             request->protocol = id->interfaceProtocol;
                    240:             request->maxPower = _configDesc->maxPower;
                    241:             request->busPowered = _configDesc->attributes & kUSBAtrBusPowered ? 2 : 1;
                    242:             request->selfPowered = _configDesc->attributes & kUSBAtrSelfPowered ? 2 : 1;
                    243:             request->remoteWakeup = _configDesc->attributes & kUSBAtrRemoteWakeup ? 2 : 1;
                    244:              return(id);
                    245:         }
                    246:     }
                    247:     return(0);
                    248: }
                    249: 
                    250: 
                    251: IOUSBPipe *IOUSBInterface::findNextPipe(IOUSBPipe *current,
                    252:                                 IOUSBFindEndpointRequest *request)
                    253: {
                    254:     const IOUSBController::Endpoint *  endpoint;
                    255:     IOUSBPipe *                                pipe;
                    256:     int                                        numEndpoints;
                    257:     int                                        i;
                    258: 
                    259:     numEndpoints = _interfaceDesc->numEndpoints;
                    260: 
                    261:     if (request == 0)
                    262:         return NULL;
                    263:     if(current != 0) {
                    264:         for(i=0;i < numEndpoints; i++) {
                    265:             if(_pipeList[i] == current) {
                    266:                i++; // Skip the one we just did
                    267:                 break;
                    268:             }
                    269:        }
                    270:     }
                    271:     else
                    272:         i = 0; // Start at beginning.
                    273: 
                    274:     for (;i < numEndpoints; i++) {
                    275:         pipe = _pipeList[i];
                    276:         if(!pipe)
                    277:             continue;
                    278:         endpoint = pipe->endpoint();
                    279: 
                    280:         // check the request parameters
                    281:         if (request->type != kUSBAnyType &&
                    282:             request->type != endpoint->transferType)
                    283:             pipe = 0;          // this is not it
                    284:         else if (request->direction != kUSBAnyDirn &&
                    285:             request->direction != endpoint->direction)
                    286:             pipe = 0;          // this is not it
                    287: 
                    288:         if (pipe == 0)
                    289:             continue;
                    290: 
                    291:         request->type = endpoint->transferType;
                    292:         request->direction = endpoint->direction;
                    293:         request->maxPacketSize = endpoint->maxPacketSize;
                    294:         request->interval = endpoint->interval;
                    295:         return(pipe);
                    296:     }
                    297: 
                    298:     return(0);
                    299: }
                    300: 
                    301: const IOUSBDescriptorHeader *
                    302: IOUSBInterface::findNextAssociatedDescriptor(const void *current, UInt8 type)
                    303: {
                    304:     const IOUSBDescriptorHeader *next;
                    305:     if(current == NULL)
                    306:         current = _interfaceDesc;
                    307:     next = (const IOUSBDescriptorHeader *)current;
                    308: 
                    309:     while (true) {
                    310:         next = findNextDescriptor(next, kUSBAnyDesc);
                    311: 
                    312:         if(!next || next->descriptorType == kUSBInterfaceDesc)
                    313:             return NULL;       // Reached end of our list.
                    314:         if(next->descriptorType == type || type == kUSBAnyDesc)
                    315:             break;
                    316:     }
                    317:     return next;
                    318: }
                    319: 
                    320: IOReturn
                    321: IOUSBInterface::setAlternateInterface(UInt8 alternateSetting)
                    322: {
                    323:     const IOUSBDescriptorHeader *next;
                    324:     const IOUSBInterfaceDescriptor *ifdesc;
                    325: 
                    326:     next = (const IOUSBDescriptorHeader *)_configDesc;
                    327: 
                    328:     while( (next = findNextDescriptor(next, kUSBInterfaceDesc))) {
                    329:         ifdesc = (const IOUSBInterfaceDescriptor *)next;
                    330:         if(ifdesc->interfaceNumber == _interfaceDesc->interfaceNumber &&
                    331:             ifdesc->alternateSetting == alternateSetting)
                    332:             break;
                    333:     }
                    334: 
                    335:     if(ifdesc) {
                    336:         _interfaceDesc = ifdesc;
                    337:         OSData * data;
                    338:         data = OSData::withBytes(ifdesc, sizeof(*ifdesc));
                    339:         if (data) {
                    340:             setProperty("interface descriptor", data);
                    341:             data->release();
                    342:         }
                    343: 
                    344:         return kIOReturnSuccess;
                    345:     }
                    346:     else
                    347:         return kIOUSBConfigNotFound;
                    348: }
                    349: 
                    350: UInt8 IOUSBInterface::getConfigValue()
                    351: {
                    352:     return _configDesc->configValue;
                    353: }
                    354: 
                    355: const IOUSBInterfaceDescriptor * IOUSBInterface::interfaceDescriptor()
                    356: {
                    357:     return _interfaceDesc;
                    358: }
                    359: 
                    360: IOUSBDevice * IOUSBInterface::device()
                    361: {
                    362:     return _device;
                    363: }
                    364: 
                    365: IOReturn IOUSBInterface::newUserClient(  task_t                owningTask,
                    366:                                       void *           /* security_id */,
                    367:                                       UInt32           type,
                    368:                                       IOUserClient **  handler )
                    369: 
                    370: {
                    371:     IOReturn                   err = kIOReturnSuccess;
                    372:     IOUSBInterfaceUserClient * client;
                    373: 
                    374:     if( type != kIOUSBDeviceConnectType)
                    375:         return( kIOReturnBadArgument);
                    376: 
                    377:     client = IOUSBInterfaceUserClient::withTask(owningTask);
                    378: 
                    379:     if( !client || (false == client->attach( this )) ||
                    380:         (false == client->start( this )) ) {
                    381:         if(client) {
                    382:             client->detach( this );
                    383:             client->release();
                    384:         }
                    385:         err = kIOReturnNoMemory;
                    386:     }
                    387: 
                    388:     *handler = client;
                    389:     return( err );
                    390: }
                    391: 
                    392: 
                    393: 

unix.superglobalmegacorp.com

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