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