Annotation of XNU/iokit/Families/IOUSBBus/IOUSBInterface.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:  * 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.