|
|
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/IOUSBDevice.h>
39: #include <IOKit/usb/IOUSBInterface.h>
40: #include <IOKit/usb/IOUSBPipe.h>
41:
42: #include "IOUSBUserClient.h"
43: #include "IOUSBHub.h"
44:
45: #define super IOUSBNub
46:
47: static int devdebug = 0;
48: #define DEBUGLOG if (devdebug) kprintf
49:
50: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
51:
52: OSDefineMetaClassAndStructors(IOUSBDevice, IOUSBNub)
53:
54: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
55:
56: void IOUSBDevice::setPort(IOUSBHubPort *port)
57: {
58: _port = port;
59: }
60:
61: bool IOUSBDevice::init(OSDictionary * propTable)
62: {
63: if(!IOUSBNub::init(propTable))
64: return false;
65: if(_descriptor.numConf) {
66: _configList = (UInt8 **)IOMalloc(sizeof(UInt8 *) * _descriptor.numConf);
67: if(!_configList)
68: return false;
69: bzero(_configList, sizeof(UInt8 *) * _descriptor.numConf);
70: }
71: return true;
72: }
73:
74: void IOUSBDevice::free()
75: {
76: if(_configList) {
77: int i;
78: for(i=0; i<_descriptor.numConf; i++) {
79: if(_configList[i]) {
80: int len = OSReadLittleInt16(&((IOUSBConfigurationDescriptor *)_configList[i])->totalLength, 0);
81: IOFree(_configList[i], len+2);
82: _configList[i] = NULL;
83: }
84: }
85: IOFree(_configList, sizeof(UInt8 *) * _descriptor.numConf);
86: }
87: IOUSBNub::free();
88: }
89:
90: bool IOUSBDevice::attach(IOService *provider)
91: {
92: IOReturn err;
93: char name[128];
94:
95: if( !IOUSBNub::attach(provider))
96: return (false);
97: // Set controller if we weren't given one earlier.
98: if(_controller == NULL)
99: _controller = OSDynamicCast(IOUSBController, provider);
100: if(_controller == NULL)
101: return false;
102:
103: // Don't do this until we have a controller
104: _endpointZero.length = sizeof(_endpointZero);
105: _endpointZero.descriptorType = kUSBEndpointDesc;
106: _endpointZero.endpointAddress = 0;
107: _endpointZero.attributes = kUSBControl;
108: OSWriteLittleInt16(&_endpointZero.maxPacketSizeLo, 0, _descriptor.maxPacketSize);
109: _endpointZero.interval = 0;
110:
111: _pipeZero = IOUSBPipe::toEndpoint(&_endpointZero, _speed, _address, _controller);
112:
113: if(_descriptor.prodIdx) {
114: err = GetStringDescriptor(_descriptor.prodIdx, name, sizeof(name));
115: if(err == kIOReturnSuccess) {
116: setName(name);
117: setProperty("USB Product Name", name);
118: }
119: }
120: if(_descriptor.manuIdx) {
121: err = GetStringDescriptor(_descriptor.manuIdx, name, sizeof(name));
122: if(err == kIOReturnSuccess) {
123: setProperty("USB Vendor Name", name);
124: }
125: }
126: if(_descriptor.serialIdx) {
127: err = GetStringDescriptor(_descriptor.serialIdx, name, sizeof(name));
128: if(err == kIOReturnSuccess) {
129: setProperty("USB Serial Number", name);
130: }
131: }
132: return true;
133: }
134:
135: // Stop all activity, reset device, restart.
136: IOReturn IOUSBDevice::resetDevice()
137: {
138: IOReturn err;
139:
140: if(_pipeZero) {
141: _pipeZero->release();
142: _pipeZero = NULL;
143: }
144: err = _port->resetDevice();
145:
146: // Recreate pipe 0 object
147: if(err == kIOReturnSuccess) {
148: _pipeZero = IOUSBPipe::toEndpoint(&_endpointZero, _speed, _address, _controller);
149: if(!_pipeZero)
150: err = kIOReturnNoMemory;
151: }
152:
153: return err;
154: }
155:
156: /******************************************************
157: * Helper Methods
158: ******************************************************/
159:
160: const IOUSBConfigurationDescriptor *
161: IOUSBDevice::findConfig(UInt8 configValue, int *configIndex)
162: {
163: int i;
164: const IOUSBConfigurationDescriptor *cd = NULL;
165:
166: for(i = 0; i < _descriptor.numConf; i++) {
167: cd = getFullConfigurationDescriptor(i);
168: if(!cd)
169: continue;
170: if(cd->configValue == configValue)
171: break;
172: }
173: if(cd && configIndex)
174: *configIndex = i;
175:
176: return cd;
177: }
178:
179: // Finding the correct interface
180: /*
181: * findNextInterface
182: * This method should really be rewritten to use iterators or
183: * be broken out into more functions without a request structure.
184: * Or even better, make the interfaces and endpoint objects that
185: * have their own methods for this stuff.
186: *
187: * returns:
188: * next interface matching criteria. 0 if no matches
189: */
190: IOUSBInterface *
191: IOUSBDevice::findNextInterface(IOUSBInterface *current,
192: FindInterfaceRequest *request)
193: {
194: const IOUSBConfigurationDescriptor *cd;
195: const IOUSBInterfaceDescriptor * id;
196: const IOUSBDescriptorHeader * pos = NULL;
197: bool found;
198: int configIndex;
199: if(current == NULL) {
200: configIndex = 0;
201: cd = getFullConfigurationDescriptor(configIndex);
202: if(!cd)
203: return NULL;
204: pos = (IOUSBDescriptorHeader *)cd;
205: }
206: else {
207: cd = findConfig(current->getConfigValue(), &configIndex);
208: if(!cd)
209: return NULL;
210: pos = (IOUSBDescriptorHeader *)cd;
211: while((pos = findNextDescriptor(pos, kUSBInterfaceDesc))) {
212: if(bcmp(pos, current->interfaceDescriptor(),
213: sizeof(IOUSBInterfaceDescriptor)) == 0) {
214: break;
215: }
216: }
217: }
218: while (configIndex < _descriptor.numConf)
219: {
220: pos = findNextDescriptor(pos, kUSBInterfaceDesc);
221: if(pos == NULL) {
222: // End of that configuration
223: configIndex++;
224: if(configIndex >= _descriptor.numConf)
225: break;
226:
227: cd = getFullConfigurationDescriptor(configIndex);
228: continue;
229: }
230: id = (const IOUSBInterfaceDescriptor *)pos;
231:
232: // check the request parameters
233: found = true;
234: if (request->theClass != 0 && request->theClass != id->interfaceClass)
235: found = false; // this is not it
236: if (request->subClass != 0 && request->subClass != id->interfaceSubClass)
237: found = false; // this is not it
238: if (request->protocol != 0 && request->protocol != id->interfaceProtocol)
239: found = false; // this is not it
240: if (request->maxPower != 0 && request->maxPower < cd->maxPower)
241: found = false; // draws too much power
242: if (id->alternateSetting != 0)
243: found = false; // Only want main setting
244:
245: if (found)
246: {
247: request->theClass = id->interfaceClass;
248: request->subClass = id->interfaceSubClass;
249: request->protocol = id->interfaceProtocol;
250: request->maxPower = cd->maxPower;
251: request->busPowered = cd->attributes & kUSBAtrBusPowered ? 2 : 1;
252: request->selfPowered = cd->attributes & kUSBAtrSelfPowered ? 2 : 1;
253: request->remoteWakeup = cd->attributes & kUSBAtrRemoteWakeup ? 2 : 1;
254: return(GetInterface(id, cd));
255: }
256: }
257: return(0);
258: }
259:
260: const IOUSBConfigurationDescriptor *IOUSBDevice::getFullConfigurationDescriptor(UInt8 index)
261: {
262: IOReturn err;
263:
264: if(_configList[index] == NULL) {
265: int len;
266: IOUSBConfigurationDescriptor temp;
267: err = GetConfigDescriptor(index, &temp, sizeof(temp));
268: if (err) {
269: DEBUGLOG("getFullConfigurationDescriptor: Error 0x%x getting configuration descriptor\n", err);
270: return(0);
271: }
272: len = OSReadLittleInt16(&temp.totalLength, 0);
273: _configList[index] = (UInt8 *)IOMalloc(len + 2);
274: if(_configList[index] == NULL)
275: return 0;
276: err = GetConfigDescriptor(index, _configList[index], len);
277: if (err) {
278: DEBUGLOG("getFullConfigurationDescriptor: Error %d getting full configuration\n", err);
279: return(0);
280: }
281: *(_configList[index]+len) = 0; // A Known ~Elephant.
282: *(_configList[index]+len+1) = 0;// A Known ~Elephant.
283: }
284: return (IOUSBConfigurationDescriptor *)_configList[index];
285: }
286:
287: /*
288: * GetConfigDescriptor:
289: * In: pointer to buffer for config descriptor, length to get
290: * Assumes: desc is has enough space to put it all
291: */
292: IOReturn IOUSBDevice::GetConfigDescriptor(UInt8 configIndex,
293: void *desc, int len)
294: {
295: IOReturn err = kIOReturnSuccess;
296: IOUSBDevRequest request;
297:
298: DEBUGLOG("********** GET CONFIG DESCRIPTOR (%d)**********\n", len);
299:
300: /*
301: * with config descriptors, the device will send back all descriptors,
302: * if the request is big enough.
303: */
304:
305: request.rqDirection = kUSBIn;
306: request.rqType = kUSBStandard;
307: request.rqRecipient = kUSBDevice;
308: request.bRequest = kUSBRqGetDescriptor;
309: OSWriteLittleInt16(&request.wValue, 0, (kUSBConfDesc << 8) + configIndex);
310: OSWriteLittleInt16(&request.wIndex, 0, 0);
311: OSWriteLittleInt16(&request.wLength, 0, len);
312: request.pData = desc;
313:
314: err = deviceRequest(&request);
315:
316: if (err)
317: {
318: DEBUGLOG("%s: error getting device config descriptor. err=0x%x\n", getName(), err);
319: }
320:
321: return(err);
322: }
323:
324: IOReturn IOUSBDevice::SetConfiguration(UInt8 configNumber)
325: {
326: IOReturn err = kIOReturnSuccess;
327: IOUSBDevRequest request;
328:
329: DEBUGLOG("********** SET CONFIGURATION TO %d **********\n", configNumber);
330:
331: request.rqDirection = kUSBOut;
332: request.rqType = kUSBStandard;
333: request.rqRecipient = kUSBDevice;
334: request.bRequest = kUSBRqSetConfig;
335: OSWriteLittleInt16(&request.wValue, 0, configNumber);
336: OSWriteLittleInt16(&request.wIndex, 0, 0);
337: OSWriteLittleInt16(&request.wLength, 0, 0);
338: request.pData = 0;
339:
340: err = deviceRequest(&request);
341:
342: if (err)
343: {
344: DEBUGLOG("%s: error setting config. err=%d\n", getName(), err);
345: }
346:
347: return(err);
348: }
349:
350: IOUSBInterface * IOUSBDevice::GetInterface(const IOUSBInterfaceDescriptor *interface,
351: const IOUSBConfigurationDescriptor *config)
352: {
353: OSDictionary * propTable = 0;
354: OSArray * epArray = 0;
355: IOUSBInterface * newDevice = 0;
356: OSData * data;
357: OSNumber * offset;
358: int i;
359: char location[8];
360: OSIterator * clients;
361: /*
362: * First see if the interface has already been created,
363: * ie. there's already one with the given interface descriptor and config descriptor
364: */
365: clients = getClientIterator();
366: if(clients) {
367: OSObject *next;
368: while((next = clients->getNextObject())) {
369: IOUSBInterface *testIt = OSDynamicCast(IOUSBInterface, next);
370: if(testIt) {
371: if(config->configValue == testIt->getConfigValue() &&
372: bcmp(interface, testIt->interfaceDescriptor(), sizeof(IOUSBInterfaceDescriptor)) == 0) {
373: newDevice = testIt;
374: break;
375: }
376: }
377: }
378: clients->release();
379: }
380: if(newDevice) {
381: newDevice->retain();
382: return newDevice;
383: }
384: do {
385: propTable = OSDictionary::withCapacity(13);
386: if (!propTable)
387: continue;
388:
389: data = OSData::withBytes( &_descriptor, sizeof( _descriptor ));
390: if (data) {
391: propTable->setObject("device descriptor", data);
392: data->release();
393: }
394: offset = OSNumber::withNumber(interface->interfaceClass, 8);
395: if(offset) {
396: propTable->setObject("class", offset);
397: offset->release();
398: }
399: offset = OSNumber::withNumber(interface->interfaceSubClass, 8);
400: if(offset) {
401: propTable->setObject("subClass", offset);
402: offset->release();
403: }
404: offset = OSNumber::withNumber(interface->interfaceProtocol, 8);
405: if(offset) {
406: propTable->setObject("protocol", offset);
407: offset->release();
408: }
409: offset = OSNumber::withNumber(OSReadLittleInt16(&_descriptor.vendor, 0), 16);
410: if(offset) {
411: propTable->setObject("vendor", offset);
412: offset->release();
413: }
414: offset = OSNumber::withNumber(OSReadLittleInt16(&_descriptor.product, 0), 16);
415: if(offset) {
416: propTable->setObject("product", offset);
417: offset->release();
418: }
419: offset = OSNumber::withNumber(OSReadLittleInt16(&_descriptor.devRel, 0), 16);
420: if(offset) {
421: propTable->setObject("version", offset);
422: offset->release();
423: }
424: data = OSData::withBytes(&_address, sizeof( _address ));
425: if (data) {
426: propTable->setObject("device address", data);
427: data->release();
428: }
429: data = OSData::withBytes( config,
430: sizeof( *config ));
431: if (data) {
432: propTable->setObject("configuration descriptor", data);
433: data->release();
434: }
435: data = OSData::withBytes( interface,
436: sizeof(*interface));
437: if (data) {
438: propTable->setObject("interface descriptor", data);
439: data->release();
440: }
441: data = OSData::withBytes(&_busPowerAvailable, sizeof(_busPowerAvailable));
442: if (data) {
443: propTable->setObject("bus power available", data);
444: data->release();
445: }
446: data = OSData::withBytes(&_speed, sizeof(_speed));
447: if (data) {
448: propTable->setObject("low speed device", data);
449: data->release();
450: }
451:
452: epArray = OSArray::withCapacity(interface->numEndpoints);
453: if (!epArray)
454: continue;
455: IOUSBEndpointDescriptor *ep = (IOUSBEndpointDescriptor *)interface;
456: for(i=0; i<interface->numEndpoints; i++) {
457: ep = (IOUSBEndpointDescriptor *)findNextDescriptor(ep, kUSBEndpointDesc);
458: if(!ep)
459: break;
460: data = OSData::withBytes(ep, sizeof(IOUSBEndpointDescriptor));
461: if (data) {
462: epArray->setObject(i, data);
463: data->release();
464: }
465: }
466: propTable->setObject("Endpoints", epArray);
467: epArray->release();
468:
469: newDevice = createInterface(propTable, config, interface);
470:
471: if (!newDevice )
472: continue;
473:
474: propTable->release(); // done with it after init
475: propTable = 0;
476:
477: sprintf( location, "%x", _address );
478: newDevice->setLocation(location);
479: if (!newDevice->attach(this))
480: break;
481:
482: return(newDevice);
483:
484: } while (false);
485:
486: if (propTable)
487: propTable->release();
488: if (epArray)
489: epArray->release();
490: if (newDevice)
491: newDevice->release();
492:
493: return(NULL);
494: }
495:
496: IOUSBInterface *
497: IOUSBDevice::createInterface(OSDictionary *table,
498: const IOUSBConfigurationDescriptor *config,
499: const IOUSBInterfaceDescriptor *interface)
500: {
501: IOUSBInterface *newIface;
502:
503: newIface = new IOUSBInterface;
504: if(!newIface)
505: return NULL;
506: if(!newIface->init(table, config, interface)) {
507: newIface->release();
508: newIface = NULL;
509: }
510: return newIface;
511: }
512:
513: // Copy data into supplied buffer, up to 'len' bytes.
514: IOReturn IOUSBDevice::getConfigurationDescriptor(UInt8 configValue, void *data, UInt32 len)
515: {
516: unsigned int toCopy;
517: const IOUSBConfigurationDescriptor *cd;
518: cd = findConfig(configValue);
519: if(!cd)
520: return kIOUSBConfigNotFound;
521:
522: toCopy = OSReadLittleInt16(&cd->totalLength, 0);
523: if(len < toCopy)
524: toCopy = len;
525: bcopy(cd, data, toCopy);
526: return kIOReturnSuccess;
527: }
528:
529:
530: /**
531: ** IOUserClient methods
532: **/
533:
534: IOReturn IOUSBDevice::newUserClient( task_t owningTask,
535: void * /* security_id */,
536: UInt32 type,
537: IOUserClient ** handler )
538:
539: {
540: IOReturn err = kIOReturnSuccess;
541: IOUSBDeviceUserClient * client;
542:
543: if( type != kIOUSBDeviceConnectType)
544: return( kIOReturnBadArgument);
545:
546: client = IOUSBDeviceUserClient::withTask(owningTask);
547:
548: if( !client || (false == client->attach( this )) ||
549: (false == client->start( this )) ) {
550: if(client) {
551: client->detach( this );
552: client->release();
553: }
554: err = kIOReturnNoMemory;
555: }
556:
557: *handler = client;
558: return( err );
559: }
560:
561:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.