Annotation of XNU/iokit/Families/IOUSBBus/IOUSBHub.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:  *
        !            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.