|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.