Annotation of XNU/iokit/Families/IOUSBBus/IOUSBHub_Ports.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: 
                     30: #include "IOUSBHub.h"
                     31: #include <IOKit/usb/IOUSBController.h>
                     32: 
                     33: //#define super IOService
                     34: #define self this
                     35: #define DEBUGGING_LEVEL 0      // 1 = low; 2 = high; 3 = extreme
                     36: #define DEBUGLOG kprintf
                     37: 
                     38: static portStatusChangeVector defaultPortVectors[kNumChangeHandlers] =
                     39: {
                     40:     { 0, kHubPortOverCurrent,  kUSBHubPortOverCurrentChangeFeature },
                     41:     { 0, kHubPortBeingReset,   kUSBHubPortResetChangeFeature },
                     42:     { 0, kHubPortSuspend,      kUSBHubPortSuspendChangeFeature },
                     43:     { 0, kHubPortEnabled,      kUSBHubPortEnableChangeFeature },
                     44:     { 0, kHubPortConnection,   kUSBHubPortConnectionChangeFeature },
                     45: };
                     46: 
                     47: void IOUSBHubPort::init( IOUSBHub *parent, int portNum, UInt32 powerAvailable )
                     48: {
                     49:     _hub               = parent;
                     50:     _bus               = parent->_bus;
                     51:     _hubDesc           = &parent->_hubDescriptor;
                     52:     _portNum           = portNum;
                     53:     _portDevice                = 0;
                     54:     _portPowerAvailable        = powerAvailable;
                     55:     initPortVectors();
                     56: 
                     57:     if (!_hub) DEBUGLOG("init: _hub is invalid\n");
                     58:     if (!_bus) DEBUGLOG("init: _bus is invalid\n");
                     59:     if (!_hubDesc) DEBUGLOG("init: _hubDesc is invalid\n");
                     60:     if (portNum < 1 || portNum > 64) DEBUGLOG("init: portNum is invalid\n");
                     61: }
                     62: 
                     63: /*
                     64:  * start:
                     65:  * Here we really just need to turn on power to the ports.  The change
                     66:  * handler will take it from there.  However, we need to check for 2 conditions
                     67:  * before we exit:
                     68:  *    1. are there permanent devices connected,
                     69:  *    2. some hubs don't generate a change connection if the ports are
                     70:  *       powered on with a device already connected.  
                     71:  * If either of these exist, then add the port.
                     72:  */
                     73: IOReturn IOUSBHubPort::start(void)
                     74: {
                     75:     IOReturn   err = kIOReturnSuccess;
                     76:     IOUSBHubPortStatus status;
                     77: 
                     78: 
                     79:     do
                     80:     {
                     81:         /* turn on Power to the port */
                     82:         if ((err = _hub->SetPortFeature(kUSBHubPortPowerFeature, _portNum)))
                     83:         {
                     84:             fatalError(err, "setting port power");
                     85:             break;
                     86:         }
                     87: 
                     88:         if ((err = _hub->GetPortStatus(&status, _portNum)))
                     89:         {
                     90:             fatalError(err, "getting port status (1)");
                     91:             break;
                     92:         }
                     93: 
                     94: #if (DEBUGGING_LEVEL > 0)
                     95:         DEBUGLOG("0x%x\t(start) port %d status = %xs/%xc\n", _hub,
                     96:                  _portNum, status.statusFlags, status.changeFlags);
                     97: #endif
                     98: 
                     99:         // If there is a connection change, then let the handler take it
                    100:         // from here.  Also, in some cases the hub was in a suspend state
                    101:         // (rather than a reset state) and does not register a connection
                    102:         // change when the port is powered.  So also check for a connection
                    103:        // with no change connection.        
                    104:         // Is there a change connection OR no connection?
                    105:         // THEN we're all done for now; int handler will take it from here
                    106:         //if ((status.changeFlags & kHubPortConnection) ||
                    107:         //    (status.statusFlags & kHubPortConnection) == 0)
                    108:             break;
                    109:         
                    110:         /* wait for the power on good time */
                    111:         IOSleep(_hubDesc->powerOnToGood * 2);
                    112: 
                    113:         if ((err = _hub->GetPortStatus(&status, _portNum)))
                    114:         {
                    115:             fatalError(err, "getting port status (2)");
                    116:             break;
                    117:         }
                    118: 
                    119: #if (DEBUGGING_LEVEL > 0)
                    120:         DEBUGLOG("0x%x\t(start) port %d status = %xs/%xc\n", _hub,
                    121:               _portNum, status.statusFlags, status.changeFlags);
                    122: #endif
                    123: 
                    124:         /* we now have port status */
                    125:         if (status.changeFlags & kHubPortConnection)
                    126:         {
                    127:             if ((err = _hub->ClearPortFeature
                    128:                                (kUSBHubPortConnectionChangeFeature, _portNum)))
                    129:             {
                    130:                 fatalError(err, "clearing port connection change");
                    131:                 break;
                    132:             }
                    133: 
                    134:             /* We should now be in the disconnected state */
                    135:             /* Do a port request on current port */
                    136:             if ((err = _hub->GetPortStatus(&status, _portNum)))
                    137:             {
                    138:                 fatalError(err, "getting port status (3)");
                    139:                 break;
                    140:             }
                    141:         }
                    142: 
                    143:         if (status.statusFlags & kHubPortConnection)
                    144:         {
                    145:             /* We have a connection on this port */
                    146: #if (DEBUGGING_LEVEL > 0)
                    147:             DEBUGLOG("0x%x\t(start)device detected @ port %d\n", _hub,
                    148:                  _portNum);
                    149: #endif
                    150:             if ((err = addDevice()))
                    151:                 fatalError(err, "adding device");
                    152:         }
                    153:     } while(false);
                    154: 
                    155:     return(err);
                    156: }
                    157: 
                    158: void IOUSBHubPort::stop(void)
                    159: {
                    160:     // Ugh.  This could get nasty.  What if stop is called while
                    161:     // a thread is adding a device?  I think we need to start tracking
                    162:     // states.  And we might need a flag to tell us where it's because
                    163:     // the device has been unplugged, or the system is shutting down.
                    164: 
                    165:     removeDevice();
                    166: }
                    167: 
                    168: IOReturn IOUSBHubPort::addDevice(void)
                    169: {
                    170:     IOReturn           err = kIOReturnSuccess;
                    171: 
                    172:     do
                    173:     {
                    174:         _devZero = _bus->AcquireDeviceZero() == kIOReturnSuccess;
                    175:         if (!_devZero)
                    176:         {
                    177:             fatalError(/*FIXME*/0, "acquiring device zero");
                    178:             break;
                    179:         }
                    180: 
                    181:         if ((err = _hub->SetPortFeature(kUSBHubPortResetFeature,
                    182:                                               _portNum)))
                    183:         {
                    184:             fatalError(err, "set feature (resetting port)");
                    185:             break;
                    186:         }
                    187:        {
                    188:             // Now poll for exit from reset.
                    189:             IOUSBHubPortStatus status;
                    190:             int portByte;
                    191:             UInt8 portMask;
                    192:             bool waitReset = true;
                    193:             AbsoluteTime endResetTime, nowTime;
                    194:             AbsoluteTime_to_scalar(&nowTime) = 0;
                    195:             portByte = _portNum / 8;
                    196:             portMask = 1 << (_portNum % 8);
                    197:             clock_interval_to_deadline(1, kSecondScale, &endResetTime);
                    198:             do
                    199:             {
                    200:                 const UInt8* stat = _hub->getStatusChanged();
                    201:                 if(stat == NULL)
                    202:                     break;
                    203:                 // Check if we've waited long enough!
                    204:                 if( CMP_ABSOLUTETIME(&nowTime, &endResetTime) > 0) {
                    205:                     err = kIOReturnTimeout;
                    206:                     break;
                    207:                 }
                    208:                 clock_get_uptime(&nowTime);
                    209:                if(!stat[portByte] & portMask) {
                    210:                    IOSleep(2);
                    211:                     continue;
                    212:                }
                    213:                 /* Do a port status request on current port */
                    214:                 if ((err = _hub->GetPortStatus(&status, _portNum)))
                    215:                 {
                    216:                     fatalError(err, "get status (waiting for reset end)");
                    217:                     break;
                    218:                 }
                    219: #if (DEBUGGING_LEVEL > 0)
                    220:                 DEBUGLOG("0x%x\t(waiting for reset end) port %d status = %xs/%xc\n", _hub,
                    221:                     _portNum, status.statusFlags, status.changeFlags);
                    222: #endif
                    223:                 if(status.changeFlags & kHubPortBeingReset)
                    224:                 {
                    225:                     if ((err = _hub->ClearPortFeature(
                    226:                                kUSBHubPortResetChangeFeature, _portNum)))
                    227:                     {
                    228:                         fatalError(err, "clear port vector bit feature");
                    229:                         break;
                    230:                     }
                    231:                     err = addDeviceResetChangeHandler(status.changeFlags);
                    232:                     waitReset = false;
                    233:                 }
                    234:             } while (waitReset);
                    235:        }
                    236:     } while(false);
                    237: 
                    238:     if (err && _devZero)
                    239:     {
                    240:         _bus->ReleaseDeviceZero();
                    241:         _devZero = false;
                    242:         
                    243:         // put it back to the default if there was an error
                    244: #if (DEBUGGING_LEVEL > 0)
                    245:         DEBUGLOG("error: setting change handler to default\n");
                    246: #endif
                    247:         setPortVector(&IOUSBHubPort::defaultResetChangeHandler,
                    248:                       kHubPortBeingReset);
                    249:     }
                    250: 
                    251:     return(err);
                    252: }
                    253: 
                    254: void IOUSBHubPort::removeDevice(void)
                    255: {
                    256:     bool       ok;
                    257: 
                    258:     if (_portDevice) {
                    259:        ok = _portDevice->terminate(kIOServiceRequired);
                    260:         if( !ok)
                    261:             DEBUGLOG("IOUSBHubPort: terminate() failed\n");
                    262:        _portDevice->release();
                    263:        _portDevice = 0;
                    264:     }
                    265:     initPortVectors();
                    266: }
                    267: 
                    268: IOReturn IOUSBHubPort::resetDevice()
                    269: {
                    270:     IOReturn err = kIOReturnSuccess;
                    271: 
                    272:     do {
                    273:         _devZero = _bus->AcquireDeviceZero() == kIOReturnSuccess;
                    274:         if (!_devZero)
                    275:         {
                    276:             fatalError(/*FIXME*/0, "acquiring device zero");
                    277:             err = kIOReturnCannotLock;
                    278:             break;
                    279:         }
                    280: 
                    281:         setPortVector(&IOUSBHubPort::handleResetDevice, kHubPortBeingReset);
                    282: 
                    283:         err = _hub->SetPortFeature(kUSBHubPortResetFeature, _portNum);
                    284:         if(err != kIOReturnSuccess)
                    285:             break;
                    286: 
                    287:     } while (false);
                    288: 
                    289:     if(err == kIOReturnSuccess)
                    290:     {
                    291:         _bus->WaitForReleaseDeviceZero();
                    292:     }
                    293:     else if(_devZero)
                    294:     {
                    295:         _bus->ReleaseDeviceZero();
                    296:         _devZero = false;
                    297:     }
                    298: 
                    299:     return err;
                    300: }
                    301: 
                    302: IOReturn IOUSBHubPort::handleResetDevice(UInt16 changeFlags)
                    303: {
                    304:     IOReturn err = kIOReturnSuccess;
                    305: 
                    306:     setPortVector(&IOUSBHubPort::defaultResetChangeHandler, kHubPortBeingReset);
                    307:     /* Now address the device */
                    308:     _bus->ConfigureDeviceZero(_desc.maxPacketSize, _speed);
                    309:     err = _bus->SetDeviceZeroAddress(_portDevice->address(),
                    310:                                     _desc.maxPacketSize, _speed);
                    311: 
                    312:     _bus->ReleaseDeviceZero();
                    313:     _devZero = false;
                    314: 
                    315:     return err;
                    316: }
                    317: 
                    318: void IOUSBHubPort::fatalError(IOReturn err, char *str)
                    319: {
                    320:     DEBUGLOG("IOUSBHubPort: Error 0x%x on port %d: %s\n", err, _portNum, str);
                    321:     if (_portDevice != 0)
                    322:     {
                    323:         DEBUGLOG("IOUSBHubPort: Removing %s from port %d\n",
                    324:                  _portDevice->getName(), _portNum);
                    325:         removeDevice();        
                    326:     }
                    327: }
                    328: 
                    329: 
                    330: /**********************************************************************
                    331:  **
                    332:  ** CHANGE HANDLER FUNCTIONS
                    333:  **
                    334:  **********************************************************************/
                    335: IOReturn IOUSBHubPort::addDeviceResetChangeHandler(UInt16 changeFlags)
                    336: {
                    337:     IOReturn           err = kIOReturnSuccess;
                    338:     IOUSBHubPortStatus status;
                    339: 
                    340:     do
                    341:     {
                    342:         /* Tell the USB to add the device */
                    343:         if ((err = _hub->GetPortStatus(&status, _portNum)))
                    344:         {
                    345:             fatalError(err, "getting port status (3)");
                    346:             break;
                    347:         }
                    348: 
                    349:         if (status.statusFlags & kHubPortBeingReset)
                    350:         {
                    351:             DEBUGLOG("%s: port not finished resetting, retrying\n", _hub->getName());
                    352:             // we should never be here, just wait for another status change int
                    353:             break;
                    354:         }
                    355: 
                    356:         // macally iKey doesn't tell us until now what the device speed is.
                    357:         _speed = ((status.statusFlags & kHubPortSpeed) != 0);
                    358: #if (DEBUGGING_LEVEL > 0)
                    359:                 DEBUGLOG("0x%x\t(reset end) port %d status = %xs/%xc, %s speed\n", _hub,
                    360:                          _portNum, status.statusFlags, status.changeFlags, _speed ? "low" : "high");
                    361: #endif
                    362: 
                    363:         /* Now wait 10 ms after reset */
                    364:         IOSleep(10);
                    365: 
                    366:         // Configure algorithm:
                    367:        // * start with maxpacketsize of 8.
                    368:        // This is the smallest legal maxpacket, and the only legal size for
                    369:        // low-speed devices. The correct maxpacket size is in byte 8 of the
                    370:        // device descriptor, so even if the device sends back a bigger packet
                    371:        // (an overrun error) we should still get the correct value.
                    372:        // * get device descriptor.
                    373:        // * if we recieved the whole descriptor AND maxpacketsize is 64,
                    374:        //   success, so continue on.
                    375:         // * if descriptor returns with a different maxpacketsize, then
                    376:        //   reconfigure with the new one and try again.  Otherwise, 
                    377:        //   reconfigure with 8 and try again.
                    378:         if ((err = _bus->ConfigureDeviceZero(8, _speed)))
                    379:         {
                    380:             fatalError(err, "configuring endpoint zero");
                    381:             break;
                    382:         }              
                    383: 
                    384:         // Now do a device request to find out what it is
                    385:         // Some fast devices send back packets > 8 bytes to address 0.
                    386:         bzero(&_desc, sizeof(_desc));
                    387:         err = _bus->GetDeviceZeroDescriptor(&_desc);
                    388: 
                    389: #if (DEBUGGING_LEVEL > 0)
                    390:         DEBUGLOG("IOUSBHubPort: getDeviceDescriptor err = 0x%x  max = %d numconf = %d\n", err, _desc.maxPacketSize, _desc.numConf);
                    391: #endif
                    392:         // Check for specific conditions here before going on.
                    393:         // 1) if the pipe cannot handle the default max packet size of 8,
                    394:         //    then reconfigure the pipe and try again.  If just the size is
                    395:         //    wrong, it should return at least the correct size if not
                    396:         //    the whole descriptor.
                    397:         // 2) If there is still an err, bail out.
                    398:         if (err || _desc.maxPacketSize != 8)
                    399:         {
                    400:             // Reconfigure the pipe if the max packet size is not the default
                    401:             // of 8, but we explicitly don't want to set it to 0.  It might be
                    402:             // good to do a little more checking here...later.
                    403:             if (_desc.maxPacketSize != 0 && _desc.maxPacketSize != 8)
                    404:             {
                    405:                 err = _bus->ConfigureDeviceZero(_desc.maxPacketSize, _speed);
                    406:                 err = _bus->GetDeviceZeroDescriptor(&_desc);
                    407:             }
                    408:             // The device really didn't like 8.  Probably got a stall or
                    409:             // something like that.  As a last ditch effort, try 64.
                    410:             else if (err)
                    411:             {
                    412:                 err = _bus->ConfigureDeviceZero(64, _speed);
                    413:                 err = _bus->GetDeviceZeroDescriptor(&_desc);
                    414:             }
                    415: 
                    416:             if (err == kIOReturnOverrun)
                    417:             {
                    418:                 // Not sure what to do with this error.  It means more data
                    419:                 // came back than the size of a descriptor.  Hmmm.  For now
                    420:                 // just ignore it and assume the data that did come back is
                    421:                 // useful.
                    422: #if (DEBUGGING_LEVEL > 0)
                    423:                 DEBUGLOG("%s: overrun error reading device descriptor\n",
                    424:                       _hub->getName());
                    425: #endif
                    426:             }
                    427: 
                    428:             if (err)
                    429:             {
                    430:                 fatalError(err, "getting full device descriptor");
                    431:                 continue;
                    432:             }
                    433:         }
                    434: 
                    435:         /* ERIC FIXME?  what are we doing here?
                    436:         if ((_hubDescriptor.removablePortFlags[pp->portByte] & pp->portMask))
                    437:         {
                    438:             pb->usbOther = powerForCaptive;
                    439:         }
                    440:         else
                    441:         {
                    442:             pb->usbOther = selfPowerGood?kUSB500mAAvailable:kUSB100mAAvailable;
                    443:         }
                    444:         */             
                    445: 
                    446:         /* Now create and address the device */
                    447:         if ((_portDevice = _bus->MakeDevice(&_desc, _speed, _portPowerAvailable)) == 0)
                    448:         {
                    449:             _portDevice = 0;
                    450:             err = kIOReturnDeviceError;
                    451:             fatalError(err, "setting the device address");
                    452:             continue;
                    453:         }
                    454:         /* Tell the device who it's port is */
                    455:         _portDevice->setPort(this);
                    456: 
                    457:         /* Release */
                    458:         _bus->ReleaseDeviceZero();
                    459:         _devZero = false;
                    460: 
                    461:         /* Finally use the data gathered */
                    462:         _portDevice->registerService();
                    463: 
                    464:     } while(false);
                    465: 
                    466:     // reset the vector back to the default
                    467: #if (DEBUGGING_LEVEL > 0)
                    468:     DEBUGLOG("0x%x\t(port %d)setting change handler to default\n", _hub, _portNum);
                    469: #endif
                    470:     setPortVector(&IOUSBHubPort::defaultResetChangeHandler, kHubPortBeingReset);
                    471: 
                    472:     if (err)
                    473:     {
                    474:         if (_devZero)
                    475:         {
                    476:             _bus->ReleaseDeviceZero();
                    477:             _devZero = false;
                    478:         }
                    479:     }
                    480:     return err;
                    481: }
                    482: 
                    483: IOReturn IOUSBHubPort::defaultOverCrntChangeHandler(UInt16 changeFlags)
                    484: {
                    485: #if (DEBUGGING_LEVEL > 0)
                    486:     DEBUGLOG("IOUSBHubPort: over current change notification\n");
                    487: #endif
                    488:     return kIOReturnSuccess;
                    489: }
                    490: 
                    491: IOReturn IOUSBHubPort::defaultResetChangeHandler(UInt16 changeFlags)
                    492: {
                    493: #if (DEBUGGING_LEVEL > 0)
                    494:     DEBUGLOG("IOUSBHubPort: reset change notification\n");
                    495: #endif
                    496:     return kIOReturnSuccess;
                    497: }
                    498: 
                    499: IOReturn IOUSBHubPort::defaultSuspendChangeHandler(UInt16 changeFlags)
                    500: {
                    501: #if (DEBUGGING_LEVEL > 0)
                    502:     DEBUGLOG("IOUSBHubPort: suspend change notification\n");
                    503: #endif
                    504:     return kIOReturnSuccess;
                    505: }
                    506: 
                    507: IOReturn IOUSBHubPort::defaultEnableChangeHandler(UInt16 changeFlags)
                    508: {
                    509:     IOReturn           err = kIOReturnSuccess;
                    510:     IOUSBHubPortStatus status;
                    511: 
                    512: #if (DEBUGGING_LEVEL > 0)
                    513:     DEBUGLOG("IOUSBHubPort: enable change notification\n");
                    514: #endif
                    515: 
                    516:     if ((err = _hub->GetPortStatus(&status, _portNum)))
                    517:     {
                    518:         fatalError(err, "getting port status");
                    519:         return err;
                    520:     }
                    521: 
                    522:     if (!(status.statusFlags & kHubPortEnabled) &&
                    523:         !(changeFlags & kHubPortConnection))
                    524:     {
                    525:         // The hub gave us an enable status change and we're
                    526:         // now disabled, strange.  Cosmo does this sometimes,
                    527:         // try Re-enabling the port.
                    528: #if (DEBUGGING_LEVEL > 0)
                    529:         DEBUGLOG("IOUSBHubPort: re-enabling dead port %d\n", _portNum);
                    530: #endif
                    531:         if ((err = _hub->SetPortFeature(kUSBHubPortEnableFeature, _portNum)))
                    532:             fatalError(err, "re-enabling dead port");
                    533:     }
                    534:     return err;
                    535: }
                    536: 
                    537: IOReturn IOUSBHubPort::defaultConnectionChangeHandler(UInt16 changeFlags)
                    538: {
                    539:     IOReturn   err = kIOReturnSuccess;
                    540:     IOUSBHubPortStatus status;
                    541: 
                    542: #if (DEBUGGING_LEVEL > 0)
                    543:     DEBUGLOG("0x%x\t(port %d)connection change notification\n",  _hub, _portNum);
                    544: #endif
                    545: 
                    546:     do
                    547:     {
                    548:         /* wait for the power on good time */
                    549:         IOSleep(_hubDesc->powerOnToGood * 2);
                    550: 
                    551:         // If we get to here, there was a connection change
                    552:         // if we already have a device it must have been disconnected
                    553:         // at sometime. We should kill it before servicing a connect event
                    554:         if (_portDevice != 0)
                    555:         {      
                    556: #if (DEBUGGING_LEVEL > 0)
                    557:             DEBUGLOG("0x%x\t(port %d): removing %s device @ %d\n",
                    558:                _hub, _portNum, _portDevice->getName(), _portDevice->address());
                    559: #endif
                    560: 
                    561:             removeDevice();    
                    562:         }
                    563: 
                    564:         // BT 23Jul98 Check port again after delay. Get bounced connections
                    565:         /* Do a port status request on current port */
                    566:         if ((err = _hub->GetPortStatus(&status, _portNum)))
                    567:         {
                    568:             fatalError(err, "getting port status");
                    569:             break;
                    570:         }
                    571: 
                    572: #if (DEBUGGING_LEVEL > 0)
                    573:         DEBUGLOG("0x%x\t(conn change) port %d status = %xs/%xc\n", _hub,
                    574:                  _portNum, status.statusFlags, status.changeFlags);
                    575: #endif
                    576: 
                    577:         if (status.changeFlags & kHubPortConnection)
                    578:         {
                    579:             DEBUGLOG("IOUSBHubPort: connection bounce\n");
                    580:             break;
                    581:         }
                    582: 
                    583:         if (status.statusFlags & kHubPortConnection)
                    584:         {
                    585:             /* We have a connection on this port */
                    586: #if (DEBUGGING_LEVEL > 0)
                    587:             DEBUGLOG("0x%x\tdevice detected @ port %d\n", _hub, _portNum);
                    588: #endif
                    589:             for(int i=0; i<2; i++) {
                    590:                 err = addDevice();
                    591:                 if (err == kIOReturnSuccess)
                    592:                     break;
                    593:                 err = _hub->ClearPortFeature(kUSBHubPortEnableFeature, _portNum);
                    594:                 if (err != kIOReturnSuccess)
                    595:                     fatalError(err, "adding device");
                    596:             }
                    597:         }
                    598:         
                    599:     } while(false);
                    600:     return err;
                    601: }
                    602: 
                    603: bool IOUSBHubPort::statusChanged(void)
                    604: {
                    605:     IOReturn   err = kIOReturnSuccess;
                    606:     int        which;
                    607:     IOUSBHubPortStatus status;
                    608: 
                    609:     
                    610:     do
                    611:     {
                    612:         /* Do a port status request on current port */
                    613:         if ((err = _hub->GetPortStatus(&status, _portNum)))
                    614:         {
                    615:             fatalError(err, "get status (first in port status change)");
                    616:             break;
                    617:         }
                    618: 
                    619: #if (DEBUGGING_LEVEL > 0)
                    620:         DEBUGLOG("0x%x\t(status changed 1) port %d status = %xs/%xc\n", _hub,
                    621:               _portNum, status.statusFlags, status.changeFlags);
                    622: #endif
                    623: 
                    624:         // First clear the change condition before we return.  This prevents
                    625:         // a race condition for handling the change.
                    626:         for (which = 0; which < kNumChangeHandlers; which++)
                    627:         {
                    628:             // sometimes a change is reported but there really is
                    629:             // no change.  This will catch that.
                    630:             if (!(status.changeFlags & _changeHandler[which].bit))
                    631:                 continue;
                    632: 
                    633:             if ((err = _hub->ClearPortFeature(
                    634:                     _changeHandler[which].clearFeature, _portNum)))
                    635:             {
                    636:                 fatalError(err, "clear port vector bit feature");
                    637:                 continue;
                    638:             }
                    639:         }
                    640: 
                    641:         err = statusChangeHandler(status.changeFlags);
                    642: 
                    643:     } while(false);
                    644: 
                    645:     return(err == kIOReturnSuccess);
                    646: }
                    647: 
                    648: 
                    649: IOReturn IOUSBHubPort::statusChangeHandler(UInt16 changeFlags)
                    650: {
                    651:     int which;
                    652:     IOReturn res = kIOReturnSuccess;
                    653: 
                    654:     // Handle each change in sequential order.
                    655:     for (which = 0; which < kNumChangeHandlers; which++)
                    656:     {
                    657:         if (!(changeFlags & _changeHandler[which].bit))
                    658:             continue;
                    659:         res = (self->*_changeHandler[which].handler)(changeFlags);
                    660:         if(res != kIOReturnSuccess)
                    661:             break;
                    662:     }
                    663: 
                    664:     return(res);
                    665: }
                    666: 
                    667: 
                    668: void IOUSBHubPort::initPortVectors(void)
                    669: {
                    670:     int vector;
                    671:     for (vector = 0; vector < kNumChangeHandlers; vector++)
                    672:     {
                    673:         _changeHandler[vector] = defaultPortVectors[vector];
                    674:         switch (defaultPortVectors[vector].bit)
                    675:         {
                    676:             case kHubPortOverCurrent:
                    677:                 _changeHandler[vector].handler =
                    678:                 &IOUSBHubPort::defaultOverCrntChangeHandler;
                    679:                 break;
                    680:             case kHubPortBeingReset:
                    681:                 _changeHandler[vector].handler =
                    682:                 &IOUSBHubPort::defaultResetChangeHandler;
                    683:                 break;
                    684:             case kHubPortSuspend:
                    685:                 _changeHandler[vector].handler =
                    686:                 &IOUSBHubPort::defaultSuspendChangeHandler;
                    687:                 break;
                    688:             case kHubPortEnabled:
                    689:                 _changeHandler[vector].handler =
                    690:                 &IOUSBHubPort::defaultEnableChangeHandler;
                    691:                 break;
                    692:             case kHubPortConnection:
                    693:                 _changeHandler[vector].handler =
                    694:                 &IOUSBHubPort::defaultConnectionChangeHandler;
                    695:                 break;
                    696:         }
                    697:     }
                    698: }
                    699: 
                    700: void IOUSBHubPort::setPortVector(ChangeHandlerFuncPtr  routine,
                    701:                                  UInt32                        condition)
                    702: {
                    703:     int vector;
                    704:     for(vector = 0; vector < kNumChangeHandlers; vector++)
                    705:     {
                    706:         if(condition == _changeHandler[vector].bit)
                    707:         {
                    708:             _changeHandler[vector].handler = routine;
                    709:         }
                    710:     }
                    711: }

unix.superglobalmegacorp.com

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