Annotation of XNU/iokit/Families/IOUSBBus/IOUSBController.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * Copyright (c) 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: }

unix.superglobalmegacorp.com

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