Annotation of XNU/iokit/Families/IOUSBBus/IOUSBHub.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:  *
                     27:  */
                     28: 
                     29: #include <libkern/OSByteOrder.h>
                     30: 
                     31: #include "IOUSBHub.h"
                     32: #include <IOKit/usb/IOUSBInterface.h>
                     33: #include <IOKit/usb/IOUSBPipe.h>
                     34: 
                     35: #define super IOService
                     36: #define self this
                     37: #define DEBUGGING_LEVEL 0
                     38: #define DEBUGLOG kprintf
                     39: 
                     40: UInt32 GetErrataBits(IOUSBDeviceDescriptor *desc);
                     41: 
                     42: /* private API */
                     43: static void callStartHandler(void *hub)
                     44: {
                     45:     ((IOUSBHub *) hub)->StartHandler();
                     46: }
                     47: 
                     48: OSDefineMetaClassAndStructors(IOUSBHub, IOService)
                     49: 
                     50: bool IOUSBHub::init( OSDictionary * propTable )
                     51: {
                     52:     if( !super::init(propTable))
                     53:         return (false);
                     54: 
                     55:     _numCaptive = 0;
                     56: 
                     57:     return(true);
                     58: }
                     59: 
                     60: bool IOUSBHub::start(IOService * provider)
                     61: {
                     62:     IOReturn                   err = 0;
                     63:     IOUSBDevice::FindInterfaceRequest  req;
                     64:     IOThread                   ioThread;
                     65:     
                     66:     if( !super::start(provider))
                     67:         return (false);
                     68: 
                     69:     // remember my device
                     70:     _device            = (IOUSBDevice *) provider;
                     71:     _address           = _device->address();
                     72:     _bus               = _device->bus();
                     73: 
                     74:     if (!_device->open(this)) return false;
                     75:     
                     76:     do {
                     77:         IOLog("%s: USB Generic Hub @ %d\n", getName(), _address);
                     78: 
                     79:         // Find the first config/interface
                     80:         if (_device->deviceDescriptor()->numConf < 1)
                     81:         {
                     82:             IOLog("%s: no hub configurations\n", getName());
                     83:             break;
                     84:         }
                     85: 
                     86:         req.theClass = kUSBHubClass;
                     87:        req.subClass = req.protocol = 0;
                     88:         req.maxPower = 0;
                     89:         if ((_hubInterface = _device->findNextInterface(NULL, &req)) == 0)
                     90:         {
                     91:             IOLog("%s: no interface found\n", getName());
                     92:             break;
                     93:         }
                     94:         _busPowered = req.busPowered == 2;     //FIXME
                     95:         _selfPowered = req.selfPowered == 2;   //FIXME
                     96: 
                     97:         if( !(_busPowered || _selfPowered) )
                     98:         {
                     99:             IOLog("%s: illegal device config - no power\n", getName());
                    100:             break;
                    101:         }
                    102: 
                    103:         // set my configuration
                    104: 
                    105:         if ((err = _device->SetConfiguration(_hubInterface->getConfigValue())))
                    106:             break;
                    107: 
                    108:         // Get the hub descriptor
                    109:         if ((err = GetHubDescriptor(&_hubDescriptor)))
                    110:             break;
                    111: 
                    112:        // Setup for reading status pipe
                    113:         _buffer = IOBufferMemoryDescriptor::withCapacity(8, kIODirectionIn);
                    114: 
                    115:         if (!_hubInterface->open(this))
                    116:             break;
                    117: 
                    118:         IOUSBFindEndpointRequest request;
                    119:         request.type = kUSBInterrupt;
                    120:         request.direction = kUSBIn;
                    121:         _interruptPipe = _hubInterface->findNextPipe(NULL, &request);
                    122: 
                    123:         if(!_interruptPipe)
                    124:             return false;
                    125: 
                    126:         // prepare the ports
                    127:        UnpackPortFlags();
                    128:         CountCaptivePorts();
                    129: #if (DEBUGGING_LEVEL > 0)
                    130:         PrintHubDescriptor(&_hubDescriptor);
                    131: #endif
                    132:         if (!CheckPortPowerRequirements())     continue;
                    133:         if (!AllocatePortMemory())             continue;
                    134:         if (!StartPorts())                     continue;
                    135:         ioThread = IOCreateThread(callStartHandler, this);
                    136:         if (ioThread == NULL)                  continue;
                    137:                 
                    138:         return(true);
                    139: 
                    140:     } while (false);
                    141: 
                    142:     IOLog("%s: aborting startup.  err = %d\n", getName(), err);
                    143: 
                    144:     _device->close(this);
                    145:     stop(provider);
                    146:     
                    147:     return(false);
                    148: }
                    149: 
                    150: void IOUSBHub::stop(IOService * provider)
                    151: {
                    152:     // stop/close all ports
                    153:     // deallocate ports
                    154:     StopPorts();
                    155: 
                    156:     if (_buffer) {
                    157:         _buffer->release();
                    158:        _buffer = 0;
                    159:     }
                    160:     if(_hubInterface) {
                    161:         _hubInterface->close(this);
                    162:         _hubInterface->release();
                    163:         _hubInterface = 0;
                    164:     }
                    165:     super::stop(provider);
                    166: }
                    167: 
                    168: /**********************************************************************
                    169:  **
                    170:  ** HUB FUNCTIONS
                    171:  **
                    172:  **********************************************************************/
                    173: void IOUSBHub::UnpackPortFlags(void)
                    174: {
                    175:     // ERIC FIXME?- I don't think the first +1 should be there.
                    176:     int numFlags = ((_hubDescriptor.numPorts + 1) / 8) + 1;
                    177:     int i;
                    178: 
                    179:     for(i = 0; i < numFlags; i++)
                    180:     {
                    181:         _hubDescriptor.pwrCtlPortFlags[i] =
                    182:                                _hubDescriptor.removablePortFlags[numFlags+i];
                    183:         _hubDescriptor.removablePortFlags[numFlags+i] = 0;
                    184:     }
                    185: }
                    186: 
                    187: void IOUSBHub::CountCaptivePorts(void)
                    188: {
                    189:     int                portMask = 2;
                    190:     int                portByte = 0;
                    191:     int                        currentPort;
                    192: 
                    193: 
                    194:     for (currentPort = 1; currentPort <= _hubDescriptor.numPorts; currentPort++)
                    195:     {
                    196:         /* determine if the port is a captive port */
                    197:         if ((_hubDescriptor.removablePortFlags[portByte] & portMask) != 0)
                    198:             _numCaptive++;             // save this for power calculations
                    199: 
                    200:         portMask <<= 1;
                    201:         if(portMask > 0x80)
                    202:         {
                    203:             portMask = 1;
                    204:             portByte++;
                    205:         }
                    206:     }
                    207: }
                    208: 
                    209: 
                    210: /*
                    211:  ExtPower   Good      off
                    212: 
                    213: Bus  Self
                    214: 
                    215: 0     0     Illegal config
                    216: 1     0     Always 100mA per port
                    217: 0     1     500mA     0 (dead)
                    218: 1     1     500      100
                    219: */
                    220: bool IOUSBHub::CheckPortPowerRequirements(void)
                    221: {
                    222:     IOReturn   err = kIOReturnSuccess;
                    223:     /* Note hub current in units of 1mA, everything else in units of 2mA */
                    224:     UInt32     hubPower = _hubDescriptor.hubCurrent/2;
                    225:     UInt32     busPower = _device->busPowerAvailable();
                    226:     UInt32     powerAvailForPorts, powerNeededForPorts;
                    227:     bool       startExternal;
                    228: 
                    229:     do
                    230:     {
                    231:         if (hubPower > busPower)
                    232:         {
                    233:             IOLog("%s: hub needs more power than available", getName());
                    234:             err = kIOReturnNoPower;
                    235:         }
                    236: 
                    237:         powerAvailForPorts = busPower - hubPower;
                    238:         /* we minimally need make available 100mA per non-captive port */
                    239:         powerNeededForPorts =
                    240:             (_hubDescriptor.numPorts - _numCaptive) * kUSB100mA;
                    241:         _busPowerGood = powerAvailForPorts >= powerNeededForPorts;
                    242:         if(_numCaptive > 0)
                    243:         {
                    244:             if(_busPowerGood)
                    245:                 _powerForCaptive =
                    246:                     (powerAvailForPorts - powerNeededForPorts) / _numCaptive;
                    247:             else
                    248:                 _powerForCaptive = powerAvailForPorts / _numCaptive;
                    249:         }
                    250: 
                    251:         if( (_errataBits & kErrataCaptiveOK) != 0)
                    252:             _powerForCaptive = kUSB100mAAvailable;
                    253: 
                    254: #if (DEBUGGING_LEVEL > 0)
                    255:         DEBUGLOG("%s: power:\n", getName());
                    256:         DEBUGLOG("\tbus power available = %ldmA\n", busPower * 2);
                    257:         DEBUGLOG("\thub power needed = %ldmA\n", hubPower * 2);
                    258:         DEBUGLOG("\tport power available = %ldmA\n", powerAvailForPorts * 2);
                    259:         DEBUGLOG("\tport power needed = %ldmA\n", powerNeededForPorts * 2);
                    260:         DEBUGLOG("\tpower for captives = %ldmA\n", _powerForCaptive * 2);
                    261:         DEBUGLOG("\tbus power is %s\n", _busPowerGood?"good" : "insufficient");
                    262: #endif
                    263:         
                    264:         _selfPowerGood = false;
                    265:         
                    266:         if(_selfPowered)
                    267:         {
                    268:             USBStatus  status = 0;
                    269: 
                    270:             if ((err = _device->GetDeviceStatus(&status)))     break;
                    271:             status = USBToHostWord(status);
                    272:             _selfPowerGood = ((status & 1) != 0);      // FIXME 1?
                    273:         }
                    274: 
                    275:         if(_selfPowered && _busPowered)
                    276:         {
                    277:             /* Dual power hub */
                    278:             DEBUGLOG("%s: Hub attached - Self/Bus powered, ", getName());
                    279:             if(_selfPowerGood)
                    280:                 DEBUGLOG("power supply good\n");
                    281:             else
                    282:                 DEBUGLOG("no external power\n");
                    283:         }
                    284:         else
                    285:         {
                    286:             /* Single power hub */
                    287:             if(_selfPowered)
                    288:             {
                    289:                 DEBUGLOG("%s: Hub attached - Self powered, ", getName());
                    290:                 if(_selfPowerGood)
                    291:                     DEBUGLOG("power supply good\n");
                    292:                 else
                    293:                     DEBUGLOG("no external power\n");
                    294:             }
                    295:             else
                    296:             {
                    297:                 DEBUGLOG("%s: Hub attached - Bus powered\n", getName());
                    298:             }
                    299: 
                    300:         }
                    301:         startExternal = (_busPowerGood || _selfPowerGood);
                    302:         if( !startExternal )
                    303:         {      /* not plugged in or bus powered on a bus powered hub */
                    304:             err = kIOReturnNoPower;
                    305:             DEBUGLOG("%s: insufficient power to turn on ports\n", getName());
                    306:             if(!_busPowered)
                    307:             {
                    308:                 /* may be able to turn on compound devices */
                    309:                 break; /* Now what ?? */
                    310:             }
                    311:         }
                    312:     } while (false);
                    313: 
                    314:     return(err == kIOReturnSuccess);
                    315: }
                    316: 
                    317: 
                    318: bool IOUSBHub::AllocatePortMemory(void)
                    319: {
                    320:     IOUSBHubPort       *port;
                    321:     UInt32             power;
                    322:     int                portMask = 2;
                    323:     int                portByte = 0;
                    324:     int                        currentPort;
                    325: 
                    326: 
                    327:     _ports = (IOUSBHubPort **)
                    328:                IOMalloc(sizeof(IOUSBHubPort *) * _hubDescriptor.numPorts);
                    329:     if (!_ports)
                    330:         return(false);
                    331: 
                    332:     for (currentPort = 1; currentPort <= _hubDescriptor.numPorts; currentPort++)
                    333:     {
                    334:         /* determine if the port is a captive port */
                    335:         if ((_hubDescriptor.removablePortFlags[portByte] & portMask) != 0)
                    336:         {
                    337:             power = _powerForCaptive;
                    338:         }
                    339:         else
                    340:         {
                    341:             power = _selfPowerGood ? kUSB500mAAvailable : kUSB100mAAvailable;
                    342:         }
                    343: 
                    344:         port = new IOUSBHubPort;
                    345:         port->init(self, currentPort, power);
                    346:         _ports[currentPort-1] = port;
                    347: 
                    348:         portMask <<= 1;
                    349:         if(portMask > 0x80)
                    350:         {
                    351:             portMask = 1;
                    352:             portByte++;
                    353:         }
                    354:     }
                    355:     
                    356:     return(true);
                    357: }
                    358: 
                    359: 
                    360: bool IOUSBHub::StartPorts(void)
                    361: {
                    362:     IOReturn           err = kIOReturnSuccess;
                    363:     IOUSBHubPort       *port;
                    364:     int                        currentPort;
                    365:     //IOThread                 ioThread;
                    366: 
                    367: 
                    368: #if (DEBUGGING_LEVEL > 0)
                    369:     DEBUGLOG("%s: starting ports (%d)\n", getName(), _hubDescriptor.numPorts);
                    370: #endif
                    371: 
                    372:     for (currentPort = 1; currentPort <= _hubDescriptor.numPorts; currentPort++)
                    373:     {
                    374:         port = _ports[currentPort-1];
                    375:        if (port)
                    376:             err = port->start();
                    377: 
                    378:         // Temporarily fork off a thread for each port.  Each port could
                    379:         // potentially call addDevice which will generate hub events.
                    380:         //ioThread = IOCreateThread(callStart, port);
                    381:         //if (ioThread == NULL)
                    382:         //{
                    383:         //    err = kIOReturnNoMemory;
                    384:         //    break;
                    385:         //}
                    386:     }
                    387: 
                    388:     // Ignore any error for now.  Maybe the hub would want to know
                    389:     // if all ports failed, but if at least one succeeds, then we
                    390:     // should continue.
                    391:     return(true);
                    392: }
                    393: 
                    394: bool IOUSBHub::StopPorts(void)
                    395: {
                    396:     IOUSBHubPort       *port;
                    397:     int                        currentPort;
                    398: 
                    399: 
                    400: #if (DEBUGGING_LEVEL > 0)
                    401:     DEBUGLOG("%s: stopping ports (%d)\n", getName(), _hubDescriptor.numPorts);
                    402: #endif
                    403: 
                    404:     if( _ports) for (currentPort = 1; currentPort <= _hubDescriptor.numPorts; currentPort++)
                    405:     {
                    406:         port = _ports[currentPort-1];
                    407:        if (port) {
                    408:             port->stop();
                    409:             delete port;
                    410:             _ports[currentPort-1] = 0;
                    411:        }
                    412:     }
                    413: 
                    414:     IOFree(_ports, sizeof(IOUSBHubPort *) * _hubDescriptor.numPorts);
                    415:     _ports = 0;
                    416:     return(true);
                    417: }
                    418: 
                    419: const UInt8 * IOUSBHub::getStatusChanged(void)
                    420: {
                    421:     IOReturn           err = kIOReturnSuccess;
                    422:     const UInt8 *      status = NULL;
                    423: 
                    424:     _buffer->setLength(8);
                    425: 
                    426:     do
                    427:     {
                    428:         if ((err = _interruptPipe->read(_buffer)))
                    429:         {
                    430:             DEBUGLOG("%s: error 0x%x reading interrupt pipe.\n", getName(), err);
                    431:             break;
                    432:         }
                    433: 
                    434:         if (err == kIOReturnNotResponding)
                    435:         {
                    436:             // This probably means the device was unplugged.
                    437:             break;
                    438:         }
                    439:         else if (err != kIOReturnSuccess)
                    440:         {
                    441:             // We should handle other errors more intelligently, but
                    442:             // for now just return and assume the error is recoverable.
                    443:             //kprintf("%s: error %d reading interrupt pipe\n", getName(), err);
                    444:             break;
                    445:         }
                    446:         status = (const UInt8 *)_buffer->getBytesNoCopy();
                    447:     } while (false);
                    448:     return status;
                    449: }
                    450: 
                    451: bool IOUSBHub::StartHandler(void)
                    452: {
                    453:     IOReturn   err = kIOReturnSuccess;
                    454:     const UInt8        *statusChangedBitmap;
                    455:     int        portMask;
                    456:     int        portByte;
                    457:     int        portIndex;
                    458:     IOUSBHubPort *port;
                    459: 
                    460:     do
                    461:     {
                    462:         portMask = 2;
                    463:         portByte = 0;
                    464:         statusChangedBitmap = getStatusChanged();
                    465:         if (statusChangedBitmap == 0)
                    466:         {
                    467:             DEBUGLOG("%s: no data returned from int pipe\n", getName());
                    468:             break;
                    469:         }
                    470: 
                    471: #if (DEBUGGING_LEVEL > 0)
                    472:         DEBUGLOG("read returned 0x%x (%d)\n", statusChangedBitmap[portByte],
                    473:                  _buffer->getLength());
                    474: #endif
                    475: 
                    476:         for (portIndex = 1; portIndex <=_hubDescriptor.numPorts; portIndex++)
                    477:         {
                    478:             if ((statusChangedBitmap[portByte] & portMask) != 0)
                    479:             {
                    480:                 port = _ports[portIndex-1];
                    481:                 port->statusChanged();
                    482:             }
                    483: 
                    484:             portMask <<= 1;
                    485:             if (portMask > 0x80)
                    486:             {
                    487:                 portMask = 1;
                    488:                 portByte++;
                    489:             }
                    490:         }
                    491: 
                    492:         /* hub status changed */
                    493:         if ((statusChangedBitmap[0] & 1) != 0)
                    494:         {      
                    495:             statusChanged();
                    496:         }
                    497: 
                    498:     } while (true);
                    499: 
                    500:     DEBUGLOG("%s: error %d.  Exiting Hub Handler\n", getName(), err);
                    501: 
                    502:     _device->close(this);
                    503:     
                    504:     return(false);
                    505: }
                    506: 
                    507: 
                    508: bool IOUSBHub::statusChanged(void)
                    509: {
                    510:     IOReturn   err = kIOReturnSuccess;
                    511: 
                    512:     do
                    513:     {
                    514:         if ((err = GetHubStatus(&_hubStatus)))
                    515:         {
                    516:             fatalError(err, "get status (first in hub status change)");
                    517:             break;            
                    518:         }
                    519:         _hubStatus.statusFlags = USBToHostWord(_hubStatus.statusFlags);
                    520:         _hubStatus.changeFlags = USBToHostWord(_hubStatus.changeFlags);
                    521: 
                    522: #if (DEBUGGING_LEVEL > 0)
                    523:         DEBUGLOG("%s: hub status = %x/%x\n", getName(),
                    524:                  _hubStatus.statusFlags, _hubStatus.changeFlags);
                    525: #endif
                    526: 
                    527:         if (_hubStatus.changeFlags & kHubLocalPowerStatusChange)
                    528:         {
                    529: #if (DEBUGGING_LEVEL > 0)
                    530:             DEBUGLOG("%s: Local Power Status Change detected\n", getName());
                    531: #endif
                    532:             if ((err = ClearHubFeature(kHubLocalPowerStatusChange)))
                    533:             {
                    534:                 fatalError(err, "clear hub power status feature");
                    535:                 break;
                    536:             }
                    537:             if ((err = GetHubStatus(&_hubStatus)))
                    538:             {
                    539:                 fatalError(err, "get status (second in hub status change)");
                    540:                 break;
                    541:             }
                    542:             _hubStatus.statusFlags = USBToHostWord(_hubStatus.statusFlags);
                    543:             _hubStatus.changeFlags = USBToHostWord(_hubStatus.changeFlags);
                    544:         }
                    545: 
                    546:         if (_hubStatus.changeFlags & kHubOverCurrentIndicatorChange)
                    547:         {
                    548: #if (DEBUGGING_LEVEL > 0)
                    549:             DEBUGLOG("%s: OverCurrent Indicator Change detected\n", getName());
                    550: #endif
                    551:             if ((err =
                    552:                  ClearHubFeature(kHubOverCurrentIndicatorChange)))
                    553:             {
                    554:                 fatalError(err, "clear hub over current feature");
                    555:                 break;
                    556:             }
                    557:             if ((err = GetHubStatus(&_hubStatus)))
                    558:             {
                    559:                 fatalError(err, "get status (second in hub status change)");
                    560:                 break;
                    561:             }
                    562:             _hubStatus.statusFlags = USBToHostWord(_hubStatus.statusFlags);
                    563:             _hubStatus.changeFlags = USBToHostWord(_hubStatus.changeFlags);
                    564:         }
                    565: 
                    566:         //DEBUGLOG("%s: calling delay reentering poll loop\n", getName());
                    567:         //USBDelay(10);  //FIXME
                    568: 
                    569:     } while(false);
                    570: 
                    571:     return(err == kIOReturnSuccess);
                    572: }
                    573: 
                    574: static ErrataListEntry errataList[] = {
                    575: 
                    576: /* For the Cherry 4 port KB, From Cherry:
                    577: We use the bcd_releasenumber-highbyte for hardware- and the lowbyte for
                    578: firmwarestatus. We have 2 different for the hardware 03(eprom) and
                    579: 06(masked microcontroller). Firmwarestatus is 05 today.
                    580: So high byte can be 03 or 06 ----  low byte can be 01, 02, 03, 04, 05
                    581: 
                    582: Currently we are working on a new mask with the new descriptors. The
                    583: firmwarestatus will be higher than 05.
                    584: */
                    585:       {0x046a, 0x003, 0x0301, 0x0305, kErrataCaptiveOK}, // Cherry 4 port KB
                    586:       {0x046a, 0x003, 0x0601, 0x0605, kErrataCaptiveOK}  // Cherry 4 port KB
                    587: };
                    588: 
                    589: #define errataListLength (sizeof(errataList)/sizeof(ErrataListEntry))
                    590: 
                    591: UInt32 GetErrataBits(IOUSBDeviceDescriptor *desc)
                    592: {
                    593:       UInt16           vendID, deviceID, revisionID;
                    594:       ErrataListEntry  *entryPtr;
                    595:       UInt32           i, errata = 0;
                    596: 
                    597:       // get this chips vendID, deviceID, revisionID
                    598:       vendID = USBToHostWord(desc->vendor);
                    599:       deviceID = USBToHostWord(desc->product);
                    600:       revisionID = USBToHostWord(desc->devRel);
                    601: 
                    602:       for(i=0, entryPtr = errataList; i < errataListLength; i++, entryPtr++)
                    603:       {
                    604:           if (vendID == entryPtr->vendID
                    605:               && deviceID == entryPtr->deviceID
                    606:               && revisionID >= entryPtr->revisionLo
                    607:               && revisionID <= entryPtr->revisionHi)
                    608:           {
                    609:               errata |= entryPtr->errata;  // we match, add this errata to our list
                    610:           }
                    611:       }
                    612:       return(errata);
                    613: }
                    614: 
                    615: void IOUSBHub::fatalError(IOReturn err, char *str)
                    616: {
                    617:     DEBUGLOG("IOUSBHub: Error %d: %s\n", err, str);
                    618: }
                    619: 
                    620: IOReturn IOUSBHub::GetHubDescriptor(IOUSBHubDescriptor *desc)
                    621: {
                    622:     IOReturn   err = kIOReturnSuccess;
                    623:     IOUSBDevRequest    request;
                    624: 
                    625: #if (DEBUGGING_LEVEL > 0)
                    626:     DEBUGLOG("*********** GET HUB DESCRIPTOR ***********\n");
                    627: #endif
                    628: 
                    629:     if (!desc) return (kIOReturnBadArgument);
                    630: 
                    631:     request.rqDirection = kUSBIn;
                    632:     request.rqType = kUSBClass;
                    633:     request.rqRecipient = kUSBDevice;
                    634:     request.bRequest = kUSBRqGetDescriptor;
                    635:     OSWriteLittleInt16(&request.wValue, 0, kUSBHubDescriptorType);
                    636:     OSWriteLittleInt16(&request.wIndex, 0, 0);
                    637:     OSWriteLittleInt16(&request.wLength, 0, sizeof(IOUSBHubDescriptor));
                    638:     request.pData = desc;
                    639: 
                    640:     err = _device->deviceRequest(&request);
                    641: 
                    642:     if (err)
                    643:     {
                    644:         /*
                    645:          * Is this a bogus hub?  Some hubs require 0 for the descriptor type
                    646:          * to get their device descriptor.  This is a bug, but it's actually
                    647:          * spec'd out in the USB 1.1 docs.
                    648:          */
                    649:         OSWriteLittleInt16(&request.wValue, 0, 0);
                    650:         OSWriteLittleInt16(&request.wLength, 0, sizeof(IOUSBHubDescriptor));
                    651:         err = _device->deviceRequest(&request);
                    652:     }
                    653: 
                    654:     if (err)
                    655:         IOLog("%s: error getting hub descriptor. err=%d\n", getName(), err);
                    656: 
                    657:     return(err);
                    658: }
                    659: 
                    660: IOReturn IOUSBHub::GetHubStatus(IOUSBHubStatus *status)
                    661: {
                    662:     IOReturn           err = kIOReturnSuccess;
                    663:     IOUSBDevRequest    request;
                    664: 
                    665: #if (DEBUGGING_LEVEL > 0)
                    666:     DEBUGLOG("************* GET HUB STATUS *************\n");
                    667: #endif
                    668: 
                    669:     request.rqDirection = kUSBIn;
                    670:     request.rqType = kUSBClass;
                    671:     request.rqRecipient = kUSBDevice;
                    672:     request.bRequest = kUSBRqGetStatus;
                    673:     OSWriteLittleInt16(&request.wValue, 0, 0);
                    674:     OSWriteLittleInt16(&request.wIndex, 0, 0);
                    675:     OSWriteLittleInt16(&request.wLength, 0, sizeof(IOUSBHubStatus));
                    676:     request.pData = status;
                    677: 
                    678:     err = _device->deviceRequest(&request);
                    679: 
                    680:     if (err)
                    681:         IOLog("%s: error getting hub status. err=%d\n", getName(), err);
                    682: 
                    683:     return(err);
                    684: }
                    685: 
                    686: IOReturn IOUSBHub::GetPortState(UInt8 *state, UInt16 port)
                    687: {
                    688:     IOReturn           err = kIOReturnSuccess;
                    689:     IOUSBDevRequest    request;
                    690: 
                    691: #if (DEBUGGING_LEVEL > 0)
                    692:     DEBUGLOG("************* GET PORT STATE *************\n");
                    693: #endif
                    694: 
                    695:     request.rqDirection = kUSBIn;
                    696:     request.rqType = kUSBClass;
                    697:     request.rqRecipient = kUSBOther;
                    698:     request.bRequest = kUSBRqGetState;
                    699:     OSWriteLittleInt16(&request.wValue, 0, 0);
                    700:     OSWriteLittleInt16(&request.wIndex, 0, port);
                    701:     OSWriteLittleInt16(&request.wLength, 0, sizeof(*state));
                    702:     request.pData = state;
                    703: 
                    704:     err = _device->deviceRequest(&request);
                    705: 
                    706:     if (err)
                    707:         IOLog("%s: error getting hub state. err=%d\n", getName(), err);
                    708: 
                    709:     return(err);
                    710: }
                    711: 
                    712: IOReturn IOUSBHub::ClearHubFeature(UInt16 feature)
                    713: {
                    714:     IOReturn           err = kIOReturnSuccess;
                    715:     IOUSBDevRequest    request;
                    716: 
                    717: #if (DEBUGGING_LEVEL > 0)
                    718:     DEBUGLOG("********** CLEAR HUB FEATURE %d **********\n", feature);
                    719: #endif
                    720: 
                    721:     request.rqDirection = kUSBOut;
                    722:     request.rqType = kUSBClass;
                    723:     request.rqRecipient = kUSBDevice;
                    724:     request.bRequest = kUSBRqClearFeature;
                    725:     OSWriteLittleInt16(&request.wValue, 0, feature);
                    726:     OSWriteLittleInt16(&request.wIndex, 0, 0);
                    727:     OSWriteLittleInt16(&request.wLength, 0, 0);
                    728:     OSWriteLittleInt16(&request.pData, 0, 0);
                    729: 
                    730:     err = _device->deviceRequest(&request);
                    731: 
                    732:     if (err)
                    733:         IOLog("%s: error clearing hub feature. err=%d\n", getName(), err);
                    734: 
                    735:     return(err);
                    736: }
                    737: 
                    738: IOReturn IOUSBHub::GetPortStatus(IOUSBHubPortStatus *status, UInt16 port)
                    739: {
                    740:     IOReturn   err = kIOReturnSuccess;
                    741:     IOUSBDevRequest    request;
                    742: 
                    743: #if (DEBUGGING_LEVEL > 0)
                    744:     DEBUGLOG("*********** GET PORT %d STATUS ************\n", port);
                    745: #endif
                    746: 
                    747:     request.rqDirection = kUSBIn;
                    748:     request.rqType = kUSBClass;
                    749:     request.rqRecipient = kUSBOther;
                    750:     request.bRequest = kUSBRqGetStatus;
                    751:     OSWriteLittleInt16(&request.wValue, 0, 0);
                    752:     OSWriteLittleInt16(&request.wIndex, 0, port);
                    753:     OSWriteLittleInt16(&request.wLength, 0, sizeof(IOUSBHubPortStatus));
                    754:     request.pData = status;
                    755: 
                    756:     err = _device->deviceRequest(&request);
                    757: 
                    758:     if (err)
                    759:         IOLog("%s: error getting port status. err=%d\n", getName(), err);
                    760: 
                    761:     // Get things the right way round.
                    762:     status->statusFlags = OSReadLittleInt16(&status->statusFlags, 0);
                    763:     status->changeFlags = OSReadLittleInt16(&status->changeFlags, 0);
                    764: 
                    765:     return(err);
                    766: }
                    767: 
                    768: IOReturn IOUSBHub::SetPortFeature(UInt16 feature, UInt16 port)
                    769: {
                    770:     IOReturn           err = kIOReturnSuccess;
                    771:     IOUSBDevRequest    request;
                    772: 
                    773: #if (DEBUGGING_LEVEL > 0)
                    774:     DEBUGLOG("********* SET PORT %d FEATURE %d **********\n", port, feature);
                    775: #endif
                    776: 
                    777:     request.rqDirection = kUSBOut;
                    778:     request.rqType = kUSBClass;
                    779:     request.rqRecipient = kUSBOther;
                    780:     request.bRequest = kUSBRqSetFeature;
                    781:     OSWriteLittleInt16(&request.wValue, 0, feature);
                    782:     OSWriteLittleInt16(&request.wIndex, 0, port);
                    783:     OSWriteLittleInt16(&request.wLength, 0, 0);
                    784:     request.pData = 0;
                    785: 
                    786:     err = _device->deviceRequest(&request);
                    787: 
                    788:     if (err)
                    789:         IOLog("%s: error setting port feature. err=%d\n", getName(), err);
                    790: 
                    791:     return(err);
                    792: }
                    793: 
                    794: IOReturn IOUSBHub::ClearPortFeature(UInt16 feature, UInt16 port)
                    795: {
                    796:     IOReturn           err = kIOReturnSuccess;
                    797:     IOUSBDevRequest    request;
                    798: 
                    799: #if (DEBUGGING_LEVEL > 0)
                    800:     DEBUGLOG("******** CLEAR PORT %d FEATURE %d *********\n", port, feature);
                    801: #endif
                    802: 
                    803:     request.rqDirection = kUSBOut;
                    804:     request.rqType = kUSBClass;
                    805:     request.rqRecipient = kUSBOther;
                    806:     request.bRequest = kUSBRqClearFeature;
                    807:     OSWriteLittleInt16(&request.wValue, 0, feature);
                    808:     OSWriteLittleInt16(&request.wIndex, 0, port);
                    809:     OSWriteLittleInt16(&request.wLength, 0, 0);
                    810:     request.pData = 0;
                    811: 
                    812:     err = _device->deviceRequest(&request);
                    813: 
                    814:     if (err)
                    815:         IOLog("%s: error clearing port feature. err=%d\n", getName(), err);
                    816: 
                    817:     return(err);
                    818: }
                    819: 
                    820: void IOUSBHub::PrintHubDescriptor(IOUSBHubDescriptor *desc)
                    821: {
                    822:     int i = 0;
                    823:     char *characteristics[] =
                    824:         { "ppsw", "nosw", "comp", "ppoc", "nooc", 0 };
                    825: 
                    826: 
                    827:     if (desc->length == 0) return;
                    828: 
                    829:     DEBUGLOG("hub descriptor: (%d bytes)\n", desc->length);
                    830:     DEBUGLOG("\thubType = %d\n", desc->hubType);
                    831:     DEBUGLOG("\tnumPorts = %d\n", desc->numPorts);
                    832:     DEBUGLOG("\tcharacteristics = %x ( ",
                    833:                                 USBToHostWord(desc->characteristics));
                    834:     do
                    835:     {
                    836:         if (USBToHostWord(desc->characteristics) & (1 << i))
                    837:             DEBUGLOG("%s ", characteristics[i]);
                    838:     } while (characteristics[++i]);
                    839:     DEBUGLOG(")\n");
                    840:     DEBUGLOG("\tpowerOnToGood = %d ms\n", desc->powerOnToGood * 2);
                    841:     DEBUGLOG("\thubCurrent = %d\n", desc->hubCurrent);
                    842:     DEBUGLOG("\tremovablePortFlags = %x %x\n", &desc->removablePortFlags[1], &desc->removablePortFlags[0]);
                    843:     DEBUGLOG("\tpwrCtlPortFlags    = %x %x\n", &desc->pwrCtlPortFlags[1], &desc->removablePortFlags[0]);
                    844: }

unix.superglobalmegacorp.com

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