|
|
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: * 08 Dec 98 ehewitt created.
27: *
28: */
29:
30: #include <libkern/OSByteOrder.h>
31:
32: #include <libkern/c++/OSDictionary.h>
33: #include <IOKit/IOMemoryDescriptor.h>
34: #include <libkern/c++/OSData.h>
35:
36: #include <IOKit/usb/USB.h>
37: #include <IOKit/usb/IOUSBController.h>
38: #include <IOKit/usb/IOUSBNub.h>
39: #include <IOKit/usb/IOUSBPipe.h>
40:
41: #include "IOUSBUserClient.h"
42: #include "IOUSBHub.h"
43:
44: static int devdebug = 0;
45: #define DEBUGLOG if (devdebug) kprintf
46:
47: static const IOUSBDescriptorHeader *nextDescriptor(const void *desc)
48: {
49: const UInt8 *next = (const UInt8 *)desc;
50: UInt8 length = next[0];
51: next = &next[length];
52: return((const IOUSBDescriptorHeader *)next);
53: }
54:
55: const IOUSBDescriptorHeader *
56: IOUSBNub::findNextDescriptor(const void *cur, UInt8 descType)
57: {
58: const IOUSBDescriptorHeader *hdr;
59: hdr = (const IOUSBDescriptorHeader *)cur;
60: do {
61: hdr = nextDescriptor(hdr);
62: if(hdr->length == 0)
63: break;
64: if(descType == 0)
65: return hdr; // type 0 is wildcard.
66: else if(hdr->descriptorType == descType)
67: return hdr;
68: }
69: while(true);
70:
71: return NULL; // Fell off end of list
72: }
73:
74: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
75:
76: OSDefineMetaClass( IOUSBNub, IOService )
77: OSDefineAbstractStructors(IOUSBNub, IOService)
78:
79: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
80:
81: bool IOUSBNub::init(OSDictionary * propTable)
82: {
83: OSData * addressProperty;
84: OSData * descProperty;
85: OSData * powerProperty;
86: OSData * speedProperty;
87:
88: if( !IOService::init(propTable))
89: return (false);
90:
91: addressProperty = (OSData *) propTable->getObject("device address");
92: descProperty = (OSData *) propTable->getObject("device descriptor");
93: powerProperty = (OSData *) propTable->getObject("bus power available");
94: speedProperty = (OSData *) propTable->getObject("low speed device");
95: if (!addressProperty || !powerProperty || !speedProperty || !descProperty)
96: {
97: IOLog("%s: Unable to initialize\n", getName());
98: return (false);
99: }
100: _address = *((USBDeviceAddress *) addressProperty->getBytesNoCopy());
101:
102: bcopy(descProperty->getBytesNoCopy(), &_descriptor,
103: descProperty->getLength());
104:
105: _busPowerAvailable = *((UInt32 *) powerProperty->getBytesNoCopy());
106: _speed = *((UInt8 *) speedProperty->getBytesNoCopy());
107: DEBUGLOG("%s @ %d (%ldmA available, %s speed)\n", getName(), _address,_busPowerAvailable*2, _speed ? "low" : "high");
108:
109: #if (devdebug > 0)
110: printDeviceDescriptor(&_descriptor);
111: #endif
112:
113: return (true);
114: }
115:
116: bool IOUSBNub::finalize(IOOptionBits options)
117: {
118: if(_pipeZero) {
119: _pipeZero->release();
120: _pipeZero = NULL;
121: }
122: return(IOService::finalize(options));
123: }
124:
125: USBDeviceAddress IOUSBNub::address(void)
126: {
127: return(_address);
128: }
129:
130: const IOUSBDeviceDescriptor * IOUSBNub::deviceDescriptor(void)
131: {
132: return(&_descriptor);
133: }
134:
135: IOUSBController * IOUSBNub::bus(void)
136: {
137: return(_controller);
138: }
139:
140: UInt32 IOUSBNub::busPowerAvailable( void )
141: {
142: return(_busPowerAvailable);
143: }
144:
145: IOUSBPipe * IOUSBNub::pipeZero()
146: {
147: return _pipeZero;
148: }
149:
150: // Lowlevel requests for non-standard device requests
151: IOReturn IOUSBNub::deviceRequest(IOUSBDevRequest *request,
152: IOUSBCompletion *completion = 0)
153: {
154: UInt16 theRequest;
155: theRequest = EncodeRequest(request->bRequest, request->rqDirection,
156: request->rqType, request->rqRecipient);
157: if (theRequest == kSetAddress) {
158: DEBUGLOG("\tignoring kSetAddress\n");
159: return kIOReturnNotPermitted;
160: }
161: return(_pipeZero->controlRequest(request, completion));
162: }
163:
164: IOReturn IOUSBNub::deviceRequest(IOUSBDevRequestDesc *request,
165: IOUSBCompletion *completion = 0)
166: {
167: UInt16 theRequest;
168: theRequest = EncodeRequest(request->bRequest, request->rqDirection,
169: request->rqType, request->rqRecipient);
170: if (theRequest == kSetAddress) {
171: DEBUGLOG("\tignoring kSetAddress\n");
172: return kIOReturnNotPermitted;
173: }
174: return(_pipeZero->controlRequest(request, completion));
175: }
176:
177:
178: IOReturn IOUSBNub::GetConfiguration(UInt8 *configNumber)
179: {
180: IOReturn err = kIOReturnSuccess;
181: IOUSBDevRequest request;
182:
183: DEBUGLOG("************ GET CONFIGURATION *************\n");
184:
185: request.rqDirection = kUSBIn;
186: request.rqType = kUSBStandard;
187: request.rqRecipient = kUSBDevice;
188: request.bRequest = kUSBRqGetConfig;
189: OSWriteLittleInt16(&request.wValue, 0, 0);
190: OSWriteLittleInt16(&request.wIndex, 0, 0);
191: OSWriteLittleInt16(&request.wLength, 0, sizeof(*configNumber));
192: request.pData = configNumber;
193:
194: err = deviceRequest(&request);
195:
196: if (err)
197: {
198: DEBUGLOG("%s: error getting config. err=%d\n", getName(), err);
199: }
200:
201: return(err);
202: }
203:
204: IOReturn IOUSBNub::GetDeviceStatus(USBStatus *status)
205: {
206: IOReturn err = kIOReturnSuccess;
207: IOUSBDevRequest request;
208:
209: DEBUGLOG("*********** GET DEVICE STATUS ***********\n");
210:
211: request.rqDirection = kUSBIn;
212: request.rqType = kUSBStandard;
213: request.rqRecipient = kUSBDevice;
214: request.bRequest = kUSBRqGetStatus;
215: OSWriteLittleInt16(&request.wValue, 0, 0);
216: OSWriteLittleInt16(&request.wIndex, 0, 0);
217: OSWriteLittleInt16(&request.wLength, 0, sizeof(*status));
218: request.pData = status;
219:
220: err = deviceRequest(&request);
221:
222: if (err)
223: IOLog("%s: error getting device status. err=%d\n", getName(), err);
224:
225: return(err);
226: }
227:
228: IOReturn IOUSBNub::GetStringDescriptor(UInt8 index,
229: char *buf, int maxLen, UInt16 lang)
230: {
231: IOReturn err;
232: UInt8 desc[256]; // Max possible descriptor length
233: IOUSBDevRequest request;
234: int i, len;
235:
236: DEBUGLOG("*********** GET STRING DESCRIPTOR %d, lang 0x%x***********\n", index, lang);
237:
238: // First get actual length (lame devices don't like being asked for too much data)
239: request.rqDirection = kUSBIn;
240: request.rqType = kUSBStandard;
241: request.rqRecipient = kUSBDevice;
242: request.bRequest = kUSBRqGetDescriptor;
243: OSWriteLittleInt16(&request.wValue, 0, (kUSBStringDesc << 8) | index);
244: OSWriteLittleInt16(&request.wIndex, 0, lang);
245:
246: OSWriteLittleInt16(&request.wLength, 0, 2);
247: bzero(desc, 2);
248: request.pData = &desc;
249:
250: err = deviceRequest(&request);
251:
252: if (err != kIOReturnSuccess)
253: return(err);
254:
255: request.rqDirection = kUSBIn;
256: request.rqType = kUSBStandard;
257: request.rqRecipient = kUSBDevice;
258: request.bRequest = kUSBRqGetDescriptor;
259: len = desc[0];
260: if(len == 0)
261: len = sizeof(desc); // Silly result for small read, try big one.
262: OSWriteLittleInt16(&request.wValue, 0, (kUSBStringDesc << 8) | index);
263: OSWriteLittleInt16(&request.wIndex, 0, lang);
264: OSWriteLittleInt16(&request.wLength, 0, len);
265: request.pData = &desc;
266:
267: err = deviceRequest(&request);
268:
269: if (err != kIOReturnSuccess)
270: return(err);
271: DEBUGLOG("*********** Got STRING DESCRIPTOR %d, length 0x%x, got 0x%x***********\n",
272: index, desc[0], OSReadLittleInt16(&request.wLength, 0));
273: len = (desc[0]-2)/2;
274: if(len > maxLen-1)
275: len = maxLen-1;
276: for(i=0; i<len; i++)
277: buf[i] = desc[2*i+2];
278: buf[len] = 0;
279:
280: return kIOReturnSuccess;
281: }
282:
283: UInt32 IOUSBNub::GetBandwidthAvailable()
284: {
285: return _controller->GetBandwidthAvailable();
286: }
287:
288: UInt64 IOUSBNub::GetFrameNumber()
289: {
290: return _controller->GetFrameNumber();
291: }
292:
293: /**
294: ** Matching methods
295: **/
296: bool IOUSBNub::matchPropertyTable(OSDictionary * table)
297: {
298: //
299: // If the service object wishes to compare some of its properties in its
300: // property table against the supplied matching dictionary,
301: // it should do so in this method and return truth on success.
302: //
303:
304: if (!IOService::matchPropertyTable(table)) return false;
305:
306: // We return success if the following expression is true -- individual
307: // comparisions evaluate to truth if the named property is not present
308: // in the supplied matching dictionary.
309:
310: return compareProperty(table, "class") &&
311: compareProperty(table, "subClass") &&
312: compareProperty(table, "protocol") &&
313: compareProperty(table, "vendor") &&
314: compareProperty(table, "product") &&
315: compareProperty(table, "version");
316: }
317:
318: #ifdef __cplusplus
319: extern "C" {
320: #endif
321:
322: void printDescriptor(IOUSBDescriptorHeader *desc)
323: {
324: if (!desc)
325: return;
326:
327: switch (desc->descriptorType)
328: {
329: case kUSBDeviceDesc:
330: printDeviceDescriptor((IOUSBDeviceDescriptor *)desc); break;
331: case kUSBConfDesc:
332: printConfigDescriptor((IOUSBConfigurationDescriptor *)desc); break;
333: case kUSBInterfaceDesc:
334: printInterfaceDescriptor((IOUSBInterfaceDescriptor *)desc); break;
335: case kUSBEndpointDesc:
336: printEndpointDescriptor((IOUSBEndpointDescriptor *)desc); break;
337: default:
338: DEBUGLOG("printDescriptor: unknown descriptor type (%d)\n",
339: desc->descriptorType);
340:
341: }
342: }
343:
344: // for debugging. Should print generic
345: // descriptor based on descriptor type.
346: void printDeviceDescriptor(IOUSBDeviceDescriptor *desc)
347: {
348: if (!desc)
349: return;
350:
351: DEBUGLOG("device descriptor: v0x%x (%d bytes) type = %d %d configs\n",
352: OSReadLittleInt16(&desc->usbRel, 0), desc->length, desc->descType,
353: desc->numConf);
354: DEBUGLOG("\tclass = [%d:%d:%d] maxPacketSize = %d\n", desc->deviceClass,
355: desc->deviceSubClass, desc->protocol, desc->maxPacketSize);
356: DEBUGLOG("\tvendor = [%x:%x:%x] idx's = [%d:%d:%d]\n",
357: OSReadLittleInt16(&desc->vendor, 0), USBToHostWord(desc->product),
358: OSReadLittleInt16(&desc->devRel, 0), desc->manuIdx, desc->prodIdx,
359: desc->serialIdx);
360: }
361:
362: // for debugging -- nothing yet. Should print generic
363: // descriptor based on descriptor type.
364: void printConfigDescriptor(IOUSBConfigurationDescriptor *cd)
365: {
366: void *end;
367: const IOUSBDescriptorHeader *dp;
368:
369: if (!cd)
370: return;
371:
372: DEBUGLOG("CONFIG #%d: (%d bytes) T(%d bytes) ",
373: cd->configValue, cd->length, OSReadLittleInt16(&cd->totalLength, 0));
374: DEBUGLOG("descType = %d numInterfaces = %d ",
375: cd->descriptorType, cd->numInterfaces);
376: DEBUGLOG("attributes = %d maxPower = %d\n",
377: cd->attributes, cd->maxPower);
378:
379: end = (void *)(((UInt8 *)cd) + OSReadLittleInt16(&cd->totalLength, 0));
380: dp = nextDescriptor((const IOUSBDescriptorHeader *)cd);
381:
382: while(dp < end)
383: {
384: if (dp->descriptorType == kUSBInterfaceDesc)
385: printInterfaceDescriptor((IOUSBInterfaceDescriptor *)dp);
386: else if (dp->descriptorType == kUSBEndpointDesc)
387: printEndpointDescriptor((IOUSBEndpointDescriptor *)dp);
388: else
389: DEBUGLOG("Unknown descriptor type %d\n", dp->descriptorType);
390:
391: dp = nextDescriptor(dp);
392: }
393: }
394:
395: void printInterfaceDescriptor(IOUSBInterfaceDescriptor *id)
396: {
397: if (!id)
398: return;
399:
400: DEBUGLOG("INTERFACE #%d/%d: (%d bytes) type = %d ",
401: id->interfaceNumber, id->alternateSetting, id->length,
402: id->descriptorType);
403: DEBUGLOG("class = [%d:%d:%d] numEndpoints = %d\n", id->interfaceClass,
404: id->interfaceSubClass, id->interfaceProtocol, id->numEndpoints);
405: }
406:
407: void printEndpointDescriptor(IOUSBEndpointDescriptor *ed)
408: {
409: char *eType[] = { "control", "isochronous", "bulk", "interrupt" };
410: if (!ed)
411: return;
412:
413: DEBUGLOG("ENDPOINT #%x (%s): (%d bytes, type %d) type = %d (%s) ",
414: ed->endpointAddress & 0x0F, ed->endpointAddress & 0x80 ? "in" : "out",
415: ed->length, ed->descriptorType, ed->attributes & 0x03,
416: eType[ed->attributes & 0x03]);
417: DEBUGLOG("interval = %dms maxPacketSize = %d\n",
418: ed->interval, OSReadLittleInt16(&ed->maxPacketSizeLo, 0));
419: }
420:
421: #ifdef __cplusplus
422: }
423: #endif
424:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.