|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * HISTORY ! 26: * 08 Dec 98 ehewitt created. ! 27: * ! 28: */ ! 29: ! 30: #include <libkern/OSByteOrder.h> ! 31: ! 32: #define DEBUGGING_LEVEL 0 // 1 = low; 2 = high; 3 = extreme ! 33: #define DEBUGLOG kprintf ! 34: ! 35: #include <libkern/c++/OSDictionary.h> ! 36: #include <libkern/c++/OSData.h> ! 37: #include <IOKit/usb/IOUSBController.h> ! 38: #include <IOKit/usb/IOUSBDevice.h> ! 39: #include "IOUSBRootHubDevice.h" ! 40: #include <IOKit/assert.h> ! 41: #include <IOKit/IOSyncer.h> ! 42: ! 43: enum { ! 44: kSetupSent = 0x01, ! 45: kDataSent = 0x02, ! 46: kStatusSent = 0x04, ! 47: kSetupBack = 0x10, ! 48: kDataBack = 0x20, ! 49: kStatusBack = 0x40 ! 50: }; ! 51: ! 52: #define kUSBSetup kUSBNone ! 53: ! 54: void IOUSBSyncCompletion(void * target, ! 55: void * parameter, ! 56: IOReturn status, ! 57: UInt32 bufferSizeRemaining) ! 58: { ! 59: IOSyncer *syncer = (IOSyncer *)target; ! 60: ! 61: if(parameter != NULL) { ! 62: *(UInt32 *)parameter -= bufferSizeRemaining; ! 63: } ! 64: ! 65: syncer->signal(status); ! 66: } ! 67: ! 68: void IOUSBSyncIsoCompletion(void *target, void * parameter, ! 69: IOReturn status, ! 70: IOUSBIsocFrame *pFrames) ! 71: { ! 72: IOSyncer *syncer = (IOSyncer *)target; ! 73: syncer->signal(status); ! 74: } ! 75: ! 76: ! 77: #define super IOUSBBus ! 78: ! 79: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 80: ! 81: OSDefineMetaClass( IOUSBController, IOUSBBus ) ! 82: OSDefineAbstractStructors(IOUSBController, IOUSBBus) ! 83: ! 84: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 85: ! 86: bool IOUSBController::init(OSDictionary * propTable) ! 87: { ! 88: if (!super::init(propTable)) return false; ! 89: ! 90: return (true); ! 91: } ! 92: ! 93: bool IOUSBController::start( IOService * provider ) ! 94: { ! 95: IOUSBDeviceDescriptor desc; ! 96: ! 97: ! 98: if( !super::start(provider)) ! 99: return (false); ! 100: ! 101: do { ! 102: ! 103: /* ! 104: * Initialize the Workloop and Command gate ! 105: */ ! 106: _workLoop = IOWorkLoop::workLoop(); ! 107: if (!_workLoop) ! 108: { ! 109: IOLog("%s: unable to create workloop\n", getName()); ! 110: break; ! 111: } ! 112: ! 113: _commandGate = IOCommandGate:: commandGate(this, NULL); ! 114: if (!_commandGate) ! 115: { ! 116: IOLog("%s: unable to create command gate\n", getName()); ! 117: break; ! 118: } ! 119: ! 120: if (_workLoop->addEventSource(_commandGate) != kIOReturnSuccess) ! 121: { ! 122: IOLog("%s: unable to add command gate\n", getName()); ! 123: break; ! 124: } ! 125: ! 126: /* ! 127: * Initialize the UIM ! 128: */ ! 129: if (UIMInitialize(provider) != kIOReturnSuccess) ! 130: { ! 131: IOLog("%s: unable to initialize UIM\n", getName()); ! 132: break; ! 133: } ! 134: ! 135: /* ! 136: * Initialize device zero ! 137: */ ! 138: _devZeroLock = IOLockAlloc(); ! 139: ! 140: /* ! 141: * Create the root hub device ! 142: */ ! 143: if (getRootHubDeviceDescriptor( &desc ) != kIOReturnSuccess) ! 144: { ! 145: IOLog("%s: unable to get root hub descriptor\n", getName()); ! 146: break; ! 147: } ! 148: ! 149: _rootHubDevice = new IOUSBRootHubDevice; ! 150: ! 151: CreateDevice(_rootHubDevice, getNewAddress(), &desc, ! 152: kUSBHighSpeed, kUSB500mAAvailable); ! 153: if (_rootHubDevice == 0) ! 154: { ! 155: IOLog("%s: unable to initialize root hub\n", getName()); ! 156: break; ! 157: } ! 158: _rootHubDevice->registerService(); ! 159: ! 160: return(true); ! 161: ! 162: } while (false); ! 163: ! 164: if (_workLoop) _workLoop->release(); ! 165: if (_commandGate) _commandGate->release(); ! 166: ! 167: return( false ); ! 168: } ! 169: ! 170: IOWorkLoop *IOUSBController::getWorkLoop() const ! 171: { ! 172: return _workLoop; ! 173: } ! 174: ! 175: IOUSBDevice *IOUSBController::newDevice() ! 176: { ! 177: return(new IOUSBDevice); ! 178: } ! 179: ! 180: /* ! 181: * CreateDevice: ! 182: * This method just creates the device so we can minimally talk to it, e.g. ! 183: * get it's descriptor. After this method, the device is not ready for ! 184: * prime time. ! 185: */ ! 186: IOReturn IOUSBController::CreateDevice(IOUSBDevice *newDevice, ! 187: USBDeviceAddress deviceAddress, ! 188: IOUSBDeviceDescriptor *desc, ! 189: UInt8 speed, ! 190: UInt32 powerAvailable) ! 191: { ! 192: OSDictionary *propTable = 0; ! 193: OSData *data; ! 194: OSNumber *offset; ! 195: char location[8]; ! 196: ! 197: #if (DEBUGGING_LEVEL > 0) ! 198: DEBUGLOG("%s: CreateDevice: addr=%d, speed=%s, power=%d\n", getName(), ! 199: deviceAddress, speed ? "low" : "high", powerAvailable*2); ! 200: #endif ! 201: ! 202: do { ! 203: propTable = OSDictionary::withCapacity(4); ! 204: if (!propTable) ! 205: break; ! 206: ! 207: if (desc) { ! 208: data = OSData::withBytes( (void *)desc, sizeof( *desc )); ! 209: if(data) { ! 210: propTable->setObject("device descriptor", data); ! 211: data->release(); ! 212: } ! 213: offset = OSNumber::withNumber(desc->deviceClass, 8); ! 214: if(offset) { ! 215: propTable->setObject("class", offset); ! 216: offset->release(); ! 217: } ! 218: offset = OSNumber::withNumber(desc->deviceSubClass, 8); ! 219: if(offset) { ! 220: propTable->setObject("subClass", offset); ! 221: offset->release(); ! 222: } ! 223: offset = OSNumber::withNumber(desc->protocol, 8); ! 224: if(offset) { ! 225: propTable->setObject("protocol", offset); ! 226: offset->release(); ! 227: } ! 228: offset = OSNumber::withNumber(OSReadLittleInt16(&desc->vendor, 0), 16); ! 229: if(offset) { ! 230: propTable->setObject("vendor", offset); ! 231: offset->release(); ! 232: } ! 233: offset = OSNumber::withNumber(OSReadLittleInt16(&desc->product, 0), 16); ! 234: if(offset) { ! 235: propTable->setObject("product", offset); ! 236: offset->release(); ! 237: } ! 238: offset = OSNumber::withNumber(OSReadLittleInt16(&desc->devRel, 0), 16); ! 239: if(offset) { ! 240: propTable->setObject("version", offset); ! 241: offset->release(); ! 242: } ! 243: } ! 244: ! 245: data = OSData::withBytes( (void *)&deviceAddress, ! 246: sizeof( deviceAddress )); ! 247: if (data) { ! 248: propTable->setObject("device address", data); ! 249: data->release(); ! 250: } ! 251: ! 252: data = OSData::withBytes( (void *)&powerAvailable, ! 253: sizeof( powerAvailable )); ! 254: if (data) { ! 255: propTable->setObject("bus power available", data); ! 256: data->release(); ! 257: } ! 258: ! 259: data = OSData::withBytes( (void *)&speed, sizeof( speed )); ! 260: if (data) { ! 261: propTable->setObject("low speed device", data); ! 262: data->release(); ! 263: } ! 264: ! 265: if (!newDevice->init(propTable)) ! 266: break; ! 267: ! 268: propTable->release(); // done with it after init ! 269: propTable = 0; ! 270: ! 271: sprintf( location, "%x", deviceAddress ); ! 272: newDevice->setLocation(location); ! 273: ! 274: if (!newDevice->attach(this)) ! 275: break; ! 276: ! 277: return(kIOReturnSuccess); ! 278: ! 279: } while (false); ! 280: ! 281: if (propTable) ! 282: propTable->release(); ! 283: ! 284: return(kIOReturnNoMemory); ! 285: } ! 286: ! 287: /* ! 288: * deviceRequest: ! 289: * Queue up a low level device request. It's very simple because the ! 290: * device has done all the error checking. Commands get allocated here and get ! 291: * deallocated in the handlers. ! 292: * ! 293: */ ! 294: IOReturn IOUSBController::deviceRequest(IOUSBDevRequest * request, ! 295: IOUSBCompletion * completion, ! 296: USBDeviceAddress address, UInt8 ep) ! 297: { ! 298: // FIXME -- should preallocate a bunch of 'command's ! 299: IOUSBCommand *command = (IOUSBCommand *)IOMalloc(sizeof(IOUSBCommand)); ! 300: IOReturn err = kIOReturnSuccess; ! 301: ! 302: do ! 303: { ! 304: command->selector = DEVICE_REQUEST; ! 305: command->request = request; ! 306: command->address = address; ! 307: command->endpoint = ep; ! 308: command->type = kUSBControl; ! 309: command->buffer = 0; // no buffer for device requests ! 310: command->completion = *completion; ! 311: ! 312: if (_commandGate == 0) ! 313: { ! 314: err = kIOReturnInternalError; ! 315: break; ! 316: } ! 317: ! 318: err = _commandGate->runAction(doControlTransfer, command); ! 319: if ( err) ! 320: break; ! 321: ! 322: return (err); ! 323: } while (0); ! 324: ! 325: /* Free/give back the command */ ! 326: IOFree(command, sizeof(IOUSBCommand)); ! 327: ! 328: return(err); ! 329: } ! 330: ! 331: IOReturn IOUSBController::deviceRequest(IOUSBDevRequestDesc * request, ! 332: IOUSBCompletion * completion, ! 333: USBDeviceAddress address, UInt8 ep) ! 334: { ! 335: // FIXME -- should preallocate a bunch of 'command's ! 336: IOUSBCommand *command = (IOUSBCommand *)IOMalloc(sizeof(IOUSBCommand)); ! 337: IOReturn err = kIOReturnSuccess; ! 338: ! 339: do ! 340: { ! 341: command->selector = DEVICE_REQUEST_DESC; ! 342: // IOUSBDevRequest and IOUSBDevRequestDesc are same except for ! 343: // pData (void * or descriptor). ! 344: command->request = (IOUSBDevRequest *)request; ! 345: command->address = address; ! 346: command->endpoint = ep; ! 347: command->type = kUSBControl; ! 348: command->buffer = request->pData; ! 349: command->completion = *completion; ! 350: ! 351: if (_commandGate == 0) ! 352: { ! 353: err = kIOReturnInternalError; ! 354: break; ! 355: } ! 356: ! 357: err = _commandGate->runAction(doControlTransfer, command); ! 358: if ( err) ! 359: break; ! 360: ! 361: return (err); ! 362: } while (0); ! 363: ! 364: /* Free/give back the command */ ! 365: IOFree(command, sizeof(IOUSBCommand)); ! 366: ! 367: return(err); ! 368: } ! 369: ! 370: USBDeviceAddress IOUSBController::getNewAddress(void) ! 371: { ! 372: int i; ! 373: bool assigned[kUSBMaxDevices]; ! 374: OSIterator * clients; ! 375: ! 376: bzero(assigned, sizeof(assigned)); ! 377: ! 378: clients = getClientIterator(); ! 379: if(clients) { ! 380: OSObject *next; ! 381: while((next = clients->getNextObject())) { ! 382: IOUSBDevice *testIt = OSDynamicCast(IOUSBDevice, next); ! 383: if(testIt) { ! 384: assigned[testIt->address()] = true; ! 385: } ! 386: } ! 387: clients->release(); ! 388: } ! 389: ! 390: for(i=1; i<kUSBMaxDevices; i++) { ! 391: if(!assigned[i]) ! 392: return i; ! 393: } ! 394: ! 395: return(0); // No free device addresses! ! 396: } ! 397: ! 398: /* ! 399: * ControlPacket: ! 400: * Send a USB control packet which consists of at least two stages: setup ! 401: * and status. Optionally there can be multiple data stages. ! 402: * ! 403: */ ! 404: IOReturn IOUSBController::ControlTransaction(IOUSBCommand *command) ! 405: { ! 406: IOUSBDevRequest *request = command->request; ! 407: UInt8 direction = request->rqDirection; ! 408: UInt8 endpoint = command->endpoint; ! 409: UInt16 wLength = OSReadLittleInt16(&request->wLength, 0); ! 410: IOReturn err = kIOReturnSuccess; ! 411: IOUSBCompletion completion; ! 412: ! 413: do ! 414: { ! 415: // Setup Stage ! 416: #if (DEBUGGING_LEVEL > 1) ! 417: DEBUGLOG("\tQueueing Setup TD (dir=%d) packet=0x%lx 0x%lx\n", ! 418: direction, *(UInt32*)request, *((UInt32*)request+1)); ! 419: #endif ! 420: ! 421: completion.target = (void *)this; ! 422: completion.action = &IOUSBController::ControlPacketHandler; ! 423: completion.parameter = (void *)command; ! 424: ! 425: command->dataRemaining = wLength; ! 426: command->stage = kSetupSent; ! 427: err = UIMCreateControlTransfer( ! 428: command->address /*functionAddress*/, ! 429: endpoint /*endpointNumber*/, ! 430: completion /*completion*/, ! 431: request /*packet*/, ! 432: true /*bufferRounding*/, ! 433: 8 /*packet size*/, ! 434: kUSBSetup /*direction*/); ! 435: if (err) ! 436: { ! 437: IOLog("ControlTransaction: control packet 1 error %d\n", err); ! 438: break; ! 439: } ! 440: ! 441: // Data Stage ! 442: if (wLength != 0 && request->pData != 0) ! 443: { ! 444: #if (DEBUGGING_LEVEL > 1) ! 445: DEBUGLOG("\tQueueing Data TD (dir=%d, wLength=0x%x, pData=%lx)\n", direction, ! 446: wLength, request->pData); ! 447: #endif ! 448: command->stage |= kDataSent; ! 449: if(command->selector == DEVICE_REQUEST_DESC) ! 450: err = UIMCreateControlTransfer( ! 451: command->address /*functionAddress*/, ! 452: endpoint /*endpointNumber*/, ! 453: completion /*completion*/, ! 454: command->buffer /*buffer*/, ! 455: true /*bufferRounding*/, ! 456: wLength /*bufferSize*/, ! 457: direction /*direction*/); ! 458: else ! 459: err = UIMCreateControlTransfer( ! 460: command->address /*functionAddress*/, ! 461: endpoint /*endpointNumber*/, ! 462: completion /*completion*/, ! 463: request->pData /*buffer*/, ! 464: true /*bufferRounding*/, ! 465: wLength /*bufferSize*/, ! 466: direction /*direction*/); ! 467: if (err) ! 468: { ! 469: IOLog("ControlTransaction: control packet 2 error %d\n", err); ! 470: break; ! 471: } ! 472: ! 473: direction = kUSBOut + kUSBIn - direction; // swap direction ! 474: } ! 475: else ! 476: direction = kUSBIn; ! 477: ! 478: // Status Stage ! 479: #if (DEBUGGING_LEVEL > 1) ! 480: DEBUGLOG("\tQueueing Status TD (dir=%d)\n", direction); ! 481: #endif ! 482: command->stage |= kStatusSent; ! 483: err = UIMCreateControlTransfer( ! 484: command->address /*functionAddress*/, ! 485: endpoint /*endpointNumber*/, ! 486: completion /*completion*/, ! 487: (void *)0 /*buffer*/, ! 488: true /*bufferRounding*/, ! 489: 0 /*bufferSize*/, ! 490: direction /*direction*/); ! 491: if (err) ! 492: { ! 493: IOLog("ControlTransaction: control packet 3 error %d\n", err); ! 494: break; ! 495: } ! 496: } while(false); ! 497: ! 498: if (err) ! 499: complete(command->completion, err, 0); ! 500: return(err); ! 501: } ! 502: ! 503: /* ! 504: * ControlPacketHandler: ! 505: * Handle all three types of control packets and maintain what stage ! 506: * we're at. When we receive the last one, then call the clients ! 507: * completion routine. ! 508: */ ! 509: void IOUSBController::ControlPacketHandler(void * parameter, ! 510: IOReturn status, ! 511: UInt32 bufferSizeRemaining) ! 512: { ! 513: IOUSBCommand *command = (IOUSBCommand *)parameter; ! 514: IOUSBDevRequest *request; ! 515: UInt8 sent, back, todo; ! 516: ! 517: #if (DEBUGGING_LEVEL > 1) ! 518: DEBUGLOG("ControlPacketHandler lParam=%lx status=0x%x bufferSizeRemaining=0x%x\n", parameter, status, bufferSizeRemaining); ! 519: #endif ! 520: ! 521: if (command == 0) ! 522: return; ! 523: ! 524: request = command->request; ! 525: ! 526: sent = (command->stage & 0x0f) << 4; ! 527: back = command->stage & 0xf0; ! 528: todo = sent ^ back; /* thats xor */ ! 529: ! 530: if((todo & kSetupBack) != 0) ! 531: command->stage |= kSetupBack; ! 532: else if((todo & kDataBack) != 0) ! 533: { ! 534: /* This is the data transport phase, so this is the interesting one */ ! 535: command->stage |= kDataBack; ! 536: command->dataRemaining = bufferSizeRemaining; ! 537: } ! 538: else if((todo & kStatusBack) != 0) ! 539: command->stage |= kStatusBack; ! 540: else ! 541: IOLog("ControlPacketHandler: Spare transactions, This seems to be harmless"); ! 542: ! 543: back = command->stage & 0xf0; ! 544: todo = sent ^ back; /* thats xor */ ! 545: ! 546: if (status != kIOReturnSuccess) ! 547: { ! 548: USBDeviceAddress addr = command->address; ! 549: UInt8 endpt = command->endpoint; ! 550: ! 551: command->status = status; ! 552: ! 553: #if (DEBUGGING_LEVEL > 0) ! 554: DEBUGLOG("ControlPacketHandler: error %d occured. todo = %d\n", status, todo); ! 555: ! 556: #endif ! 557: UIMClearEndpointStall(addr, endpt, kUSBAnyDirn); ! 558: } ! 559: if (todo == 0) ! 560: { ! 561: #if (DEBUGGING_LEVEL > 0) ! 562: DEBUGLOG("ControlPacketHandler: transaction complete status=%d\n", status); ! 563: #endif ! 564: ! 565: /* Call the clients handler */ ! 566: complete(command->completion, status, command->dataRemaining); ! 567: ! 568: /* Free/give back the command */ ! 569: IOFree(command, sizeof(IOUSBCommand)); ! 570: } ! 571: } ! 572: ! 573: /* ! 574: * InterruptTransaction: ! 575: * Send a USB interrupt packet. ! 576: * ! 577: */ ! 578: IOReturn IOUSBController::InterruptTransaction(IOUSBCommand *command) ! 579: { ! 580: IOReturn err = kIOReturnSuccess; ! 581: IOUSBCompletion completion; ! 582: ! 583: completion.target = (void *)this; ! 584: completion.action = &IOUSBController::InterruptPacketHandler; ! 585: completion.parameter = (void *)command; ! 586: ! 587: err = UIMCreateInterruptTransfer( ! 588: command->address /*functionAddress*/, ! 589: command->endpoint /*endpointNumber*/, ! 590: completion /*completion*/, ! 591: command->buffer /*buffer*/, ! 592: true /*bufferRounding*/, ! 593: command->buffer->getLength() /*bufferSize*/, ! 594: command->direction); ! 595: ! 596: return(err); ! 597: } ! 598: ! 599: void IOUSBController::InterruptPacketHandler(void * parameter, IOReturn status, UInt32 bufferSizeRemaining) ! 600: { ! 601: IOUSBCommand *command = (IOUSBCommand *)parameter; ! 602: ! 603: if (command == 0) ! 604: return; ! 605: ! 606: #if (DEBUGGING_LEVEL > 1) ! 607: DEBUGLOG("InterruptPacketHandler: transaction complete status=%d bufferSizeRemaining = %d\n", status, bufferSizeRemaining); ! 608: #endif ! 609: if (status != kIOReturnSuccess) ! 610: UIMClearEndpointStall(command->address, ! 611: command->endpoint, ! 612: command->direction); ! 613: ! 614: /* Call the clients handler */ ! 615: complete(command->completion, status, bufferSizeRemaining); ! 616: ! 617: /* Free/give back the command */ ! 618: IOFree(command, sizeof(IOUSBCommand)); ! 619: } ! 620: ! 621: ! 622: /* ! 623: * BulkTransaction: ! 624: * Send a USB bulk packet. ! 625: * ! 626: */ ! 627: IOReturn IOUSBController::BulkTransaction(IOUSBCommand *command) ! 628: { ! 629: IOUSBCompletion completion; ! 630: IOReturn err = kIOReturnSuccess; ! 631: ! 632: ! 633: completion.target = (void *)this; ! 634: completion.action = &IOUSBController::BulkPacketHandler; ! 635: completion.parameter = (void *)command; ! 636: ! 637: err = UIMCreateBulkTransfer( ! 638: command->address /*functionAddress*/, ! 639: command->endpoint /*endpointNumber*/, ! 640: completion /*completion*/, ! 641: command->buffer /*buffer*/, ! 642: true /*bufferRounding*/, ! 643: command->buffer->getLength() /*bufferSize*/, ! 644: command->direction /*direction*/); ! 645: ! 646: if (err) ! 647: IOLog("BulkTransaction: error queueing bulk packet (%d)\n", err); ! 648: ! 649: return(err); ! 650: } ! 651: ! 652: void IOUSBController::BulkPacketHandler(void * parameter, ! 653: IOReturn status, ! 654: UInt32 bufferSizeRemaining) ! 655: { ! 656: IOUSBCommand *command = (IOUSBCommand *)parameter; ! 657: ! 658: ! 659: if (command == 0) ! 660: return; ! 661: ! 662: #if (DEBUGGING_LEVEL > 0) ! 663: DEBUGLOG("BulkPacketHandler: transaction complete status=%d bufferSizeRemaining = %d\n", status, bufferSizeRemaining); ! 664: #endif ! 665: if (status != kIOReturnSuccess) ! 666: UIMClearEndpointStall(command->address, ! 667: command->endpoint, ! 668: command->direction); ! 669: ! 670: /* Call the clients handler */ ! 671: complete(command->completion, status, bufferSizeRemaining); ! 672: ! 673: /* Free/give back the command */ ! 674: IOFree(command, sizeof(IOUSBCommand)); ! 675: } ! 676: ! 677: /* ! 678: * BulkTransaction: ! 679: * Send a USB bulk packet. ! 680: * ! 681: */ ! 682: IOReturn IOUSBController::doIsocTransfer(OSObject *owner, void *cmd, ! 683: void */*field2*/, void */*field3*/, void */*field4*/) ! 684: { ! 685: IOUSBController *controller = (IOUSBController *)owner; ! 686: IOUSBIsocCommand *command = (IOUSBIsocCommand *) cmd; ! 687: return(controller->IsocTransaction(command)); ! 688: } ! 689: ! 690: IOReturn IOUSBController::IsocTransaction(IOUSBIsocCommand *command) ! 691: { ! 692: IOUSBIsocCompletion completion; ! 693: IOReturn err = kIOReturnSuccess; ! 694: ! 695: ! 696: completion.target = (void *)this; ! 697: completion.action = &IOUSBController::IsocCompletionHandler; ! 698: completion.parameter = (void *)command; ! 699: ! 700: err = UIMCreateIsochTransfer( ! 701: command->address /*functionAddress*/, ! 702: command->endpoint /*endpointNumber*/, ! 703: completion /*completion*/, ! 704: command->direction /*direction*/, ! 705: command->startFrame /*Start frame */, ! 706: command->buffer /*buffer*/, ! 707: command->numFrames /*number of frames*/, ! 708: command->frameList /*transfer for each frame*/); ! 709: ! 710: if (err) { ! 711: IOLog("IsocTransaction: error queueing isoc transfer (0x%x)\n", err); ! 712: if (command->completion.action) ! 713: (command->completion.action)(command->completion.target, ! 714: command->completion.parameter, ! 715: err, ! 716: command->frameList); ! 717: } ! 718: return(err); ! 719: } ! 720: ! 721: void IOUSBController::IsocCompletionHandler(void * parameter, ! 722: IOReturn status, ! 723: IOUSBIsocFrame *pFrames) ! 724: { ! 725: IOUSBIsocCommand *command = (IOUSBIsocCommand *)parameter; ! 726: ! 727: if (command == 0) ! 728: return; ! 729: ! 730: if (status != kIOReturnSuccess) ! 731: UIMClearEndpointStall(command->address, ! 732: command->endpoint, ! 733: command->direction); ! 734: ! 735: /* Call the clients handler */ ! 736: IOUSBIsocCompletion *completion = &command->completion; ! 737: if (completion->action) (*completion->action)(completion->target, ! 738: completion->parameter, ! 739: status, ! 740: pFrames); ! 741: ! 742: /* Free/give back the command */ ! 743: IOFree(command, sizeof(IOUSBIsocCommand)); ! 744: } ! 745: ! 746: ! 747: IOReturn IOUSBController::doIOTransfer(OSObject *owner, ! 748: void *cmd, ! 749: void */*field2*/, void */*field3*/, void */*field4*/) ! 750: { ! 751: IOUSBController *controller = (IOUSBController *)owner; ! 752: IOUSBCommand *command = (IOUSBCommand *) cmd; ! 753: IOReturn err = kIOReturnSuccess; ! 754: ! 755: switch (command->type) ! 756: { ! 757: case kUSBInterrupt: ! 758: err = controller->InterruptTransaction(command); ! 759: break; ! 760: case kUSBIsoc: ! 761: IOLog("Isoc transactions not supported on non-isoc pipes!!\n"); ! 762: err = kIOReturnBadArgument; ! 763: break; ! 764: case kUSBBulk: ! 765: err = controller->BulkTransaction(command); ! 766: break; ! 767: default: ! 768: IOLog("Unknown transaction type\n"); ! 769: err = kIOReturnBadArgument; ! 770: break; ! 771: } ! 772: ! 773: if (err) ! 774: controller->complete(command->completion, err, 0); ! 775: ! 776: return err; ! 777: } ! 778: ! 779: IOReturn IOUSBController::doControlTransfer(OSObject *owner, ! 780: void *arg0, void *arg1, ! 781: void *arg2, void *arg3) ! 782: { ! 783: IOUSBController *me = (IOUSBController *)owner; ! 784: ! 785: return me->ControlTransaction((IOUSBCommand *)arg0); ! 786: } ! 787: ! 788: IOReturn IOUSBController::doDeleteEP(OSObject *owner, ! 789: void *arg0, void *arg1, ! 790: void *arg2, void *arg3) ! 791: { ! 792: IOUSBController *me = (IOUSBController *)owner; ! 793: ! 794: return me->UIMDeleteEndpoint((short)arg0, (short)arg1, (short)arg2); ! 795: } ! 796: ! 797: IOReturn IOUSBController::doCreateEP(OSObject *owner, ! 798: void *arg0, void *arg1, ! 799: void *arg2, void *arg3) ! 800: { ! 801: IOUSBController *me = (IOUSBController *)owner; ! 802: UInt8 address = (UInt8)arg0; ! 803: UInt8 speed = (UInt8)arg1; ! 804: Endpoint *endpoint = (Endpoint *)arg2; ! 805: IOReturn err; ! 806: switch (endpoint->transferType) ! 807: { ! 808: case kUSBInterrupt: ! 809: err = me->UIMCreateInterruptEndpoint(address, ! 810: endpoint->number, ! 811: endpoint->direction, ! 812: speed, ! 813: endpoint->maxPacketSize, ! 814: endpoint->interval); ! 815: break; ! 816: ! 817: case kUSBBulk: ! 818: err = me->UIMCreateBulkEndpoint(address, ! 819: endpoint->number, ! 820: endpoint->direction, ! 821: speed, ! 822: endpoint->maxPacketSize); ! 823: break; ! 824: ! 825: case kUSBControl: ! 826: err = me->UIMCreateControlEndpoint(address, ! 827: endpoint->number, ! 828: endpoint->maxPacketSize, ! 829: speed); ! 830: break; ! 831: ! 832: case kUSBIsoc: ! 833: err = me->UIMCreateIsochEndpoint(address, ! 834: endpoint->number, ! 835: endpoint->maxPacketSize, ! 836: endpoint->direction); ! 837: break; ! 838: ! 839: default: ! 840: err = kIOReturnBadArgument; ! 841: break; ! 842: } ! 843: return (err); ! 844: } ! 845: ! 846: IOReturn IOUSBController::AcquireDeviceZero() ! 847: { ! 848: IOReturn err = 0; ! 849: Endpoint ep; ! 850: ! 851: ep.number = 0; ! 852: ep.transferType = kUSBControl; ! 853: ep.maxPacketSize = 8; ! 854: ! 855: #if (DEBUGGING_LEVEL > 0) ! 856: DEBUGLOG("%s: TRYING TO ACQUIRE DEVICE ZERO\n", getName()); ! 857: #endif ! 858: ! 859: IOTakeLock(_devZeroLock); ! 860: ! 861: #if (DEBUGGING_LEVEL > 0) ! 862: DEBUGLOG("%s: ACQUIRED DEVICE ZERO\n", getName()); ! 863: #endif ! 864: ! 865: err = openPipe(0, kUSBHighSpeed, &ep); ! 866: return(err); ! 867: } ! 868: ! 869: void IOUSBController::ReleaseDeviceZero(void) ! 870: { ! 871: IOReturn err = 0; ! 872: ! 873: err = _commandGate->runAction(doDeleteEP, (void *)0, (void *)0, (void *)kUSBAnyDirn); ! 874: IOUnlock(_devZeroLock); ! 875: ! 876: #if (DEBUGGING_LEVEL > 0) ! 877: DEBUGLOG("%s: RELEASED DEVICE ZERO\n", getName()); ! 878: #endif ! 879: ! 880: return; ! 881: } ! 882: ! 883: void IOUSBController::WaitForReleaseDeviceZero() ! 884: { ! 885: IOTakeLock(_devZeroLock); ! 886: IOUnlock(_devZeroLock); ! 887: } ! 888: ! 889: IOReturn IOUSBController::ConfigureDeviceZero(UInt8 maxPacketSize, UInt8 speed) ! 890: { ! 891: IOReturn err = kIOReturnSuccess; ! 892: Endpoint ep; ! 893: ! 894: ep.number = 0; ! 895: ep.transferType = kUSBControl; ! 896: ep.maxPacketSize = maxPacketSize; ! 897: ! 898: #if (DEBUGGING_LEVEL > 0) ! 899: DEBUGLOG("********** ConfigureDeviceZero %d %d **********\n", maxPacketSize, speed); ! 900: #endif ! 901: err = _commandGate->runAction(doDeleteEP, (void *)0, (void *)0, (void *)kUSBAnyDirn); ! 902: err = openPipe(0, speed, &ep); ! 903: ! 904: return(err); ! 905: } ! 906: ! 907: ! 908: IOReturn IOUSBController::GetDeviceZeroDescriptor(IOUSBDeviceDescriptor *desc) ! 909: { ! 910: IOReturn err = kIOReturnSuccess; ! 911: IOUSBDevRequest request; ! 912: ! 913: #if (DEBUGGING_LEVEL > 0) ! 914: DEBUGLOG("********** GET DEVICE ZERO DEVICE DESCRIPTOR **********\n"); ! 915: #endif ! 916: ! 917: do ! 918: { ! 919: IOUSBCompletion tap; ! 920: IOSyncer * syncer; ! 921: ! 922: syncer = IOSyncer::create(); ! 923: ! 924: tap.target = syncer; ! 925: tap.action = &IOUSBSyncCompletion; ! 926: tap.parameter = NULL; ! 927: ! 928: if (!desc) ! 929: { ! 930: err = kIOReturnBadArgument; ! 931: break; ! 932: } ! 933: ! 934: request.rqDirection = kUSBIn; ! 935: request.rqType = kUSBStandard; ! 936: request.rqRecipient = kUSBDevice; ! 937: request.bRequest = kUSBRqGetDescriptor; ! 938: OSWriteLittleInt16(&request.wValue, 0, (kUSBDeviceDesc << 8)); ! 939: OSWriteLittleInt16(&request.wIndex, 0, 0); ! 940: OSWriteLittleInt16(&request.wLength, 0, sizeof(IOUSBDeviceDescriptor)); ! 941: request.pData = desc; ! 942: ! 943: err = deviceRequest(&request, &tap, 0, 0); ! 944: ! 945: if (err) ! 946: { ! 947: #if (DEBUGGING_LEVEL > 0) ! 948: DEBUGLOG("%s: error getting device descriptor. err=%d\n", getName(), err); ! 949: #endif ! 950: syncer->release(); ! 951: syncer->release(); ! 952: break; ! 953: } ! 954: err = syncer->wait(); ! 955: ! 956: } while(false); ! 957: ! 958: return(err); ! 959: } ! 960: ! 961: IOReturn IOUSBController::SetDeviceZeroAddress(USBDeviceAddress address, ! 962: UInt8 maxPacketSize, UInt8 speed) ! 963: { ! 964: IOReturn err = kIOReturnSuccess; ! 965: IOUSBDevRequest request; ! 966: ! 967: #if (DEBUGGING_LEVEL > 0) ! 968: DEBUGLOG("********** SET DEVICE ZERO ADDRESS: %d %d %d **********\n", ! 969: address, maxPacketSize, speed); ! 970: #endif ! 971: ! 972: do ! 973: { ! 974: IOUSBCompletion tap; ! 975: IOSyncer * syncer; ! 976: ! 977: syncer = IOSyncer::create(); ! 978: ! 979: tap.target = syncer; ! 980: tap.action = &IOUSBSyncCompletion; ! 981: tap.parameter = NULL; ! 982: ! 983: request.rqDirection = kUSBOut; ! 984: request.rqType = kUSBStandard; ! 985: request.rqRecipient = kUSBDevice; ! 986: request.bRequest = kUSBRqSetAddress; ! 987: OSWriteLittleInt16(&request.wValue, 0, address); ! 988: OSWriteLittleInt16(&request.wIndex, 0, 0); ! 989: OSWriteLittleInt16(&request.wLength, 0, 0); ! 990: request.pData = 0; ! 991: ! 992: err = deviceRequest(&request, &tap, 0, 0); ! 993: ! 994: if (err) ! 995: { ! 996: syncer->release(); syncer->release(); ! 997: break; ! 998: } ! 999: err = syncer->wait(); ! 1000: ! 1001: } while(false); ! 1002: ! 1003: #if (DEBUGGING_LEVEL > 0) ! 1004: DEBUGLOG("%s: error setting device address. err=%d\n", getName(), err); ! 1005: #endif ! 1006: return(err); ! 1007: } ! 1008: ! 1009: IOUSBDevice *IOUSBController::MakeDevice(IOUSBDeviceDescriptor *desc, ! 1010: UInt8 speed, UInt32 power) ! 1011: { ! 1012: IOReturn err = kIOReturnSuccess; ! 1013: IOUSBDevice *newDev; ! 1014: USBDeviceAddress address; ! 1015: ! 1016: #if (DEBUGGING_LEVEL > 0) ! 1017: DEBUGLOG("*************** MakeDevice ***************\n"); ! 1018: #endif ! 1019: ! 1020: newDev = newDevice(); ! 1021: if (newDev == 0) ! 1022: return(0); ! 1023: ! 1024: address = getNewAddress(); ! 1025: if(address == 0) { ! 1026: newDev->release(); ! 1027: return 0; ! 1028: } ! 1029: ! 1030: err = SetDeviceZeroAddress(address, desc->maxPacketSize, speed); ! 1031: ! 1032: if (err) ! 1033: { ! 1034: #if (DEBUGGING_LEVEL > 0) ! 1035: DEBUGLOG("%s: error setting address. err=%d device=%lx\n", ! 1036: getName(), err, (UInt32)this); ! 1037: #endif ! 1038: //return(0); Some devices produce a spurious error here, eg. Altec Lansing speakers ! 1039: } ! 1040: ! 1041: err = CreateDevice(newDev, address, desc, speed, power); ! 1042: if(err) { ! 1043: newDev->release(); ! 1044: return(0); ! 1045: } ! 1046: return(newDev); ! 1047: } ! 1048: ! 1049: IOReturn IOUSBController::PolledRead( ! 1050: short functionNumber, ! 1051: short endpointNumber, ! 1052: IOUSBCompletion completion, ! 1053: IOMemoryDescriptor * CBP, ! 1054: bool bufferRounding, ! 1055: UInt32 bufferSize) ! 1056: { ! 1057: return UIMCreateInterruptTransfer(functionNumber, endpointNumber, ! 1058: completion, CBP, bufferRounding, bufferSize, kUSBIn); ! 1059: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.