|
|
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.