|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.