|
|
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: #define DEBUGGING_LEVEL 0 // 1 = low; 2 = high; 3 = extreme
33: #define DEBUGLOG kprintf
34:
35: #include <libkern/c++/OSDictionary.h>
36: #include <libkern/c++/OSData.h>
37: #include <IOKit/usb/IOUSBController.h>
38: #include <IOKit/usb/IOUSBDevice.h>
39: #include "IOUSBRootHubDevice.h"
40: #include <IOKit/assert.h>
41: #include <IOKit/IOSyncer.h>
42:
43: enum {
44: kSetupSent = 0x01,
45: kDataSent = 0x02,
46: kStatusSent = 0x04,
47: kSetupBack = 0x10,
48: kDataBack = 0x20,
49: kStatusBack = 0x40
50: };
51:
52: #define kUSBSetup kUSBNone
53:
54: void IOUSBSyncCompletion(void * target,
55: void * parameter,
56: IOReturn status,
57: UInt32 bufferSizeRemaining)
58: {
59: IOSyncer *syncer = (IOSyncer *)target;
60:
61: if(parameter != NULL) {
62: *(UInt32 *)parameter -= bufferSizeRemaining;
63: }
64:
65: syncer->signal(status);
66: }
67:
68: void IOUSBSyncIsoCompletion(void *target, void * parameter,
69: IOReturn status,
70: IOUSBIsocFrame *pFrames)
71: {
72: IOSyncer *syncer = (IOSyncer *)target;
73: syncer->signal(status);
74: }
75:
76:
77: #define super IOUSBBus
78:
79: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
80:
81: OSDefineMetaClass( IOUSBController, IOUSBBus )
82: OSDefineAbstractStructors(IOUSBController, IOUSBBus)
83:
84: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
85:
86: bool IOUSBController::init(OSDictionary * propTable)
87: {
88: if (!super::init(propTable)) return false;
89:
90: return (true);
91: }
92:
93: bool IOUSBController::start( IOService * provider )
94: {
95: IOUSBDeviceDescriptor desc;
96:
97:
98: if( !super::start(provider))
99: return (false);
100:
101: do {
102:
103: /*
104: * Initialize the Workloop and Command gate
105: */
106: _workLoop = IOWorkLoop::workLoop();
107: if (!_workLoop)
108: {
109: IOLog("%s: unable to create workloop\n", getName());
110: break;
111: }
112:
113: _commandGate = IOCommandGate:: commandGate(this, NULL);
114: if (!_commandGate)
115: {
116: IOLog("%s: unable to create command gate\n", getName());
117: break;
118: }
119:
120: if (_workLoop->addEventSource(_commandGate) != kIOReturnSuccess)
121: {
122: IOLog("%s: unable to add command gate\n", getName());
123: break;
124: }
125:
126: /*
127: * Initialize the UIM
128: */
129: if (UIMInitialize(provider) != kIOReturnSuccess)
130: {
131: IOLog("%s: unable to initialize UIM\n", getName());
132: break;
133: }
134:
135: /*
136: * Initialize device zero
137: */
138: _devZeroLock = IOLockAlloc();
139:
140: /*
141: * Create the root hub device
142: */
143: if (getRootHubDeviceDescriptor( &desc ) != kIOReturnSuccess)
144: {
145: IOLog("%s: unable to get root hub descriptor\n", getName());
146: break;
147: }
148:
149: _rootHubDevice = new IOUSBRootHubDevice;
150:
151: CreateDevice(_rootHubDevice, getNewAddress(), &desc,
152: kUSBHighSpeed, kUSB500mAAvailable);
153: if (_rootHubDevice == 0)
154: {
155: IOLog("%s: unable to initialize root hub\n", getName());
156: break;
157: }
158: _rootHubDevice->registerService();
159:
160: return(true);
161:
162: } while (false);
163:
164: if (_workLoop) _workLoop->release();
165: if (_commandGate) _commandGate->release();
166:
167: return( false );
168: }
169:
170: IOWorkLoop *IOUSBController::getWorkLoop() const
171: {
172: return _workLoop;
173: }
174:
175: IOUSBDevice *IOUSBController::newDevice()
176: {
177: return(new IOUSBDevice);
178: }
179:
180: /*
181: * CreateDevice:
182: * This method just creates the device so we can minimally talk to it, e.g.
183: * get it's descriptor. After this method, the device is not ready for
184: * prime time.
185: */
186: IOReturn IOUSBController::CreateDevice(IOUSBDevice *newDevice,
187: USBDeviceAddress deviceAddress,
188: IOUSBDeviceDescriptor *desc,
189: UInt8 speed,
190: UInt32 powerAvailable)
191: {
192: OSDictionary *propTable = 0;
193: OSData *data;
194: OSNumber *offset;
195: char location[8];
196:
197: #if (DEBUGGING_LEVEL > 0)
198: DEBUGLOG("%s: CreateDevice: addr=%d, speed=%s, power=%d\n", getName(),
199: deviceAddress, speed ? "low" : "high", powerAvailable*2);
200: #endif
201:
202: do {
203: propTable = OSDictionary::withCapacity(4);
204: if (!propTable)
205: break;
206:
207: if (desc) {
208: data = OSData::withBytes( (void *)desc, sizeof( *desc ));
209: if(data) {
210: propTable->setObject("device descriptor", data);
211: data->release();
212: }
213: offset = OSNumber::withNumber(desc->deviceClass, 8);
214: if(offset) {
215: propTable->setObject("class", offset);
216: offset->release();
217: }
218: offset = OSNumber::withNumber(desc->deviceSubClass, 8);
219: if(offset) {
220: propTable->setObject("subClass", offset);
221: offset->release();
222: }
223: offset = OSNumber::withNumber(desc->protocol, 8);
224: if(offset) {
225: propTable->setObject("protocol", offset);
226: offset->release();
227: }
228: offset = OSNumber::withNumber(OSReadLittleInt16(&desc->vendor, 0), 16);
229: if(offset) {
230: propTable->setObject("vendor", offset);
231: offset->release();
232: }
233: offset = OSNumber::withNumber(OSReadLittleInt16(&desc->product, 0), 16);
234: if(offset) {
235: propTable->setObject("product", offset);
236: offset->release();
237: }
238: offset = OSNumber::withNumber(OSReadLittleInt16(&desc->devRel, 0), 16);
239: if(offset) {
240: propTable->setObject("version", offset);
241: offset->release();
242: }
243: }
244:
245: data = OSData::withBytes( (void *)&deviceAddress,
246: sizeof( deviceAddress ));
247: if (data) {
248: propTable->setObject("device address", data);
249: data->release();
250: }
251:
252: data = OSData::withBytes( (void *)&powerAvailable,
253: sizeof( powerAvailable ));
254: if (data) {
255: propTable->setObject("bus power available", data);
256: data->release();
257: }
258:
259: data = OSData::withBytes( (void *)&speed, sizeof( speed ));
260: if (data) {
261: propTable->setObject("low speed device", data);
262: data->release();
263: }
264:
265: if (!newDevice->init(propTable))
266: break;
267:
268: propTable->release(); // done with it after init
269: propTable = 0;
270:
271: sprintf( location, "%x", deviceAddress );
272: newDevice->setLocation(location);
273:
274: if (!newDevice->attach(this))
275: break;
276:
277: return(kIOReturnSuccess);
278:
279: } while (false);
280:
281: if (propTable)
282: propTable->release();
283:
284: return(kIOReturnNoMemory);
285: }
286:
287: /*
288: * deviceRequest:
289: * Queue up a low level device request. It's very simple because the
290: * device has done all the error checking. Commands get allocated here and get
291: * deallocated in the handlers.
292: *
293: */
294: IOReturn IOUSBController::deviceRequest(IOUSBDevRequest * request,
295: IOUSBCompletion * completion,
296: USBDeviceAddress address, UInt8 ep)
297: {
298: // FIXME -- should preallocate a bunch of 'command's
299: IOUSBCommand *command = (IOUSBCommand *)IOMalloc(sizeof(IOUSBCommand));
300: IOReturn err = kIOReturnSuccess;
301:
302: do
303: {
304: command->selector = DEVICE_REQUEST;
305: command->request = request;
306: command->address = address;
307: command->endpoint = ep;
308: command->type = kUSBControl;
309: command->buffer = 0; // no buffer for device requests
310: command->completion = *completion;
311:
312: if (_commandGate == 0)
313: {
314: err = kIOReturnInternalError;
315: break;
316: }
317:
318: err = _commandGate->runAction(doControlTransfer, command);
319: if ( err)
320: break;
321:
322: return (err);
323: } while (0);
324:
325: /* Free/give back the command */
326: IOFree(command, sizeof(IOUSBCommand));
327:
328: return(err);
329: }
330:
331: IOReturn IOUSBController::deviceRequest(IOUSBDevRequestDesc * request,
332: IOUSBCompletion * completion,
333: USBDeviceAddress address, UInt8 ep)
334: {
335: // FIXME -- should preallocate a bunch of 'command's
336: IOUSBCommand *command = (IOUSBCommand *)IOMalloc(sizeof(IOUSBCommand));
337: IOReturn err = kIOReturnSuccess;
338:
339: do
340: {
341: command->selector = DEVICE_REQUEST_DESC;
342: // IOUSBDevRequest and IOUSBDevRequestDesc are same except for
343: // pData (void * or descriptor).
344: command->request = (IOUSBDevRequest *)request;
345: command->address = address;
346: command->endpoint = ep;
347: command->type = kUSBControl;
348: command->buffer = request->pData;
349: command->completion = *completion;
350:
351: if (_commandGate == 0)
352: {
353: err = kIOReturnInternalError;
354: break;
355: }
356:
357: err = _commandGate->runAction(doControlTransfer, command);
358: if ( err)
359: break;
360:
361: return (err);
362: } while (0);
363:
364: /* Free/give back the command */
365: IOFree(command, sizeof(IOUSBCommand));
366:
367: return(err);
368: }
369:
370: USBDeviceAddress IOUSBController::getNewAddress(void)
371: {
372: int i;
373: bool assigned[kUSBMaxDevices];
374: OSIterator * clients;
375:
376: bzero(assigned, sizeof(assigned));
377:
378: clients = getClientIterator();
379: if(clients) {
380: OSObject *next;
381: while((next = clients->getNextObject())) {
382: IOUSBDevice *testIt = OSDynamicCast(IOUSBDevice, next);
383: if(testIt) {
384: assigned[testIt->address()] = true;
385: }
386: }
387: clients->release();
388: }
389:
390: for(i=1; i<kUSBMaxDevices; i++) {
391: if(!assigned[i])
392: return i;
393: }
394:
395: return(0); // No free device addresses!
396: }
397:
398: /*
399: * ControlPacket:
400: * Send a USB control packet which consists of at least two stages: setup
401: * and status. Optionally there can be multiple data stages.
402: *
403: */
404: IOReturn IOUSBController::ControlTransaction(IOUSBCommand *command)
405: {
406: IOUSBDevRequest *request = command->request;
407: UInt8 direction = request->rqDirection;
408: UInt8 endpoint = command->endpoint;
409: UInt16 wLength = OSReadLittleInt16(&request->wLength, 0);
410: IOReturn err = kIOReturnSuccess;
411: IOUSBCompletion completion;
412:
413: do
414: {
415: // Setup Stage
416: #if (DEBUGGING_LEVEL > 1)
417: DEBUGLOG("\tQueueing Setup TD (dir=%d) packet=0x%lx 0x%lx\n",
418: direction, *(UInt32*)request, *((UInt32*)request+1));
419: #endif
420:
421: completion.target = (void *)this;
422: completion.action = &IOUSBController::ControlPacketHandler;
423: completion.parameter = (void *)command;
424:
425: command->dataRemaining = wLength;
426: command->stage = kSetupSent;
427: err = UIMCreateControlTransfer(
428: command->address /*functionAddress*/,
429: endpoint /*endpointNumber*/,
430: completion /*completion*/,
431: request /*packet*/,
432: true /*bufferRounding*/,
433: 8 /*packet size*/,
434: kUSBSetup /*direction*/);
435: if (err)
436: {
437: IOLog("ControlTransaction: control packet 1 error %d\n", err);
438: break;
439: }
440:
441: // Data Stage
442: if (wLength != 0 && request->pData != 0)
443: {
444: #if (DEBUGGING_LEVEL > 1)
445: DEBUGLOG("\tQueueing Data TD (dir=%d, wLength=0x%x, pData=%lx)\n", direction,
446: wLength, request->pData);
447: #endif
448: command->stage |= kDataSent;
449: if(command->selector == DEVICE_REQUEST_DESC)
450: err = UIMCreateControlTransfer(
451: command->address /*functionAddress*/,
452: endpoint /*endpointNumber*/,
453: completion /*completion*/,
454: command->buffer /*buffer*/,
455: true /*bufferRounding*/,
456: wLength /*bufferSize*/,
457: direction /*direction*/);
458: else
459: err = UIMCreateControlTransfer(
460: command->address /*functionAddress*/,
461: endpoint /*endpointNumber*/,
462: completion /*completion*/,
463: request->pData /*buffer*/,
464: true /*bufferRounding*/,
465: wLength /*bufferSize*/,
466: direction /*direction*/);
467: if (err)
468: {
469: IOLog("ControlTransaction: control packet 2 error %d\n", err);
470: break;
471: }
472:
473: direction = kUSBOut + kUSBIn - direction; // swap direction
474: }
475: else
476: direction = kUSBIn;
477:
478: // Status Stage
479: #if (DEBUGGING_LEVEL > 1)
480: DEBUGLOG("\tQueueing Status TD (dir=%d)\n", direction);
481: #endif
482: command->stage |= kStatusSent;
483: err = UIMCreateControlTransfer(
484: command->address /*functionAddress*/,
485: endpoint /*endpointNumber*/,
486: completion /*completion*/,
487: (void *)0 /*buffer*/,
488: true /*bufferRounding*/,
489: 0 /*bufferSize*/,
490: direction /*direction*/);
491: if (err)
492: {
493: IOLog("ControlTransaction: control packet 3 error %d\n", err);
494: break;
495: }
496: } while(false);
497:
498: if (err)
499: complete(command->completion, err, 0);
500: return(err);
501: }
502:
503: /*
504: * ControlPacketHandler:
505: * Handle all three types of control packets and maintain what stage
506: * we're at. When we receive the last one, then call the clients
507: * completion routine.
508: */
509: void IOUSBController::ControlPacketHandler(void * parameter,
510: IOReturn status,
511: UInt32 bufferSizeRemaining)
512: {
513: IOUSBCommand *command = (IOUSBCommand *)parameter;
514: IOUSBDevRequest *request;
515: UInt8 sent, back, todo;
516:
517: #if (DEBUGGING_LEVEL > 1)
518: DEBUGLOG("ControlPacketHandler lParam=%lx status=0x%x bufferSizeRemaining=0x%x\n", parameter, status, bufferSizeRemaining);
519: #endif
520:
521: if (command == 0)
522: return;
523:
524: request = command->request;
525:
526: sent = (command->stage & 0x0f) << 4;
527: back = command->stage & 0xf0;
528: todo = sent ^ back; /* thats xor */
529:
530: if((todo & kSetupBack) != 0)
531: command->stage |= kSetupBack;
532: else if((todo & kDataBack) != 0)
533: {
534: /* This is the data transport phase, so this is the interesting one */
535: command->stage |= kDataBack;
536: command->dataRemaining = bufferSizeRemaining;
537: }
538: else if((todo & kStatusBack) != 0)
539: command->stage |= kStatusBack;
540: else
541: IOLog("ControlPacketHandler: Spare transactions, This seems to be harmless");
542:
543: back = command->stage & 0xf0;
544: todo = sent ^ back; /* thats xor */
545:
546: if (status != kIOReturnSuccess)
547: {
548: USBDeviceAddress addr = command->address;
549: UInt8 endpt = command->endpoint;
550:
551: command->status = status;
552:
553: #if (DEBUGGING_LEVEL > 0)
554: DEBUGLOG("ControlPacketHandler: error %d occured. todo = %d\n", status, todo);
555:
556: #endif
557: UIMClearEndpointStall(addr, endpt, kUSBAnyDirn);
558: }
559: if (todo == 0)
560: {
561: #if (DEBUGGING_LEVEL > 0)
562: DEBUGLOG("ControlPacketHandler: transaction complete status=%d\n", status);
563: #endif
564:
565: /* Call the clients handler */
566: complete(command->completion, status, command->dataRemaining);
567:
568: /* Free/give back the command */
569: IOFree(command, sizeof(IOUSBCommand));
570: }
571: }
572:
573: /*
574: * InterruptTransaction:
575: * Send a USB interrupt packet.
576: *
577: */
578: IOReturn IOUSBController::InterruptTransaction(IOUSBCommand *command)
579: {
580: IOReturn err = kIOReturnSuccess;
581: IOUSBCompletion completion;
582:
583: completion.target = (void *)this;
584: completion.action = &IOUSBController::InterruptPacketHandler;
585: completion.parameter = (void *)command;
586:
587: err = UIMCreateInterruptTransfer(
588: command->address /*functionAddress*/,
589: command->endpoint /*endpointNumber*/,
590: completion /*completion*/,
591: command->buffer /*buffer*/,
592: true /*bufferRounding*/,
593: command->buffer->getLength() /*bufferSize*/,
594: command->direction);
595:
596: return(err);
597: }
598:
599: void IOUSBController::InterruptPacketHandler(void * parameter, IOReturn status, UInt32 bufferSizeRemaining)
600: {
601: IOUSBCommand *command = (IOUSBCommand *)parameter;
602:
603: if (command == 0)
604: return;
605:
606: #if (DEBUGGING_LEVEL > 1)
607: DEBUGLOG("InterruptPacketHandler: transaction complete status=%d bufferSizeRemaining = %d\n", status, bufferSizeRemaining);
608: #endif
609: if (status != kIOReturnSuccess)
610: UIMClearEndpointStall(command->address,
611: command->endpoint,
612: command->direction);
613:
614: /* Call the clients handler */
615: complete(command->completion, status, bufferSizeRemaining);
616:
617: /* Free/give back the command */
618: IOFree(command, sizeof(IOUSBCommand));
619: }
620:
621:
622: /*
623: * BulkTransaction:
624: * Send a USB bulk packet.
625: *
626: */
627: IOReturn IOUSBController::BulkTransaction(IOUSBCommand *command)
628: {
629: IOUSBCompletion completion;
630: IOReturn err = kIOReturnSuccess;
631:
632:
633: completion.target = (void *)this;
634: completion.action = &IOUSBController::BulkPacketHandler;
635: completion.parameter = (void *)command;
636:
637: err = UIMCreateBulkTransfer(
638: command->address /*functionAddress*/,
639: command->endpoint /*endpointNumber*/,
640: completion /*completion*/,
641: command->buffer /*buffer*/,
642: true /*bufferRounding*/,
643: command->buffer->getLength() /*bufferSize*/,
644: command->direction /*direction*/);
645:
646: if (err)
647: IOLog("BulkTransaction: error queueing bulk packet (%d)\n", err);
648:
649: return(err);
650: }
651:
652: void IOUSBController::BulkPacketHandler(void * parameter,
653: IOReturn status,
654: UInt32 bufferSizeRemaining)
655: {
656: IOUSBCommand *command = (IOUSBCommand *)parameter;
657:
658:
659: if (command == 0)
660: return;
661:
662: #if (DEBUGGING_LEVEL > 0)
663: DEBUGLOG("BulkPacketHandler: transaction complete status=%d bufferSizeRemaining = %d\n", status, bufferSizeRemaining);
664: #endif
665: if (status != kIOReturnSuccess)
666: UIMClearEndpointStall(command->address,
667: command->endpoint,
668: command->direction);
669:
670: /* Call the clients handler */
671: complete(command->completion, status, bufferSizeRemaining);
672:
673: /* Free/give back the command */
674: IOFree(command, sizeof(IOUSBCommand));
675: }
676:
677: /*
678: * BulkTransaction:
679: * Send a USB bulk packet.
680: *
681: */
682: IOReturn IOUSBController::doIsocTransfer(OSObject *owner, void *cmd,
683: void */*field2*/, void */*field3*/, void */*field4*/)
684: {
685: IOUSBController *controller = (IOUSBController *)owner;
686: IOUSBIsocCommand *command = (IOUSBIsocCommand *) cmd;
687: return(controller->IsocTransaction(command));
688: }
689:
690: IOReturn IOUSBController::IsocTransaction(IOUSBIsocCommand *command)
691: {
692: IOUSBIsocCompletion completion;
693: IOReturn err = kIOReturnSuccess;
694:
695:
696: completion.target = (void *)this;
697: completion.action = &IOUSBController::IsocCompletionHandler;
698: completion.parameter = (void *)command;
699:
700: err = UIMCreateIsochTransfer(
701: command->address /*functionAddress*/,
702: command->endpoint /*endpointNumber*/,
703: completion /*completion*/,
704: command->direction /*direction*/,
705: command->startFrame /*Start frame */,
706: command->buffer /*buffer*/,
707: command->numFrames /*number of frames*/,
708: command->frameList /*transfer for each frame*/);
709:
710: if (err) {
711: IOLog("IsocTransaction: error queueing isoc transfer (0x%x)\n", err);
712: if (command->completion.action)
713: (command->completion.action)(command->completion.target,
714: command->completion.parameter,
715: err,
716: command->frameList);
717: }
718: return(err);
719: }
720:
721: void IOUSBController::IsocCompletionHandler(void * parameter,
722: IOReturn status,
723: IOUSBIsocFrame *pFrames)
724: {
725: IOUSBIsocCommand *command = (IOUSBIsocCommand *)parameter;
726:
727: if (command == 0)
728: return;
729:
730: if (status != kIOReturnSuccess)
731: UIMClearEndpointStall(command->address,
732: command->endpoint,
733: command->direction);
734:
735: /* Call the clients handler */
736: IOUSBIsocCompletion *completion = &command->completion;
737: if (completion->action) (*completion->action)(completion->target,
738: completion->parameter,
739: status,
740: pFrames);
741:
742: /* Free/give back the command */
743: IOFree(command, sizeof(IOUSBIsocCommand));
744: }
745:
746:
747: IOReturn IOUSBController::doIOTransfer(OSObject *owner,
748: void *cmd,
749: void */*field2*/, void */*field3*/, void */*field4*/)
750: {
751: IOUSBController *controller = (IOUSBController *)owner;
752: IOUSBCommand *command = (IOUSBCommand *) cmd;
753: IOReturn err = kIOReturnSuccess;
754:
755: switch (command->type)
756: {
757: case kUSBInterrupt:
758: err = controller->InterruptTransaction(command);
759: break;
760: case kUSBIsoc:
761: IOLog("Isoc transactions not supported on non-isoc pipes!!\n");
762: err = kIOReturnBadArgument;
763: break;
764: case kUSBBulk:
765: err = controller->BulkTransaction(command);
766: break;
767: default:
768: IOLog("Unknown transaction type\n");
769: err = kIOReturnBadArgument;
770: break;
771: }
772:
773: if (err)
774: controller->complete(command->completion, err, 0);
775:
776: return err;
777: }
778:
779: IOReturn IOUSBController::doControlTransfer(OSObject *owner,
780: void *arg0, void *arg1,
781: void *arg2, void *arg3)
782: {
783: IOUSBController *me = (IOUSBController *)owner;
784:
785: return me->ControlTransaction((IOUSBCommand *)arg0);
786: }
787:
788: IOReturn IOUSBController::doDeleteEP(OSObject *owner,
789: void *arg0, void *arg1,
790: void *arg2, void *arg3)
791: {
792: IOUSBController *me = (IOUSBController *)owner;
793:
794: return me->UIMDeleteEndpoint((short)arg0, (short)arg1, (short)arg2);
795: }
796:
797: IOReturn IOUSBController::doCreateEP(OSObject *owner,
798: void *arg0, void *arg1,
799: void *arg2, void *arg3)
800: {
801: IOUSBController *me = (IOUSBController *)owner;
802: UInt8 address = (UInt8)arg0;
803: UInt8 speed = (UInt8)arg1;
804: Endpoint *endpoint = (Endpoint *)arg2;
805: IOReturn err;
806: switch (endpoint->transferType)
807: {
808: case kUSBInterrupt:
809: err = me->UIMCreateInterruptEndpoint(address,
810: endpoint->number,
811: endpoint->direction,
812: speed,
813: endpoint->maxPacketSize,
814: endpoint->interval);
815: break;
816:
817: case kUSBBulk:
818: err = me->UIMCreateBulkEndpoint(address,
819: endpoint->number,
820: endpoint->direction,
821: speed,
822: endpoint->maxPacketSize);
823: break;
824:
825: case kUSBControl:
826: err = me->UIMCreateControlEndpoint(address,
827: endpoint->number,
828: endpoint->maxPacketSize,
829: speed);
830: break;
831:
832: case kUSBIsoc:
833: err = me->UIMCreateIsochEndpoint(address,
834: endpoint->number,
835: endpoint->maxPacketSize,
836: endpoint->direction);
837: break;
838:
839: default:
840: err = kIOReturnBadArgument;
841: break;
842: }
843: return (err);
844: }
845:
846: IOReturn IOUSBController::AcquireDeviceZero()
847: {
848: IOReturn err = 0;
849: Endpoint ep;
850:
851: ep.number = 0;
852: ep.transferType = kUSBControl;
853: ep.maxPacketSize = 8;
854:
855: #if (DEBUGGING_LEVEL > 0)
856: DEBUGLOG("%s: TRYING TO ACQUIRE DEVICE ZERO\n", getName());
857: #endif
858:
859: IOTakeLock(_devZeroLock);
860:
861: #if (DEBUGGING_LEVEL > 0)
862: DEBUGLOG("%s: ACQUIRED DEVICE ZERO\n", getName());
863: #endif
864:
865: err = openPipe(0, kUSBHighSpeed, &ep);
866: return(err);
867: }
868:
869: void IOUSBController::ReleaseDeviceZero(void)
870: {
871: IOReturn err = 0;
872:
873: err = _commandGate->runAction(doDeleteEP, (void *)0, (void *)0, (void *)kUSBAnyDirn);
874: IOUnlock(_devZeroLock);
875:
876: #if (DEBUGGING_LEVEL > 0)
877: DEBUGLOG("%s: RELEASED DEVICE ZERO\n", getName());
878: #endif
879:
880: return;
881: }
882:
883: void IOUSBController::WaitForReleaseDeviceZero()
884: {
885: IOTakeLock(_devZeroLock);
886: IOUnlock(_devZeroLock);
887: }
888:
889: IOReturn IOUSBController::ConfigureDeviceZero(UInt8 maxPacketSize, UInt8 speed)
890: {
891: IOReturn err = kIOReturnSuccess;
892: Endpoint ep;
893:
894: ep.number = 0;
895: ep.transferType = kUSBControl;
896: ep.maxPacketSize = maxPacketSize;
897:
898: #if (DEBUGGING_LEVEL > 0)
899: DEBUGLOG("********** ConfigureDeviceZero %d %d **********\n", maxPacketSize, speed);
900: #endif
901: err = _commandGate->runAction(doDeleteEP, (void *)0, (void *)0, (void *)kUSBAnyDirn);
902: err = openPipe(0, speed, &ep);
903:
904: return(err);
905: }
906:
907:
908: IOReturn IOUSBController::GetDeviceZeroDescriptor(IOUSBDeviceDescriptor *desc)
909: {
910: IOReturn err = kIOReturnSuccess;
911: IOUSBDevRequest request;
912:
913: #if (DEBUGGING_LEVEL > 0)
914: DEBUGLOG("********** GET DEVICE ZERO DEVICE DESCRIPTOR **********\n");
915: #endif
916:
917: do
918: {
919: IOUSBCompletion tap;
920: IOSyncer * syncer;
921:
922: syncer = IOSyncer::create();
923:
924: tap.target = syncer;
925: tap.action = &IOUSBSyncCompletion;
926: tap.parameter = NULL;
927:
928: if (!desc)
929: {
930: err = kIOReturnBadArgument;
931: break;
932: }
933:
934: request.rqDirection = kUSBIn;
935: request.rqType = kUSBStandard;
936: request.rqRecipient = kUSBDevice;
937: request.bRequest = kUSBRqGetDescriptor;
938: OSWriteLittleInt16(&request.wValue, 0, (kUSBDeviceDesc << 8));
939: OSWriteLittleInt16(&request.wIndex, 0, 0);
940: OSWriteLittleInt16(&request.wLength, 0, sizeof(IOUSBDeviceDescriptor));
941: request.pData = desc;
942:
943: err = deviceRequest(&request, &tap, 0, 0);
944:
945: if (err)
946: {
947: #if (DEBUGGING_LEVEL > 0)
948: DEBUGLOG("%s: error getting device descriptor. err=%d\n", getName(), err);
949: #endif
950: syncer->release();
951: syncer->release();
952: break;
953: }
954: err = syncer->wait();
955:
956: } while(false);
957:
958: return(err);
959: }
960:
961: IOReturn IOUSBController::SetDeviceZeroAddress(USBDeviceAddress address,
962: UInt8 maxPacketSize, UInt8 speed)
963: {
964: IOReturn err = kIOReturnSuccess;
965: IOUSBDevRequest request;
966:
967: #if (DEBUGGING_LEVEL > 0)
968: DEBUGLOG("********** SET DEVICE ZERO ADDRESS: %d %d %d **********\n",
969: address, maxPacketSize, speed);
970: #endif
971:
972: do
973: {
974: IOUSBCompletion tap;
975: IOSyncer * syncer;
976:
977: syncer = IOSyncer::create();
978:
979: tap.target = syncer;
980: tap.action = &IOUSBSyncCompletion;
981: tap.parameter = NULL;
982:
983: request.rqDirection = kUSBOut;
984: request.rqType = kUSBStandard;
985: request.rqRecipient = kUSBDevice;
986: request.bRequest = kUSBRqSetAddress;
987: OSWriteLittleInt16(&request.wValue, 0, address);
988: OSWriteLittleInt16(&request.wIndex, 0, 0);
989: OSWriteLittleInt16(&request.wLength, 0, 0);
990: request.pData = 0;
991:
992: err = deviceRequest(&request, &tap, 0, 0);
993:
994: if (err)
995: {
996: syncer->release(); syncer->release();
997: break;
998: }
999: err = syncer->wait();
1000:
1001: } while(false);
1002:
1003: #if (DEBUGGING_LEVEL > 0)
1004: DEBUGLOG("%s: error setting device address. err=%d\n", getName(), err);
1005: #endif
1006: return(err);
1007: }
1008:
1009: IOUSBDevice *IOUSBController::MakeDevice(IOUSBDeviceDescriptor *desc,
1010: UInt8 speed, UInt32 power)
1011: {
1012: IOReturn err = kIOReturnSuccess;
1013: IOUSBDevice *newDev;
1014: USBDeviceAddress address;
1015:
1016: #if (DEBUGGING_LEVEL > 0)
1017: DEBUGLOG("*************** MakeDevice ***************\n");
1018: #endif
1019:
1020: newDev = newDevice();
1021: if (newDev == 0)
1022: return(0);
1023:
1024: address = getNewAddress();
1025: if(address == 0) {
1026: newDev->release();
1027: return 0;
1028: }
1029:
1030: err = SetDeviceZeroAddress(address, desc->maxPacketSize, speed);
1031:
1032: if (err)
1033: {
1034: #if (DEBUGGING_LEVEL > 0)
1035: DEBUGLOG("%s: error setting address. err=%d device=%lx\n",
1036: getName(), err, (UInt32)this);
1037: #endif
1038: //return(0); Some devices produce a spurious error here, eg. Altec Lansing speakers
1039: }
1040:
1041: err = CreateDevice(newDev, address, desc, speed, power);
1042: if(err) {
1043: newDev->release();
1044: return(0);
1045: }
1046: return(newDev);
1047: }
1048:
1049: IOReturn IOUSBController::PolledRead(
1050: short functionNumber,
1051: short endpointNumber,
1052: IOUSBCompletion completion,
1053: IOMemoryDescriptor * CBP,
1054: bool bufferRounding,
1055: UInt32 bufferSize)
1056: {
1057: return UIMCreateInterruptTransfer(functionNumber, endpointNumber,
1058: completion, CBP, bufferRounding, bufferSize, kUSBIn);
1059: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.