Annotation of XNU/iokit/Families/IOUSBBus/IOUSBUserClient.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) 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.