Annotation of XNU/iokit/Families/IOUSBBus/IOUSBUserClient.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) 1999 Apple Computer, Inc.  All rights reserved.
                     24:  *
                     25:  * HISTORY
                     26:  * 16 Mar 1999 wgulland created.
                     27:  *
                     28:  */
                     29: #include <libkern/OSByteOrder.h>
                     30: 
                     31: #include <IOKit/assert.h>
                     32: #include <IOKit/IOLib.h>
                     33: #include <IOKit/IOBufferMemoryDescriptor.h>
                     34: #include <IOKit/usb/IOUSBDevice.h>
                     35: #include <IOKit/usb/IOUSBInterface.h>
                     36: #include <IOKit/usb/IOUSBPipe.h>
                     37: 
                     38: #include "IOUSBUserClient.h"
                     39: 
                     40: #define super IOUserClient
                     41: #define DEBUGGING_LEVEL 0
                     42: 
                     43: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     44: 
                     45: OSDefineMetaClass( IOUSBUserClient, IOUserClient )
                     46: OSDefineAbstractStructors(IOUSBUserClient, IOUserClient)
                     47: 
                     48: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     49: 
                     50: bool IOUSBUserClient::start( IOService * provider )
                     51: {
                     52:     IOUSBNub *owner = OSDynamicCast(IOUSBNub, provider);
                     53: 
                     54:     assert(owner);
                     55:     if(!super::start(provider))
                     56:         return false;
                     57: 
                     58:     fPipes[0] = owner->pipeZero();
                     59:     if(!fPipes[0])
                     60:        return false;
                     61: 
                     62:     // Initialize the call structures valid for IOUSBNub
                     63:     fMethods[kUSBSetConfig].object = NULL;
                     64:     fMethods[kUSBSetConfig].func = NULL;
                     65:     fMethods[kUSBSetConfig].count0 = 1;
                     66:     fMethods[kUSBSetConfig].count1 = 0;
                     67:     fMethods[kUSBSetConfig].flags = kIOUCScalarIScalarO;
                     68: 
                     69:     fMethods[kUSBGetConfig].object = provider;
                     70:     fMethods[kUSBGetConfig].func = (IOMethod)&IOUSBNub::GetConfiguration;
                     71:     fMethods[kUSBGetConfig].count0 = 0;
                     72:     fMethods[kUSBGetConfig].count1 = 1;
                     73:     fMethods[kUSBGetConfig].flags = kIOUCScalarIScalarO;
                     74: 
                     75:     fMethods[kUSBGetConfigDescriptor].object = NULL;
                     76:     fMethods[kUSBGetConfigDescriptor].func = NULL;
                     77:     fMethods[kUSBGetConfigDescriptor].count0 = 1;
                     78:     fMethods[kUSBGetConfigDescriptor].count1 = 0xffffffff; // variable
                     79:     fMethods[kUSBGetConfigDescriptor].flags = kIOUCScalarIStructO;
                     80: 
                     81:     fMethods[kUSBControlReqOut].object = this;
                     82:     fMethods[kUSBControlReqOut].func =
                     83:         (IOMethod)&IOUSBUserClient::ControlReqOut;
                     84:     fMethods[kUSBControlReqOut].count0 = 4;
                     85:     fMethods[kUSBControlReqOut].count1 = 0xffffffff; // variable
                     86:     fMethods[kUSBControlReqOut].flags = kIOUCScalarIStructI;
                     87: 
                     88:     fMethods[kUSBControlReqIn].object = this;
                     89:     fMethods[kUSBControlReqIn].func =
                     90:         (IOMethod)&IOUSBUserClient::ControlReqIn;
                     91:     fMethods[kUSBControlReqIn].count0 = 4;
                     92:     fMethods[kUSBControlReqIn].count1 = 0xffffffff; // variable
                     93:     fMethods[kUSBControlReqIn].flags = kIOUCScalarIStructO;
                     94: 
                     95:     fMethods[kUSBOpenPipe].object = NULL;
                     96:     fMethods[kUSBOpenPipe].func = NULL;
                     97:     fMethods[kUSBOpenPipe].count0 = 4;
                     98:     fMethods[kUSBOpenPipe].count1 = 1;
                     99:     fMethods[kUSBOpenPipe].flags = kIOUCScalarIScalarO;
                    100: 
                    101:     fMethods[kUSBClosePipe].object = this;
                    102:     fMethods[kUSBClosePipe].func =
                    103:         (IOMethod)&IOUSBUserClient::ClosePipe;
                    104:     fMethods[kUSBClosePipe].count0 = 1;
                    105:     fMethods[kUSBClosePipe].count1 = 0;
                    106:     fMethods[kUSBClosePipe].flags = kIOUCScalarIScalarO;
                    107: 
                    108:     fMethods[kUSBReadPipe].object = this;
                    109:     fMethods[kUSBReadPipe].func =
                    110:         (IOMethod)&IOUSBUserClient::ReadPipe;
                    111:     fMethods[kUSBReadPipe].count0 = 1;
                    112:     fMethods[kUSBReadPipe].count1 = 0xffffffff; // variable
                    113:     fMethods[kUSBReadPipe].flags = kIOUCScalarIStructO;
                    114: 
                    115:     fMethods[kUSBWritePipe].object = this;
                    116:     fMethods[kUSBWritePipe].func =
                    117:         (IOMethod)&IOUSBUserClient::WritePipe;
                    118:     fMethods[kUSBWritePipe].count0 = 1;
                    119:     fMethods[kUSBWritePipe].count1 = 0xffffffff; // variable
                    120:     fMethods[kUSBWritePipe].flags = kIOUCScalarIStructI;
                    121: 
                    122:     fMethods[kUSBGetPipeStatus].object = this;
                    123:     fMethods[kUSBGetPipeStatus].func =
                    124:         (IOMethod)&IOUSBUserClient::getPipeStatus;
                    125:     fMethods[kUSBGetPipeStatus].count0 = 1;
                    126:     fMethods[kUSBGetPipeStatus].count1 = 0;
                    127:     fMethods[kUSBGetPipeStatus].flags = kIOUCScalarIScalarO;
                    128: 
                    129:     fMethods[kUSBAbortPipe].object = this;
                    130:     fMethods[kUSBAbortPipe].func =
                    131:         (IOMethod)&IOUSBUserClient::abortPipe;
                    132:     fMethods[kUSBAbortPipe].count0 = 1;
                    133:     fMethods[kUSBAbortPipe].count1 = 0;
                    134:     fMethods[kUSBAbortPipe].flags = kIOUCScalarIScalarO;
                    135: 
                    136:     fMethods[kUSBResetPipe].object = this;
                    137:     fMethods[kUSBResetPipe].func =
                    138:         (IOMethod)&IOUSBUserClient::resetPipe;
                    139:     fMethods[kUSBResetPipe].count0 = 1;
                    140:     fMethods[kUSBResetPipe].count1 = 0;
                    141:     fMethods[kUSBResetPipe].flags = kIOUCScalarIScalarO;
                    142: 
                    143:     fMethods[kUSBSetPipeIdle].object = this;
                    144:     fMethods[kUSBSetPipeIdle].func =
                    145:         (IOMethod)&IOUSBUserClient::setPipeIdle;
                    146:     fMethods[kUSBSetPipeIdle].count0 = 1;
                    147:     fMethods[kUSBSetPipeIdle].count1 = 0;
                    148:     fMethods[kUSBSetPipeIdle].flags = kIOUCScalarIScalarO;
                    149: 
                    150:     fMethods[kUSBSetPipeActive].object = this;
                    151:     fMethods[kUSBSetPipeActive].func =
                    152:         (IOMethod)&IOUSBUserClient::setPipeActive;
                    153:     fMethods[kUSBSetPipeActive].count0 = 1;
                    154:     fMethods[kUSBSetPipeActive].count1 = 0;
                    155:     fMethods[kUSBSetPipeActive].flags = kIOUCScalarIScalarO;
                    156: 
                    157:     fMethods[kUSBClearPipeStall].object = this;
                    158:     fMethods[kUSBClearPipeStall].func =
                    159:         (IOMethod)&IOUSBUserClient::clearPipeStall;
                    160:     fMethods[kUSBClearPipeStall].count0 = 1;
                    161:     fMethods[kUSBClearPipeStall].count1 = 0;
                    162:     fMethods[kUSBClearPipeStall].flags = kIOUCScalarIScalarO;
                    163: 
                    164:     fMethods[kUSBReadPipeOOL].object = this;
                    165:     fMethods[kUSBReadPipeOOL].func =
                    166:         (IOMethod)&IOUSBUserClient::ReadPipeOOL;
                    167:     fMethods[kUSBReadPipeOOL].count0 = 3;
                    168:     fMethods[kUSBReadPipeOOL].count1 = 1;
                    169:     fMethods[kUSBReadPipeOOL].flags = kIOUCScalarIScalarO;
                    170: 
                    171:     fAsyncMethods[kUSBReadPipeOOL].object = this;
                    172:     fAsyncMethods[kUSBReadPipeOOL].func =
                    173:         (IOAsyncMethod)&IOUSBUserClient::ReadPipeAsync;
                    174:     fAsyncMethods[kUSBReadPipeOOL].count0 = 3;
                    175:     fAsyncMethods[kUSBReadPipeOOL].count1 = 0;
                    176:     fAsyncMethods[kUSBReadPipeOOL].flags = kIOUCScalarIScalarO;
                    177: 
                    178:     fMethods[kUSBWritePipeOOL].object = this;
                    179:     fMethods[kUSBWritePipeOOL].func =
                    180:         (IOMethod)&IOUSBUserClient::WritePipeOOL;
                    181:     fMethods[kUSBWritePipeOOL].count0 = 3;
                    182:     fMethods[kUSBWritePipeOOL].count1 = 0;
                    183:     fMethods[kUSBWritePipeOOL].flags = kIOUCScalarIScalarO;
                    184: 
                    185:     fAsyncMethods[kUSBWritePipeOOL].object = this;
                    186:     fAsyncMethods[kUSBWritePipeOOL].func =
                    187:         (IOAsyncMethod)&IOUSBUserClient::WritePipeAsync;
                    188:     fAsyncMethods[kUSBWritePipeOOL].count0 = 3;
                    189:     fAsyncMethods[kUSBWritePipeOOL].count1 = 0;
                    190:     fAsyncMethods[kUSBWritePipeOOL].flags = kIOUCScalarIScalarO;
                    191: 
                    192:     fMethods[kUSBControlReqInOOL].object = this;
                    193:     fMethods[kUSBControlReqInOOL].func =
                    194:         (IOMethod)&IOUSBUserClient::ControlReqInOOL;
                    195:     fMethods[kUSBControlReqInOOL].count0 = sizeof(DevReqOOL);
                    196:     fMethods[kUSBControlReqInOOL].count1 = sizeof(UInt32);
                    197:     fMethods[kUSBControlReqInOOL].flags = kIOUCStructIStructO;
                    198: 
                    199:     fAsyncMethods[kUSBControlReqInOOL].object = this;
                    200:     fAsyncMethods[kUSBControlReqInOOL].func =
                    201:         (IOAsyncMethod)&IOUSBUserClient::ControlReqInAsync;
                    202:     fAsyncMethods[kUSBControlReqInOOL].count0 = sizeof(DevReqOOL);
                    203:     fAsyncMethods[kUSBControlReqInOOL].count1 = 0;
                    204:     fAsyncMethods[kUSBControlReqInOOL].flags = kIOUCStructIStructO;
                    205: 
                    206:     fMethods[kUSBControlReqOutOOL].object = this;
                    207:     fMethods[kUSBControlReqOutOOL].func =
                    208:         (IOMethod)&IOUSBUserClient::ControlReqOutOOL;
                    209:     fMethods[kUSBControlReqOutOOL].count0 = sizeof(DevReqOOL);
                    210:     fMethods[kUSBControlReqOutOOL].count1 = 0;
                    211:     fMethods[kUSBControlReqOutOOL].flags = kIOUCStructIStructO;
                    212: 
                    213:     fAsyncMethods[kUSBControlReqOutOOL].object = this;
                    214:     fAsyncMethods[kUSBControlReqOutOOL].func =
                    215:         (IOAsyncMethod)&IOUSBUserClient::ControlReqOutAsync;
                    216:     fAsyncMethods[kUSBControlReqOutOOL].count0 = sizeof(DevReqOOL);
                    217:     fAsyncMethods[kUSBControlReqOutOOL].count1 = 0;
                    218:     fAsyncMethods[kUSBControlReqOutOOL].flags = kIOUCStructIStructO;
                    219: 
                    220: 
                    221:     fMethods[kUSBResetDevice].object = NULL;
                    222:     fMethods[kUSBResetDevice].func = NULL;
                    223:     fMethods[kUSBResetDevice].count0 = 0;
                    224:     fMethods[kUSBResetDevice].count1 = 0;
                    225:     fMethods[kUSBResetDevice].flags = kIOUCScalarIScalarO;
                    226: 
                    227:     return true;
                    228: }
                    229: 
                    230: IOExternalMethod *
                    231: IOUSBUserClient::getExternalMethodForIndex( UInt32 index )
                    232: {
                    233:     if(index >= kNumUSBMethods || fMethods[index].object == NULL)
                    234:        return NULL;
                    235:     else
                    236:         return &fMethods[index];
                    237: }
                    238: 
                    239: IOExternalAsyncMethod *
                    240: IOUSBUserClient::getExternalAsyncMethodForIndex( UInt32 index )
                    241: {
                    242:     if(index >= kNumUSBMethods || fAsyncMethods[index].object == NULL)
                    243:         return NULL;
                    244:     else
                    245:         return &fAsyncMethods[index];
                    246: }
                    247: 
                    248: /*
                    249:  * There's a limit of max 6 arguments to user client methods, so the type, recipient and request
                    250:  * are packed into one 16 bit integer.
                    251:  */
                    252: IOReturn
                    253: IOUSBUserClient::ControlReqIn(UInt32 pipe, UInt16 bmreqtypeRequest, UInt16 wValue,
                    254:                UInt16 wIndex, void *buf, UInt32 *size)
                    255: {
                    256:     IOReturn res;
                    257:     IOUSBDevRequest    req;
                    258:     IOUSBPipe *pipeObj;
                    259: 
                    260:     pipeObj = fPipes[pipe];
                    261:     if(!pipeObj)
                    262:         return kIOUSBUnknownPipeErr;
                    263: 
                    264:     req.rqDirection = kUSBIn;
                    265:     req.rqType = (bmreqtypeRequest >> kUSBRqTypeShift) & kUSBRqTypeMask;
                    266:     req.rqRecipient = bmreqtypeRequest & kUSBRqRecipientMask;
                    267:     req.bRequest = bmreqtypeRequest >> 8;
                    268:     OSWriteLittleInt16(&req.wValue, 0, wValue);
                    269:     OSWriteLittleInt16(&req.wIndex, 0, wIndex);
                    270:     OSWriteLittleInt16(&req.wLength, 0, *size);
                    271:     req.pData = buf;
                    272:     res = pipeObj->controlRequest(&req);
                    273: 
                    274:     if(res == kIOReturnSuccess) {
                    275:         *size = req.wLenDone;
                    276:     }
                    277:     else {
                    278:         IOLog("IOUSBUserClient::ControlReqIn err:0x%x\n", res);
                    279:         *size = 0;
                    280:     }
                    281:     return res;
                    282: }
                    283: 
                    284: /*
                    285:  * There's a limit of max 6 arguments to user client methods, so the type, recipient and request
                    286:  * are packed into one 16 bit integer.
                    287:  */
                    288: IOReturn
                    289: IOUSBUserClient::ControlReqOut(UInt32 pipe, UInt16 bmreqtypeRequest, UInt16 wValue,
                    290:                 UInt16 wIndex, void *buf, UInt32 size)
                    291: {
                    292:     IOReturn res;
                    293:     IOUSBDevRequest    req;
                    294:     IOUSBPipe *pipeObj;
                    295: 
                    296:     pipeObj = fPipes[pipe];
                    297:     if(!pipeObj)
                    298:         return kIOUSBUnknownPipeErr;
                    299: 
                    300:     req.rqDirection = kUSBOut;
                    301:     req.rqType = (bmreqtypeRequest >> kUSBRqTypeShift) & kUSBRqTypeMask;
                    302:     req.rqRecipient = bmreqtypeRequest & kUSBRqRecipientMask;
                    303:     req.bRequest = bmreqtypeRequest >> 8;
                    304:     OSWriteLittleInt16(&req.wValue, 0, wValue);
                    305:     OSWriteLittleInt16(&req.wIndex, 0, wIndex);
                    306:     OSWriteLittleInt16(&req.wLength, 0, size);
                    307:     req.pData = buf;
                    308:     res = pipeObj->controlRequest(&req);
                    309: 
                    310:     if(kIOReturnSuccess != res) {
                    311:         IOLog("IOUSBUserClient::ControlReqOut err:0x%x\n", res);
                    312:     }
                    313:     return res;
                    314: }
                    315: 
                    316: IOReturn
                    317: IOUSBUserClient::ControlReqInOOL(DevReqOOL *reqIn, UInt32 *sizeOut, IOByteCount inCount,
                    318:                                 IOByteCount *outCount)
                    319: {
                    320:     IOReturn                   res;
                    321:     IOUSBDevRequestDesc                req;
                    322:     IOMemoryDescriptor *       mem;
                    323:     IOUSBPipe *                        pipeObj;
                    324: 
                    325:     if(inCount != sizeof(DevReqOOL) ||
                    326:        *outCount != sizeof(UInt32))
                    327:         return kIOReturnBadArgument;
                    328: 
                    329:     pipeObj = fPipes[reqIn->pipe];
                    330:     if(!pipeObj)
                    331:         return kIOUSBUnknownPipeErr;
                    332: 
                    333:     mem = IOMemoryDescriptor::withAddress((vm_address_t)reqIn->buf, reqIn->sizeIn,
                    334:                                           kIODirectionIn,
                    335:                                           fTask);
                    336:     if(!mem) {
                    337:         return kIOReturnNoMemory;
                    338:     }
                    339:     req.rqDirection = kUSBIn;
                    340:     req.rqType = (reqIn->bmreqtype >> kUSBRqTypeShift) & kUSBRqTypeMask;
                    341:     req.rqRecipient = reqIn->bmreqtype & kUSBRqRecipientMask;
                    342:     req.bRequest = reqIn->request;
                    343:     OSWriteLittleInt16(&req.wValue, 0, reqIn->wValue);
                    344:     OSWriteLittleInt16(&req.wIndex, 0, reqIn->wIndex);
                    345:     OSWriteLittleInt16(&req.wLength, 0, reqIn->sizeIn);
                    346:     req.pData = mem;
                    347: 
                    348:     res = mem->prepare();
                    349:     if(res == kIOReturnSuccess)
                    350:         res = pipeObj->controlRequest(&req);
                    351:     mem->complete();
                    352:     mem->release();
                    353:     if(res == kIOReturnSuccess) {
                    354:         *sizeOut = req.wLenDone;
                    355:     }
                    356:     else {
                    357:         IOLog("IOUSBUserClient::ControlReqInOOL err:0x%x\n", res);
                    358:         *sizeOut = 0;
                    359:     }
                    360:     *outCount = sizeof(UInt32);
                    361: 
                    362:     return res;
                    363: }
                    364: 
                    365: typedef struct AsyncPB {
                    366:     OSAsyncReference fAsyncRef;
                    367:     UInt32 fMax;
                    368:     IOMemoryDescriptor *fMem;
                    369: };
                    370: 
                    371: IOReturn
                    372: IOUSBUserClient::ControlReqInAsync(OSAsyncReference asyncRef,
                    373:                                    DevReqOOL *reqIn, IOByteCount inCount)
                    374: {
                    375:     IOReturn                   res;
                    376:     IOUSBDevRequestDesc                req;
                    377:     IOUSBPipe *                        pipeObj;
                    378: 
                    379:     IOUSBCompletion            tap;
                    380:     AsyncPB *                  pb = NULL;
                    381:     IOMemoryDescriptor *       mem = NULL;
                    382: 
                    383:     if(inCount != sizeof(DevReqOOL))
                    384:         return kIOReturnBadArgument;
                    385: 
                    386:     pipeObj = fPipes[reqIn->pipe];
                    387:     if(!pipeObj)
                    388:         return kIOUSBUnknownPipeErr;
                    389: 
                    390:     do {
                    391:         mem = IOMemoryDescriptor::withAddress((vm_address_t)reqIn->buf,
                    392:                                             reqIn->sizeIn,
                    393:                                             kIODirectionIn,
                    394:                                             fTask);
                    395:         if(!mem) {
                    396:             res = kIOReturnNoMemory;
                    397:             break;
                    398:         }
                    399:         res = mem->prepare();
                    400:         if(res != kIOReturnSuccess)
                    401:             break;
                    402:         pb = (AsyncPB *)IOMalloc(sizeof(AsyncPB));
                    403:         if(!pb) {
                    404:             res = kIOReturnNoMemory;
                    405:             break;
                    406:         }
                    407: 
                    408:         req.rqDirection = kUSBIn;
                    409:         req.rqType = (reqIn->bmreqtype >> kUSBRqTypeShift) & kUSBRqTypeMask;
                    410:         req.rqRecipient = reqIn->bmreqtype & kUSBRqRecipientMask;
                    411:         req.bRequest = reqIn->request;
                    412:         OSWriteLittleInt16(&req.wValue, 0, reqIn->wValue);
                    413:         OSWriteLittleInt16(&req.wIndex, 0, reqIn->wIndex);
                    414:         OSWriteLittleInt16(&req.wLength, 0, reqIn->sizeIn);
                    415:         req.pData = mem;
                    416: 
                    417:         bcopy(asyncRef, pb->fAsyncRef, sizeof(OSAsyncReference));
                    418:         pb->fMax = reqIn->sizeIn;
                    419:         pb->fMem = mem;
                    420:         tap.target = this;
                    421:         tap.action = &ReqComplete;
                    422:         tap.parameter = pb;
                    423:         res = pipeObj->controlRequest(&req, &tap);
                    424: 
                    425:     } while (false);
                    426:     
                    427:     if(res != kIOReturnSuccess) {
                    428:         IOLog("ControlReqInAsync err 0x%x\n", res);
                    429:         if(mem) {
                    430:             mem->complete();
                    431:             mem->release();
                    432:         }
                    433:         if(pb)
                    434:             IOFree(pb, sizeof(*pb));
                    435:     }
                    436: 
                    437:     return res;
                    438: }
                    439: 
                    440: void
                    441: IOUSBUserClient::ReqComplete(void *obj, void *param, IOReturn res, UInt32 remaining)
                    442: {
                    443:     void *     args[1];
                    444:     AsyncPB * pb = (AsyncPB *)param;
                    445: 
                    446:     if(res == kIOReturnSuccess) {
                    447:         args[0] = (void *)(pb->fMax - remaining);
                    448:     }
                    449:     else {
                    450:         IOLog("IOUSBUserClient::ReqComplete err:0x%x\n", res);
                    451:         args[0] = 0;
                    452:     }
                    453:     pb->fMem->complete();
                    454:     pb->fMem->release();
                    455:     sendAsyncResult(pb->fAsyncRef, res, args, 1);
                    456: 
                    457:     IOFree(pb, sizeof(*pb));
                    458: }
                    459: 
                    460: IOReturn
                    461: IOUSBUserClient::ControlReqOutOOL(DevReqOOL *reqIn, IOByteCount inCount)
                    462: {
                    463:     IOReturn                   res;
                    464:     IOUSBDevRequestDesc                req;
                    465:     IOMemoryDescriptor *       mem;
                    466:     IOUSBPipe *                        pipeObj;
                    467: 
                    468:     if(inCount != sizeof(DevReqOOL))
                    469:         return kIOReturnBadArgument;
                    470: 
                    471:     pipeObj = fPipes[reqIn->pipe];
                    472:     if(!pipeObj)
                    473:         return kIOUSBUnknownPipeErr;
                    474: 
                    475: 
                    476:     mem = IOMemoryDescriptor::withAddress((vm_address_t)reqIn->buf,
                    477:                reqIn->sizeIn, kIODirectionOut, fTask);
                    478:     if(!mem) {
                    479:         return kIOReturnNoMemory;
                    480:     }
                    481:     req.rqDirection = kUSBOut;
                    482:     req.rqType = (reqIn->bmreqtype >> kUSBRqTypeShift) & kUSBRqTypeMask;
                    483:     req.rqRecipient = reqIn->bmreqtype & kUSBRqRecipientMask;
                    484:     req.bRequest = reqIn->request;
                    485:     OSWriteLittleInt16(&req.wValue, 0, reqIn->wValue);
                    486:     OSWriteLittleInt16(&req.wIndex, 0, reqIn->wIndex);
                    487:     OSWriteLittleInt16(&req.wLength, 0, reqIn->sizeIn);
                    488:     req.pData = mem;
                    489: 
                    490:     res = mem->prepare();
                    491:     if(res == kIOReturnSuccess)
                    492:         res = pipeObj->controlRequest(&req);
                    493:     mem->complete();
                    494:     mem->release();
                    495:     return res;
                    496: }
                    497: 
                    498: IOReturn
                    499: IOUSBUserClient::ControlReqOutAsync(OSAsyncReference asyncRef,
                    500:                     DevReqOOL *reqIn, IOByteCount inCount)
                    501: {
                    502:     IOReturn                   res;
                    503:     IOUSBDevRequestDesc                req;
                    504:     IOUSBPipe *                        pipeObj;
                    505: 
                    506:     IOUSBCompletion            tap;
                    507:     AsyncPB *                  pb = NULL;
                    508:     IOMemoryDescriptor *       mem = NULL;
                    509: 
                    510:     if(inCount != sizeof(DevReqOOL))
                    511:         return kIOReturnBadArgument;
                    512: 
                    513:     pipeObj = fPipes[reqIn->pipe];
                    514:     if(!pipeObj)
                    515:         return kIOUSBUnknownPipeErr;
                    516: 
                    517:     do {
                    518:         mem = IOMemoryDescriptor::withAddress((vm_address_t)reqIn->buf,
                    519:                                             reqIn->sizeIn,
                    520:                                             kIODirectionOut,
                    521:                                             fTask);
                    522:         if(!mem) {
                    523:             res = kIOReturnNoMemory;
                    524:             break;
                    525:         }
                    526:         res = mem->prepare();
                    527:         if(res != kIOReturnSuccess)
                    528:             break;
                    529:         pb = (AsyncPB *)IOMalloc(sizeof(AsyncPB));
                    530:         if(!pb) {
                    531:             res = kIOReturnNoMemory;
                    532:             break;
                    533:         }
                    534: 
                    535:         req.rqDirection = kUSBOut;
                    536:         req.rqType = (reqIn->bmreqtype >> kUSBRqTypeShift) & kUSBRqTypeMask;
                    537:         req.rqRecipient = reqIn->bmreqtype & kUSBRqRecipientMask;
                    538:         req.bRequest = reqIn->request;
                    539:         OSWriteLittleInt16(&req.wValue, 0, reqIn->wValue);
                    540:         OSWriteLittleInt16(&req.wIndex, 0, reqIn->wIndex);
                    541:         OSWriteLittleInt16(&req.wLength, 0, reqIn->sizeIn);
                    542:         req.pData = mem;
                    543: 
                    544:         bcopy(asyncRef, pb->fAsyncRef, sizeof(OSAsyncReference));
                    545:         pb->fMax = reqIn->sizeIn;
                    546:         pb->fMem = mem;
                    547:         tap.target = this;
                    548:         tap.action = &ReqComplete;     // Want same number of reply args as for ControlReqIn
                    549:         tap.parameter = pb;
                    550:         res = pipeObj->controlRequest(&req, &tap);
                    551: 
                    552:     } while (false);
                    553: 
                    554:     if(res != kIOReturnSuccess) {
                    555:         IOLog("controlRequest err 0x%x\n", res);
                    556:         if(mem) {
                    557:             mem->complete();
                    558:             mem->release();
                    559:         }
                    560:         if(pb)
                    561:             IOFree(pb, sizeof(*pb));
                    562:     }
                    563: 
                    564:     return res;
                    565: }
                    566: 
                    567: 
                    568: // Controlling pipe state
                    569: 
                    570: IOReturn IOUSBUserClient::getPipeStatus(UInt32 pipe)
                    571: {
                    572:     IOUSBPipe *pipeObj;
                    573:     pipeObj = fPipes[pipe];
                    574:     if(!pipeObj)
                    575:         return kIOUSBUnknownPipeErr;
                    576:     return pipeObj->status();
                    577: }
                    578: 
                    579: IOReturn IOUSBUserClient::abortPipe(UInt32 pipe)
                    580: {
                    581:     IOUSBPipe *pipeObj;
                    582:     pipeObj = fPipes[pipe];
                    583:     if(!pipeObj)
                    584:         return kIOUSBUnknownPipeErr;
                    585:     return pipeObj->abort();
                    586: }
                    587: 
                    588: IOReturn IOUSBUserClient::resetPipe(UInt32 pipe)
                    589: {
                    590:     IOUSBPipe *pipeObj;
                    591:     pipeObj = fPipes[pipe];
                    592:     if(!pipeObj)
                    593:         return kIOUSBUnknownPipeErr;
                    594:     return pipeObj->reset();
                    595: }
                    596: 
                    597: IOReturn IOUSBUserClient::setPipeIdle(UInt32 pipe)
                    598: {
                    599:     return(0);
                    600: }
                    601: 
                    602: IOReturn IOUSBUserClient::setPipeActive(UInt32 pipe)
                    603: {
                    604:     return(0);
                    605: }
                    606: 
                    607: IOReturn IOUSBUserClient::clearPipeStall(UInt32 pipe)
                    608: {
                    609:     IOUSBPipe *pipeObj;
                    610:     pipeObj = fPipes[pipe];
                    611:     if(!pipeObj)
                    612:         return kIOUSBUnknownPipeErr;
                    613:     return pipeObj->clearStall();
                    614: }
                    615: 
                    616: IOReturn
                    617: IOUSBUserClient::ReadPipe(UInt32 pipe, void *buf, UInt32 *size)
                    618: {
                    619:     IOReturn                   res;
                    620:     IOMemoryDescriptor *       mem;
                    621:     IOUSBPipe *                        pipeObj;
                    622: 
                    623:     pipeObj = fPipes[pipe];
                    624:     if(!pipeObj)
                    625:         return kIOUSBUnknownPipeErr;
                    626: 
                    627:     mem = IOMemoryDescriptor::withAddress(buf, *size, kIODirectionIn);
                    628:     if(!mem) {
                    629:         *size = 0;
                    630:         return kIOReturnNoMemory;
                    631:     }
                    632:     res = pipeObj->read(mem, 0, size);
                    633:     if(kIOReturnSuccess != res)
                    634:         *size = 0;
                    635:     mem->release();
                    636: 
                    637:     return res;
                    638: }
                    639: 
                    640: IOReturn
                    641: IOUSBUserClient::WritePipe(UInt32 pipe, void *buf, UInt32 size)
                    642: {
                    643:     IOReturn                   res;
                    644:     IOMemoryDescriptor *       mem;
                    645:     IOUSBPipe *                        pipeObj;
                    646: 
                    647:     pipeObj = fPipes[pipe];
                    648:     if(!pipeObj)
                    649:         return kIOUSBUnknownPipeErr;
                    650: 
                    651:     mem = IOMemoryDescriptor::withAddress(buf, size, kIODirectionOut);
                    652:     if(!mem) {
                    653:         res = kIOReturnNoMemory;
                    654:     }
                    655:     else {
                    656:         res = pipeObj->write(mem);
                    657:         mem->release();
                    658:     }
                    659:     return res;
                    660: }
                    661: 
                    662: /*
                    663:  * Out of line version of read pipe - the buffer isn't mapped (yet) into the kernel task
                    664:  */
                    665: IOReturn
                    666: IOUSBUserClient::ReadPipeOOL(UInt32 pipe, void *buf, UInt32 sizeIn, UInt32 *sizeOut)
                    667: {
                    668:     IOReturn                   res;
                    669:     IOMemoryDescriptor *       mem;
                    670:     IOUSBPipe *                        pipeObj;
                    671: 
                    672:     pipeObj = fPipes[pipe];
                    673:     if(!pipeObj)
                    674:         return kIOUSBUnknownPipeErr;
                    675: 
                    676:     mem = IOMemoryDescriptor::withAddress((vm_address_t)buf, sizeIn,
                    677:                                           kIODirectionIn,
                    678:                                           fTask);
                    679:     if(!mem) {
                    680:         *sizeOut = 0;
                    681:         return kIOReturnNoMemory;
                    682:     }
                    683:     res = mem->prepare();
                    684:     if(res == kIOReturnSuccess)
                    685:         res = pipeObj->read(mem, 0, sizeOut);
                    686:     mem->complete();
                    687:     if(kIOReturnSuccess != res)
                    688:         *sizeOut = 0;
                    689:     mem->release();
                    690: 
                    691:     return res;
                    692: }
                    693: 
                    694: /*
                    695:  * Out of line version of write pipe - the buffer isn't mapped (yet) into the kernel task
                    696:  */
                    697: IOReturn
                    698: IOUSBUserClient::WritePipeOOL(UInt32 pipe, void *buf, UInt32 size)
                    699: {
                    700:     IOReturn                   res;
                    701:     IOMemoryDescriptor *       mem;
                    702:     IOUSBPipe *                        pipeObj;
                    703: 
                    704:     pipeObj = fPipes[pipe];
                    705:     if(!pipeObj)
                    706:         return kIOUSBUnknownPipeErr;
                    707: 
                    708:     mem = IOMemoryDescriptor::withAddress((vm_address_t)buf, size,
                    709:                                           kIODirectionOut,
                    710:                                           fTask);
                    711:     if(!mem) {
                    712:         res = kIOReturnNoMemory;
                    713:     }
                    714:     else {
                    715:         res = mem->prepare();
                    716:         if(res == kIOReturnSuccess)
                    717:             res = pipeObj->write(mem);
                    718:         mem->complete();
                    719:         mem->release();
                    720:     }
                    721:     return res;
                    722: }
                    723: 
                    724: /*
                    725:  * Async version of read pipe - the buffer isn't mapped (yet) into the kernel task
                    726:  */
                    727: IOReturn
                    728: IOUSBUserClient::ReadPipeAsync(OSAsyncReference asyncRef,
                    729:                                UInt32 pipe, void *buf, UInt32 size)
                    730: {
                    731:     IOReturn                   res;
                    732:     IOUSBPipe *                        pipeObj;
                    733:     IOUSBCompletion            tap;
                    734:     IOMemoryDescriptor *       mem = NULL;
                    735:     AsyncPB *                  pb = NULL;
                    736: 
                    737:     pipeObj = fPipes[pipe];
                    738:     if(!pipeObj)
                    739:         return kIOUSBUnknownPipeErr;
                    740: 
                    741:     do {
                    742:         mem = IOMemoryDescriptor::withAddress((vm_address_t)buf, size,
                    743:                                             kIODirectionIn,
                    744:                                             fTask);
                    745:         if(!mem) {
                    746:             res = kIOReturnNoMemory;
                    747:             break;
                    748:         }
                    749:         res = mem->prepare();
                    750:         if(res != kIOReturnSuccess)
                    751:             break;
                    752: 
                    753:         pb = (AsyncPB *)IOMalloc(sizeof(AsyncPB));
                    754:         if(!pb) {
                    755:             res = kIOReturnNoMemory;
                    756:             break;
                    757:         }
                    758: 
                    759:         bcopy(asyncRef, pb->fAsyncRef, sizeof(OSAsyncReference));
                    760:         pb->fMax = size;
                    761:         pb->fMem = mem;
                    762:         tap.target = this;
                    763:         tap.action = &ReqComplete;
                    764:         tap.parameter = pb;
                    765:         res = pipeObj->read(mem, &tap, NULL);
                    766:     } while (false);
                    767:     if(res != kIOReturnSuccess) {
                    768:         if(mem) {
                    769:             mem->complete();
                    770:             mem->release();
                    771:         }
                    772:         if(pb)
                    773:             IOFree(pb, sizeof(*pb));
                    774:     }
                    775: 
                    776:     return res;
                    777: }
                    778: 
                    779: /*
                    780:  * Async version of write pipe - the buffer isn't mapped (yet) into the kernel task
                    781:  */
                    782: IOReturn
                    783: IOUSBUserClient::WritePipeAsync(OSAsyncReference asyncRef,
                    784:                                 UInt32 pipe, void *buf, UInt32 size)
                    785: {
                    786:     IOReturn                   res;
                    787:     IOUSBPipe *                        pipeObj;
                    788:     IOUSBCompletion            tap;
                    789:     IOMemoryDescriptor *       mem = NULL;
                    790:     AsyncPB *                  pb = NULL;
                    791: 
                    792:     pipeObj = fPipes[pipe];
                    793:     if(!pipeObj)
                    794:         return kIOUSBUnknownPipeErr;
                    795: 
                    796:     do {
                    797:         mem = IOMemoryDescriptor::withAddress((vm_address_t)buf, size,
                    798:                                             kIODirectionOut,
                    799:                                             fTask);
                    800:         if(!mem) {
                    801:             res = kIOReturnNoMemory;
                    802:             break;
                    803:         }
                    804:         res = mem->prepare();
                    805:         if(res != kIOReturnSuccess)
                    806:             break;
                    807: 
                    808:         pb = (AsyncPB *)IOMalloc(sizeof(AsyncPB));
                    809:         if(!pb) {
                    810:             res = kIOReturnNoMemory;
                    811:             break;
                    812:         }
                    813: 
                    814:         bcopy(asyncRef, pb->fAsyncRef, sizeof(OSAsyncReference));
                    815:         pb->fMax = size;
                    816:         pb->fMem = mem;
                    817:         tap.target = this;
                    818:         tap.action = &ReqComplete;
                    819:         tap.parameter = pb;
                    820:         res = pipeObj->write(mem, &tap);
                    821:     } while (false);
                    822:     if(res != kIOReturnSuccess) {
                    823:         if(mem) {
                    824:             mem->complete();
                    825:             mem->release();
                    826:         }
                    827:         if(pb)
                    828:             IOFree(pb, sizeof(*pb));
                    829:     }
                    830:     return res;
                    831: }
                    832: 
                    833: IOReturn IOUSBUserClient::ClosePipe(UInt32 pipe)
                    834: {
                    835:     fPipes[pipe] = 0;
                    836:     return kIOReturnSuccess;
                    837: }
                    838: 
                    839: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    840: 
                    841: OSDefineMetaClassAndStructors(IOUSBDeviceUserClient, IOUSBUserClient)
                    842: 
                    843: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    844: 
                    845: IOUSBDeviceUserClient *IOUSBDeviceUserClient::withTask(task_t owningTask)
                    846: {
                    847:     IOUSBDeviceUserClient *me;
                    848: 
                    849:     me = new IOUSBDeviceUserClient;
                    850:     if(me) {
                    851:         if(!me->init()) {
                    852:             me->release();
                    853:             return NULL;
                    854:         }
                    855:         me->fTask = owningTask;
                    856:     }
                    857:     return me;
                    858: }
                    859: 
                    860: bool IOUSBDeviceUserClient::start( IOService * provider )
                    861: {
                    862:     assert(OSDynamicCast(IOUSBDevice, provider));
                    863:     if(!IOUSBUserClient::start(provider))
                    864:         return false;
                    865:     fOwner = (IOUSBDevice *)provider;
                    866:     fOwner->retain();
                    867:     fInterfaces = OSSet::withCapacity(1);
                    868:     if(!fInterfaces)
                    869:         return false;
                    870: 
                    871:     // initialize the call structures valid for IOUSBDevice
                    872:     fMethods[kUSBSetConfig].object = provider;
                    873:     fMethods[kUSBSetConfig].func = (IOMethod)&IOUSBDevice::SetConfiguration;
                    874:     fMethods[kUSBSetConfig].count0 = 1;
                    875:     fMethods[kUSBSetConfig].count1 = 0;
                    876:     fMethods[kUSBSetConfig].flags = kIOUCScalarIScalarO;
                    877: 
                    878:     fMethods[kUSBGetConfigDescriptor].object = this;
                    879:     fMethods[kUSBGetConfigDescriptor].func =
                    880:         (IOMethod)&IOUSBDeviceUserClient::GetConfigDescriptor;
                    881:     fMethods[kUSBGetConfigDescriptor].count0 = 1;
                    882:     fMethods[kUSBGetConfigDescriptor].count1 = 0xffffffff; // variable
                    883:     fMethods[kUSBGetConfigDescriptor].flags = kIOUCScalarIStructO;
                    884: 
                    885:     fMethods[kUSBOpenPipe].object = this;
                    886:     fMethods[kUSBOpenPipe].func =
                    887:         (IOMethod)&IOUSBDeviceUserClient::OpenPipe;
                    888:     fMethods[kUSBOpenPipe].count0 = 4;
                    889:     fMethods[kUSBOpenPipe].count1 = 1;
                    890:     fMethods[kUSBOpenPipe].flags = kIOUCScalarIScalarO;
                    891: 
                    892:     fMethods[kUSBResetDevice].object = provider;
                    893:     fMethods[kUSBResetDevice].func =
                    894:         (IOMethod)&IOUSBDevice::resetDevice;
                    895:     fMethods[kUSBResetDevice].count0 = 0;
                    896:     fMethods[kUSBResetDevice].count1 = 0;
                    897:     fMethods[kUSBResetDevice].flags = kIOUCScalarIScalarO;
                    898: 
                    899:     return true;
                    900: }
                    901: 
                    902: IOReturn IOUSBDeviceUserClient::clientClose( void )
                    903: {
                    904:     if(fInterfaces) {
                    905:         OSCollectionIterator *iter;
                    906: 
                    907:         iter = OSCollectionIterator::withCollection(fInterfaces);
                    908:         if(iter) {
                    909:             OSObject *obj;
                    910:             while( (obj=iter->getNextObject()) ) {
                    911:                 ((IOService *)obj)->close(this);
                    912:             }
                    913:             iter->release();
                    914:         }
                    915:         fInterfaces->release();
                    916:         fInterfaces = NULL;
                    917:     }
                    918:     if(fOwner) {
                    919:         detach( fOwner);
                    920:         fOwner->release();
                    921:         fOwner = NULL;
                    922:     }
                    923:     return IOUSBUserClient::clientClose();
                    924: }
                    925: 
                    926: IOReturn
                    927: IOUSBDeviceUserClient::OpenPipe(UInt32 configIndex,
                    928:                           UInt32 intfNo, UInt32 altSet, UInt32 endPtOff, UInt32 *pipe)
                    929: {
                    930:     IOReturn res;
                    931:     IOUSBInterface *intf;
                    932:     const IOUSBInterfaceDescriptor *id = NULL;
                    933:     UInt8 configVal;
                    934:     IOUSBDevice::FindInterfaceRequest request;
                    935:     UInt32 i;
                    936:     const IOUSBConfigurationDescriptor *config;
                    937: 
                    938:     config = fOwner->getFullConfigurationDescriptor(configIndex);
                    939:     configVal = config->configValue;
                    940: 
                    941:     intf = NULL;
                    942:     request.theClass = 0;
                    943:     request.subClass = 0;
                    944:     request.protocol = 0;
                    945:     request.maxPower = 0;
                    946: 
                    947:     while( (intf = fOwner->findNextInterface(intf, &request))) {
                    948:         if(intf->getConfigValue() == configVal) {
                    949:             id = intf->interfaceDescriptor();
                    950:             if(id->interfaceNumber == intfNo &&
                    951:                     id->alternateSetting == altSet)
                    952:                 break;
                    953:         }
                    954:         intf->release();
                    955:         // Reset request fields to wildcard values.
                    956:         request.theClass = 0;
                    957:         request.subClass = 0;
                    958:         request.protocol = 0;
                    959:         request.maxPower = 0;
                    960:     }
                    961: 
                    962:     if(!intf)
                    963:         return kIOUSBInterfaceNotFound;
                    964: 
                    965:     if(id->numEndpoints <= endPtOff)
                    966:         return kIOUSBUnknownPipeErr;
                    967: 
                    968:     do {
                    969:         IOUSBFindEndpointRequest findPipe;
                    970:         IOUSBPipe *pipeObj;
                    971:         if(!fInterfaces->member(intf)) {
                    972:             if(!intf->open(this)) {
                    973:                 res = kIOReturnExclusiveAccess;
                    974:                 break;
                    975:             }
                    976:             fInterfaces->setObject(intf);
                    977:         }
                    978: 
                    979:         // Loop through pipes the requested number of times
                    980:         pipeObj = NULL;
                    981:         endPtOff++; // Easier to be 1-based.
                    982:         for(i=0; i<endPtOff; i++) {
                    983:             findPipe.type = kUSBAnyType;
                    984:             findPipe.direction = kUSBAnyDirn;
                    985:             pipeObj = intf->findNextPipe(pipeObj, &findPipe);
                    986:             if(pipeObj == NULL) {
                    987:                 res = kIOUSBEndpointNotFound;
                    988:                 break;
                    989:             }
                    990:         }
                    991:         if(i != endPtOff) {
                    992:            res = kIOUSBEndpointNotFound;
                    993:             break;
                    994:         }
                    995:         for(i=1; i<kUSBMaxPipes; i++) {
                    996:             if(!fPipes[i]) {
                    997:                 fPipes[i] = pipeObj;
                    998:                 break;
                    999:             }
                   1000:         }
                   1001:         if(i >= kUSBMaxPipes) {
                   1002:             res = kIOUSBTooManyPipesErr;
                   1003:             break;
                   1004:         }
                   1005:         *pipe = i;
                   1006:         res = kIOReturnSuccess;
                   1007:     } while(false);
                   1008:     if(intf)
                   1009:         intf->release();
                   1010:     return res;
                   1011: }
                   1012: 
                   1013: IOReturn
                   1014: IOUSBDeviceUserClient::GetConfigDescriptor(UInt8 configIndex,
                   1015:                         IOUSBConfigurationDescriptorPtr desc, UInt32 *size)
                   1016: {
                   1017:     UInt16 length;
                   1018:     const IOUSBConfigurationDescriptor *cached;
                   1019: 
                   1020:     cached = fOwner->getFullConfigurationDescriptor(configIndex);
                   1021:     length = OSReadLittleInt16(&cached->totalLength, 0);
                   1022:     if(length < *size)
                   1023:         *size = length;
                   1024:     bcopy(cached, desc, *size);
                   1025:     return kIOReturnSuccess;
                   1026: }
                   1027: 
                   1028: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   1029: 
                   1030: OSDefineMetaClassAndStructors(IOUSBInterfaceUserClient, IOUSBUserClient)
                   1031: 
                   1032: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   1033: 
                   1034: IOUSBInterfaceUserClient *IOUSBInterfaceUserClient::withTask(task_t owningTask)
                   1035: {
                   1036:     IOUSBInterfaceUserClient *me;
                   1037: 
                   1038:     me = new IOUSBInterfaceUserClient;
                   1039:     if(me) {
                   1040:         if(!me->init()) {
                   1041:             me->release();
                   1042:             return NULL;
                   1043:         }
                   1044:         me->fTask = owningTask;
                   1045:     }
                   1046:     return me;
                   1047: }
                   1048: 
                   1049: bool IOUSBInterfaceUserClient::start( IOService * provider )
                   1050: {
                   1051:     assert(OSDynamicCast(IOUSBInterface, provider));
                   1052:     if(!IOUSBUserClient::start(provider))
                   1053:         return false;
                   1054:     fOwner = (IOUSBInterface *)provider;
                   1055:     fOwner->retain();
                   1056: 
                   1057: // initialize the call structures valid for IOUSBInterface
                   1058:     fMethods[kUSBGetConfigDescriptor].object = this;
                   1059:     fMethods[kUSBGetConfigDescriptor].func =
                   1060:         (IOMethod)&IOUSBInterfaceUserClient::GetConfigDescriptor;
                   1061:     fMethods[kUSBGetConfigDescriptor].count0 = 1;
                   1062:     fMethods[kUSBGetConfigDescriptor].count1 = 0xffffffff; // variable
                   1063:     fMethods[kUSBGetConfigDescriptor].flags = kIOUCScalarIStructO;
                   1064: 
                   1065:     fMethods[kUSBOpenPipe].object = this;
                   1066:     fMethods[kUSBOpenPipe].func =
                   1067:         (IOMethod)&IOUSBInterfaceUserClient::OpenPipe;
                   1068:     fMethods[kUSBOpenPipe].count0 = 4;
                   1069:     fMethods[kUSBOpenPipe].count1 = 1;
                   1070:     fMethods[kUSBOpenPipe].flags = kIOUCScalarIScalarO;
                   1071: 
                   1072:     return true;
                   1073: }
                   1074: 
                   1075: IOReturn IOUSBInterfaceUserClient::clientClose( void )
                   1076: {
                   1077:     if(fOwner) {
                   1078:         if(fOpen) {
                   1079:             fOwner->close(this);
                   1080:             fOpen = false;
                   1081:        }
                   1082:         detach( fOwner);
                   1083:         fOwner->release();
                   1084:         fOwner = NULL;
                   1085:     }
                   1086:     return IOUSBUserClient::clientClose();
                   1087: }
                   1088: 
                   1089: IOReturn
                   1090: IOUSBInterfaceUserClient::OpenPipe(UInt32 configIndex,
                   1091:                           UInt32 intfNo, UInt32 altSet, UInt32 endPtOff, UInt32 *pipe)
                   1092: {
                   1093:     IOReturn res;
                   1094:     const IOUSBInterfaceDescriptor *id = fOwner->interfaceDescriptor();
                   1095:     UInt32 i;
                   1096:     const IOUSBConfigurationDescriptor *config;
                   1097: 
                   1098:     config = fOwner->device()->getFullConfigurationDescriptor(configIndex);
                   1099: 
                   1100:     if(config->configValue != fOwner->getConfigValue())
                   1101:         return kIOUSBConfigNotFound;
                   1102: 
                   1103:     if(intfNo != id->interfaceNumber ||
                   1104:        altSet != id->alternateSetting)
                   1105:         return kIOUSBInterfaceNotFound;
                   1106: 
                   1107:     if(id->numEndpoints <= endPtOff)
                   1108:         return kIOUSBUnknownPipeErr;
                   1109: 
                   1110:     do {
                   1111:         IOUSBFindEndpointRequest findPipe;
                   1112:         IOUSBPipe *pipeObj;
                   1113:         if(!fOpen) {
                   1114:             if(!fOwner->open(this)) {
                   1115:                 res = kIOReturnExclusiveAccess;
                   1116:                 break;
                   1117:             }
                   1118:             fOpen = true;
                   1119:         }
                   1120: 
                   1121:         // Loop through pipes the requested number of times
                   1122:         pipeObj = NULL;
                   1123:         endPtOff++; // Easier to be 1-based.
                   1124:         for(i=0; i<endPtOff; i++) {
                   1125:             findPipe.type = kUSBAnyType;
                   1126:             findPipe.direction = kUSBAnyDirn;
                   1127:             pipeObj = fOwner->findNextPipe(pipeObj, &findPipe);
                   1128:             if(pipeObj == NULL) {
                   1129:                 res = kIOUSBEndpointNotFound;
                   1130:                 break;
                   1131:             }
                   1132:         }
                   1133:         if(i != endPtOff) {
                   1134:            res = kIOUSBEndpointNotFound;
                   1135:             break;
                   1136:         }
                   1137:         for(i=1; i<kUSBMaxPipes; i++) {
                   1138:             if(!fPipes[i]) {
                   1139:                 fPipes[i] = pipeObj;
                   1140:                 break;
                   1141:             }
                   1142:         }
                   1143:         if(i >= kUSBMaxPipes) {
                   1144:             res = kIOUSBTooManyPipesErr;
                   1145:             break;
                   1146:         }
                   1147:         *pipe = i;
                   1148:         res = kIOReturnSuccess;
                   1149:     } while(false);
                   1150:     return res;
                   1151: }
                   1152: 
                   1153: IOReturn
                   1154: IOUSBInterfaceUserClient::GetConfigDescriptor(UInt8 configIndex,
                   1155:                         IOUSBConfigurationDescriptorPtr desc, UInt32 *size)
                   1156: {
                   1157:     UInt16 length;
                   1158:     const IOUSBConfigurationDescriptor *cached;
                   1159: 
                   1160:     cached = fOwner->device()->getFullConfigurationDescriptor(configIndex);
                   1161:     length = OSReadLittleInt16(&cached->totalLength, 0);
                   1162:     if(length < *size)
                   1163:         *size = length;
                   1164:     bcopy(cached, desc, *size);
                   1165:     return kIOReturnSuccess;
                   1166: }

unix.superglobalmegacorp.com

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