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

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