|
|
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: * 05 Mar 99 ehewitt created.
27: *
28: * IOUSBInterface
29: * In USB there is the concept of a composite device, which means that
30: * each interface in a selected configuration can act as a separate device.
31: * Take for example a combo keyboard/trackball device. In this example,
32: * we might want a generic keyboard driver to handle the keyboard part and
33: * a generic pointer driver to handle the trackball part.
34: * So what we do is publish a IOUSBInterface for each interface of a
35: * composite device and intercept the few device requests that are not allowed
36: * by an interface, like set address and set configuration.
37: * If another driver handled both functions, or if there was a specific driver
38: * for that device, the matching logic would do the right thing.
39: *
40: */
41:
42: #include <libkern/OSByteOrder.h>
43: #include <IOKit/usb/IOUSBDevice.h>
44: #include <IOKit/usb/IOUSBController.h>
45: #include <IOKit/usb/IOUSBInterface.h>
46: #include <libkern/c++/OSDictionary.h>
47: #include <libkern/c++/OSData.h>
48: #include <IOKit/assert.h>
49:
50: #include <IOKit/usb/IOUSBPipe.h>
51: #include "IOUSBUserClient.h"
52: #define super IOUSBNub
53: #define self this
54:
55: int devintdebug = 0;
56: #define DEBUGLOG if (devintdebug) kprintf
57:
58: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
59:
60: OSDefineMetaClassAndStructors(IOUSBInterface, IOUSBNub)
61:
62: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
63:
64: bool IOUSBInterface::init(OSDictionary * propTable,
65: const IOUSBConfigurationDescriptor *cfdesc,
66: const IOUSBInterfaceDescriptor *ifdesc)
67: {
68: if(!ifdesc || !cfdesc)
69: return (false);
70:
71: if( !IOUSBNub::init(propTable))
72: return (false);
73: _configDesc = cfdesc;
74: _interfaceDesc = ifdesc;
75:
76: return (true);
77: }
78:
79: bool IOUSBInterface::attach(IOService *provider)
80: {
81: IOUSBDevice * device = OSDynamicCast(IOUSBDevice, provider);
82: if(!device)
83: return false;
84: if( !IOUSBNub::attach(provider))
85: return false;
86: _device = device;
87: _controller = device->bus();
88: _pipeZero = device->pipeZero();
89: _pipeZero->retain();
90:
91: if(_interfaceDesc->interfaceStrIndex) {
92: IOReturn err;
93: char name[128];
94:
95: err = GetStringDescriptor(_interfaceDesc->interfaceStrIndex, name, sizeof(name));
96: if(err == kIOReturnSuccess)
97: setName(name);
98: }
99:
100: return true;
101: }
102:
103: bool IOUSBInterface::finalize(IOOptionBits options)
104: {
105: cleanPipes();
106: return IOUSBNub::finalize(options);
107: }
108:
109: /*
110: * deviceRequest
111: * The idea here is to intercept only the calls that an interface,
112: * thinking it's a driver, might make. These include setting it's
113: * configuration, getting it's device descriptor, and setting it's address.
114: */
115: IOReturn IOUSBInterface::deviceRequest(IOUSBDevRequest *request,
116: IOUSBCompletion *completion = 0)
117: {
118: IOReturn err;
119: UInt16 theRequest;
120:
121:
122: if (!request)
123: return(kIOReturnBadArgument);
124:
125: theRequest = EncodeRequest(request->bRequest, request->rqDirection,
126: request->rqType, request->rqRecipient);
127:
128: if (theRequest == kSetConfiguration)
129: {
130: DEBUGLOG("\tignoring kSetConfiguration\n");
131: err = kIOReturnNotPermitted;
132: }
133: else
134: {
135: err = super::deviceRequest(request, completion);
136: }
137:
138: return(err);
139: }
140:
141: void IOUSBInterface::cleanPipes(void)
142: {
143: IOUSBPipe * pipe;
144:
145: for( unsigned int i=0; i < kUSBMaxPipes; i++) {
146: if( (pipe = _pipeList[i])) {
147: pipe->release();
148: _pipeList[i] = 0;
149: }
150: }
151: }
152:
153: // Open all the pipes.
154: bool IOUSBInterface::open(IOService * forClient,
155: IOOptionBits options = 0,
156: void * arg = 0 )
157: {
158: unsigned int i = 0;
159: const IOUSBDescriptorHeader *pos = NULL;
160: if(!IOUSBNub::open(forClient, options, arg))
161: return false;
162:
163: if(_currentAlt != _interfaceDesc->alternateSetting) {
164: IOUSBDevRequest request;
165: IOReturn res;
166:
167: request.rqDirection = kUSBOut;
168: request.rqType = kUSBStandard;
169: request.rqRecipient = kUSBInterface;
170: request.bRequest = kUSBRqSetInterface;
171: OSWriteLittleInt16(&request.wValue, 0, _interfaceDesc->alternateSetting);
172: OSWriteLittleInt16(&request.wIndex, 0, _interfaceDesc->interfaceNumber);
173: OSWriteLittleInt16(&request.wLength, 0, 0);
174: request.pData = 0;
175: res = deviceRequest(&request);
176: IOLog("SetInterface (%d, %d) returned 0x%x\n",
177: _interfaceDesc->interfaceNumber, _interfaceDesc->alternateSetting, res);
178: if(res != kIOReturnSuccess) {
179: close(forClient);
180: return false;
181: }
182: _currentAlt = _interfaceDesc->alternateSetting;
183: }
184: while ((pos = findNextAssociatedDescriptor(pos, kUSBEndpointDesc))) {
185: // Don't open twice!
186: if(_pipeList[i] == NULL) {
187: _pipeList[i] = IOUSBPipe::toEndpoint((const IOUSBEndpointDescriptor *)pos,
188: _speed, _address, _controller);
189: }
190: if(_pipeList[i] == NULL) {
191: close(forClient);
192: return false;
193: }
194: i++;
195: }
196: assert(i == _interfaceDesc->numEndpoints);
197:
198: return true;
199: }
200:
201: void IOUSBInterface::close(IOService * forClient,
202: IOOptionBits options = 0 )
203: {
204: cleanPipes();
205: IOUSBNub::close(forClient, options);
206: }
207:
208: const IOUSBInterfaceDescriptor *
209: IOUSBInterface::findNextAltInterface(const IOUSBInterfaceDescriptor *current,
210: FindInterfaceRequest *request)
211: {
212: const IOUSBInterfaceDescriptor * id;
213: const IOUSBDescriptorHeader * pos = NULL;
214: bool found;
215: if(current == NULL)
216: pos = (IOUSBDescriptorHeader *)_configDesc;
217: else
218: pos = (IOUSBDescriptorHeader *)current;
219: while (pos)
220: {
221: pos = findNextDescriptor(pos, kUSBInterfaceDesc);
222: id = (const IOUSBInterfaceDescriptor *)pos;
223: if(id == NULL || (id->interfaceNumber != _interfaceDesc->interfaceNumber)) {
224: continue;
225: }
226:
227: // check the request parameters
228: found = true;
229: if (request->theClass != 0 && request->theClass != id->interfaceClass)
230: found = false; // this is not it
231: if (request->subClass != 0 && request->subClass != id->interfaceSubClass)
232: found = false; // this is not it
233: if (request->protocol != 0 && request->protocol != id->interfaceProtocol)
234: found = false; // this is not it
235: if (found)
236: {
237: request->theClass = id->interfaceClass;
238: request->subClass = id->interfaceSubClass;
239: request->protocol = id->interfaceProtocol;
240: request->maxPower = _configDesc->maxPower;
241: request->busPowered = _configDesc->attributes & kUSBAtrBusPowered ? 2 : 1;
242: request->selfPowered = _configDesc->attributes & kUSBAtrSelfPowered ? 2 : 1;
243: request->remoteWakeup = _configDesc->attributes & kUSBAtrRemoteWakeup ? 2 : 1;
244: return(id);
245: }
246: }
247: return(0);
248: }
249:
250:
251: IOUSBPipe *IOUSBInterface::findNextPipe(IOUSBPipe *current,
252: IOUSBFindEndpointRequest *request)
253: {
254: const IOUSBController::Endpoint * endpoint;
255: IOUSBPipe * pipe;
256: int numEndpoints;
257: int i;
258:
259: numEndpoints = _interfaceDesc->numEndpoints;
260:
261: if (request == 0)
262: return NULL;
263: if(current != 0) {
264: for(i=0;i < numEndpoints; i++) {
265: if(_pipeList[i] == current) {
266: i++; // Skip the one we just did
267: break;
268: }
269: }
270: }
271: else
272: i = 0; // Start at beginning.
273:
274: for (;i < numEndpoints; i++) {
275: pipe = _pipeList[i];
276: if(!pipe)
277: continue;
278: endpoint = pipe->endpoint();
279:
280: // check the request parameters
281: if (request->type != kUSBAnyType &&
282: request->type != endpoint->transferType)
283: pipe = 0; // this is not it
284: else if (request->direction != kUSBAnyDirn &&
285: request->direction != endpoint->direction)
286: pipe = 0; // this is not it
287:
288: if (pipe == 0)
289: continue;
290:
291: request->type = endpoint->transferType;
292: request->direction = endpoint->direction;
293: request->maxPacketSize = endpoint->maxPacketSize;
294: request->interval = endpoint->interval;
295: return(pipe);
296: }
297:
298: return(0);
299: }
300:
301: const IOUSBDescriptorHeader *
302: IOUSBInterface::findNextAssociatedDescriptor(const void *current, UInt8 type)
303: {
304: const IOUSBDescriptorHeader *next;
305: if(current == NULL)
306: current = _interfaceDesc;
307: next = (const IOUSBDescriptorHeader *)current;
308:
309: while (true) {
310: next = findNextDescriptor(next, kUSBAnyDesc);
311:
312: if(!next || next->descriptorType == kUSBInterfaceDesc)
313: return NULL; // Reached end of our list.
314: if(next->descriptorType == type || type == kUSBAnyDesc)
315: break;
316: }
317: return next;
318: }
319:
320: IOReturn
321: IOUSBInterface::setAlternateInterface(UInt8 alternateSetting)
322: {
323: const IOUSBDescriptorHeader *next;
324: const IOUSBInterfaceDescriptor *ifdesc;
325:
326: next = (const IOUSBDescriptorHeader *)_configDesc;
327:
328: while( (next = findNextDescriptor(next, kUSBInterfaceDesc))) {
329: ifdesc = (const IOUSBInterfaceDescriptor *)next;
330: if(ifdesc->interfaceNumber == _interfaceDesc->interfaceNumber &&
331: ifdesc->alternateSetting == alternateSetting)
332: break;
333: }
334:
335: if(ifdesc) {
336: _interfaceDesc = ifdesc;
337: OSData * data;
338: data = OSData::withBytes(ifdesc, sizeof(*ifdesc));
339: if (data) {
340: setProperty("interface descriptor", data);
341: data->release();
342: }
343:
344: return kIOReturnSuccess;
345: }
346: else
347: return kIOUSBConfigNotFound;
348: }
349:
350: UInt8 IOUSBInterface::getConfigValue()
351: {
352: return _configDesc->configValue;
353: }
354:
355: const IOUSBInterfaceDescriptor * IOUSBInterface::interfaceDescriptor()
356: {
357: return _interfaceDesc;
358: }
359:
360: IOUSBDevice * IOUSBInterface::device()
361: {
362: return _device;
363: }
364:
365: IOReturn IOUSBInterface::newUserClient( task_t owningTask,
366: void * /* security_id */,
367: UInt32 type,
368: IOUserClient ** handler )
369:
370: {
371: IOReturn err = kIOReturnSuccess;
372: IOUSBInterfaceUserClient * client;
373:
374: if( type != kIOUSBDeviceConnectType)
375: return( kIOReturnBadArgument);
376:
377: client = IOUSBInterfaceUserClient::withTask(owningTask);
378:
379: if( !client || (false == client->attach( this )) ||
380: (false == client->start( this )) ) {
381: if(client) {
382: client->detach( this );
383: client->release();
384: }
385: err = kIOReturnNoMemory;
386: }
387:
388: *handler = client;
389: return( err );
390: }
391:
392:
393:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.