|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: File: UIMRootHubSimulation.c
27:
28: Contains: Packet level simulation of root hub functions
29:
30: Version: Neptune 1.0
31:
32: Copyright: � 1998 by Apple Computer, Inc., all rights reserved.
33:
34: File Ownership:
35:
36: DRI: Barry Twycross
37:
38: Other Contact: xxx put other contact here xxx
39:
40: Technology: USB
41:
42: Writers:
43:
44: (DF) David Ferguson
45: (DKF) David Ferguson
46: (CJK) Craig Keithley
47: (BT) Barry Twycross
48:
49: Change History (most recent first):
50:
51: <USB4> 8/25/98 BT Isoc name changes
52: <USB3> 8/12/98 BT Allow more than 1 control at a time.
53: <USB2> 6/30/98 BT Tidy up
54: <USB1> 6/30/98 BT first checked in
55: */
56:
57:
58: /*
59:
60: // UIMrootHubSimulation is USL's rootHubSimulation moved across
61:
62: <USB27> 6/14/98 DF change implemented spelling.
63: <USB26> 5/20/98 BT Fix alt settings field of interface descriptor
64: <USB25> 5/17/98 BT Make get conf descriptor more forgiving. Fix hub endpoint desc
65: <USB24> 5/14/98 DF Add status messages for unimplemented root hub stuff, also use
66: info from the UIM when getting the hub status.
67: <USB23> 4/23/98 BT Fix reset portsuspend change feature
68: <USB22> 4/20/98 BT Add device status
69: <USB21> 4/16/98 BT Eliminate debugger
70: <USB20> 4/15/98 BT More root hub capabilities
71: <USB19> 4/9/98 BT Use USB.h
72: <18> 4/2/98 BT Do OPTI chip gang switching, fix sim stall error number
73: <17> 3/19/98 BT Split UIM into UIM and root hub parts
74: <16> 3/18/98 BT Add port enable and clear port enable change features
75: <15> 3/11/98 BT interrupt transaction simulation
76: <14> 3/9/98 BT Eliminate one set of redundant descriptors
77: <13> 2/27/98 BT Add string descriptors
78: <12> 2/25/98 BT Add Apple product codes.
79: <11> 2/24/98 BT Change Apple vendor ID.
80: <10> 2/23/98 BT Simulate root hub to not corrupt reqCount
81: <USB9> 2/9/98 DKF Byte swap configuration descriptor totalLength field
82: <8> 2/8/98 BT More Power allocation stuff
83: <7> 2/4/98 BT Cope with multiple configs
84: <6> 1/30/98 BT Put Apple vendor ID in root hub device descriptor
85: <5> 1/26/98 CJK Change to use USBDeviceDescriptor (instead of just
86: devicedescriptor)
87: <4> 1/26/98 BT Mangle names after design review
88: <3> 1/20/98 BT Endian swap port status, and other fixes
89: <2> 1/20/98 BT More root hub simulation
90: <1> 1/19/98 BT first checked in
91: */
92:
93: #include "driverservices.h" //naga
94: #include "USB.h"
95: #include "USBpriv.h"
96: #include "OHCIUIM.h"
97: #include "OHCIRootHub.h"
98:
99: //naga#include "driverservices.h"
100:
101: // Need some way of talking to the outside here
102: #define USBExpertStatus(a,b, c)
103:
104: // This isn't used at the moment
105: #define UIM_Bus 0
106:
107: // Put these in globals struct????
108: typedef struct{
109: UInt8 *buf;
110: UInt32 bufLen;
111: CallBackFuncPtr handler;
112: UInt32 refCon;
113: }intTrans;
114: #define kMaxOutstandingTrans 4
115: static intTrans outstanding[kMaxOutstandingTrans];
116: static UInt32 intLock;
117: //naga typedef UInt32 *QHdrPtr; //naga temporary
118: static QHdrPtr simCallbackQueue;
119: static UInt16 configuration;
120:
121: UInt16 Swap16(UInt16 value);
122: UInt16 Swap16(UInt16 value)
123: {
124: return( (value << 8) | (value >> 8) );
125: }
126: #define HostToUSBWord Swap16
127: #define USBToHostWord Swap16
128:
129:
130: #if 0
131: if(simCallbackQueue == nil)
132: {
133: if( (PBQueueCreate(&simCallbackQueue) != noErr) ||
134: (PBQueueInit(simCallbackQueue) != noErr) )
135: {
136: /* Panic */
137: USBExpertStatus(0,"\pUSL - failed to initialise root simulation queue", 0);
138: }
139: }
140:
141:
142: OSStatus UIMProcessDoneQueue(void)
143: {
144: USBPB *pb;
145:
146: if( (simCallbackQueue != nil) && (simCallbackQueue->qHead != nil) )
147: {
148: while(PBDequeueFirst(simCallbackQueue, (void *)&pb) == noErr)
149: {
150: uslInterruptPriority(-1);
151:
152: if(pb == nil)
153: {
154: USBExpertStatus(-1, "\pNil pb", 0);
155: }
156: else
157: {
158: if (pb->usbCompletion && (pb->usbCompletion != kUSBNoCallBack))
159: (*pb->usbCompletion)(pb);
160: }
161: }
162: }
163: #if 0
164: #if CHECK_UIM
165: static void **UIM, *UIM1;
166: checkUIMMoved(&UIM, &UIM1, (void *)&UIMPlugIn->uimProcessDoneQueueProc);
167: #endif
168:
169: if(UIMPlugIn != nil)
170: {
171: return(*UIMPlugIn->uimProcessDoneQueueProc)();
172: }
173: return(-1);
174: #else
175: return(noErr);
176: #endif
177: }
178:
179: static void simIntPktHandler(long refCon, OSStatus status, short shortfall)
180: {
181: USBPB *pb;
182:
183: if(refCon == 0)
184: {
185: return;
186: }
187:
188: pb = (void *)refCon;
189: status = doUSLStatus(status, pb->usbReference);
190:
191: pb->usbStatus = status;
192: pb->usbActCount = pb->usbReqCount - shortfall;
193: uslInterruptPriority(+1);
194: PBEnqueueLast((void *)pb, simCallbackQueue);
195: }
196:
197: static void simPktHandler(long refCon, OSStatus status, short shortfall)
198: {
199: USBPB *pb;
200:
201: if(refCon == 0)
202: {
203: return;
204: }
205:
206:
207: pb = (void *)refCon;
208: status = doUSLStatus(status, pb->usbReference);
209:
210: pb->usbStatus = status;
211: pb->usbActCount = pb->usbReqCount - shortfall;
212:
213: pb->usb.cntl.WIndex = USBToHostWord(pb->usb.cntl.WIndex);
214: pb->usb.cntl.WValue = USBToHostWord(pb->usb.cntl.WValue);
215: uslInterruptPriority(+1);
216: PBEnqueueLast((void *)pb, simCallbackQueue);
217: }
218:
219:
220:
221: #endif
222:
223:
224: // *********
225:
226: static Boolean SimulateSetConfiguration(UInt16 value)
227: {
228: if((value == 1) || (value == 0) )
229: {
230: configuration = value;
231: return(false);
232: }
233: return(true);
234: }
235:
236: static Boolean SimulateGetDeviceDescriptor(UInt8 *buf, UInt32 *bufLen, UInt32 descIndex)
237: {
238: UInt32 length;
239: static USBDeviceDescriptor desc ={
240: 18, // UInt8 length;
241: kUSBDeviceDesc, // UInt8 descType;
242: USB_CONSTANT16(kUSBRel10), // UInt16 usbRel;
243: kUSBHubClass, // UInt8 class;
244: kUSBHubSubClass, // UInt8 subClass;
245: 0, // UInt8 protocol;
246: 8, // UInt8 maxPacketSize;
247: USB_CONSTANT16(kAppleVendorID), // UInt16 vendor; Apple = 1452 (decimal, swapped)
248: USB_CONSTANT16(kPrdRootHubCMD), // UInt16 product; 0x8001
249: USB_CONSTANT16(0x0100), // UInt16 devRel; 1.00
250: 0, // UInt8 manuIdx;
251: 0, // UInt8 prodIdx;
252: 0, // UInt8 serialIdx;
253: 1, // UInt8 numConf;
254: 0 // UInt16 end;
255: };
256:
257: if(descIndex != 0)
258: {
259: return(true);
260: }
261:
262: length = sizeof(desc);
263: if(*bufLen < length)
264: {
265: length = *bufLen;
266: }
267: usb_BlockMoveData(&desc, buf, length);
268: *bufLen -= length;
269:
270: return(false);
271: }
272:
273: static Boolean SimulateGetConfDescriptor(UInt8 *buf, UInt32 *bufLen, UInt32 descIndex)
274: {
275: UInt32 length;
276: #define totalLen (9+9+7)
277: static USBConfigurationDescriptor confDesc ={
278: 9, //UInt8 length;
279: kUSBConfDesc, //UInt8 descriptorType;
280: USB_CONSTANT16(totalLen), //UInt16 totalLength;
281: 1, //UInt8 numInterfaces;
282: 1, //UInt8 configValue;
283: 0, //UInt8 configStrIndex;
284: 0x60, //UInt8 attributes; self powered, supports remote wkup
285: 0, //UInt8 maxPower;
286: };
287: static USBInterfaceDescriptor intfDesc ={
288: 9, //UInt8 length;
289: kUSBInterfaceDesc, //UInt8 descriptorType;
290: 1, //UInt8 interfaceNumber;
291: 0, //UInt8 alternateSetting;
292: 1, //UInt8 numEndpoints;
293: kUSBHubClass, //UInt8 interfaceClass;
294: kUSBHubSubClass, //UInt8 interfaceSubClass;
295: 1, //UInt8 interfaceProtocol;
296: 0 //UInt8 interfaceStrIndex;
297: };
298: static USBEndPointDescriptor endptDesc ={
299: 7, //UInt8 length;
300: kUSBEndpointDesc, //UInt8 descriptorType;
301: 0x81, //UInt8 endpointAddress; In, 1
302: kUSBInterrupt, //UInt8 attributes;
303: USB_CONSTANT16(8), //UInt16 maxPacketSize;
304: 255, //UInt8 interval;
305: };
306: UInt8 confBuf[totalLen];
307:
308: if(descIndex != 0)
309: {
310: //return(true); // temp don't make this fail while debugging root hub
311: }
312: if(totalLen != confDesc.length+intfDesc.length+endptDesc.length)
313: {
314: return(true);
315: }
316: usb_BlockMoveData(&confDesc, &confBuf[0], confDesc.length);
317: usb_BlockMoveData(&intfDesc, &confBuf[confDesc.length], intfDesc.length);
318: usb_BlockMoveData(&endptDesc, &confBuf[confDesc.length+intfDesc.length], endptDesc.length);
319:
320: length = totalLen;
321: if(*bufLen < length)
322: {
323: length = *bufLen;
324: }
325: usb_BlockMoveData(&confBuf, buf, length);
326: *bufLen -= length;
327:
328: return(false);
329: }
330:
331: static Boolean SimulateGetADeviceDescriptor(setupPacket *packet, UInt8 *buf, UInt32 *bufLen)
332: {
333: UInt8 descType, descIndex;
334: descType = USBToHostWord(packet->word[wValue]) >> 8;
335: descIndex = USBToHostWord(packet->word[wValue]) & 0xff;
336: if( (packet->word[wIndex] != 0) || (descType != kUSBStringDesc) )
337: {
338: /* This is not a string descriptor and its is not a string descriptor */
339: if(descType == kUSBDeviceDesc)
340: {
341: return(SimulateGetDeviceDescriptor(buf, bufLen, descIndex));
342: }
343: else if(descType == kUSBConfDesc)
344: {
345: return(SimulateGetConfDescriptor(buf, bufLen, descIndex));
346: }
347: else
348: {
349: return(true); /* Unknown dscriptor */
350: }
351: }
352: else if(descType == kUSBStringDesc)
353: {
354: /* cope with string descriptor */
355: return(true);
356: }
357:
358: /* Non zero index with non string descriptor */
359: return(true);
360:
361: }
362:
363:
364: static Boolean SimulateGetHubDescriptor(setupPacket *packet, UInt8 *buf, UInt32 *bufLen)
365: {
366: struct uslRootHubDescriptor descr; //naga struct added
367: int bytesOfFlags, copy, length;
368:
369: if(packet->word[wValue] == 0)
370: {
371:
372: if(OHCIGetRootDescriptor(UIM_Bus, &descr) != noErr)
373: {
374: return(true);
375: }
376:
377: length = *bufLen;
378:
379: if(length > 0)
380: {
381: /* Descriptor length */
382: bytesOfFlags = (descr.numPorts+1)/8+1;
383: buf[0] = bytesOfFlags*2 + 7;
384: length--;
385: }
386: if(length > 0)
387: {
388: /* Descriptor type */
389: buf[1] = kUSBHubDescriptorType;
390: length--;
391: }
392: if(length > 0)
393: {
394: buf[2] = descr.numPorts;
395: length--;
396: }
397: if(length > 0)
398: {
399: if(descr.powerSwitching)
400: {
401: buf[3] = !descr.gangedSwitching;
402: }
403: else
404: {
405: buf[3] = 2;
406: }
407: if(descr.compoundDevice)
408: {
409: buf[3] |= 4;
410: }
411: if(descr.overCurrent)
412: {
413: buf[3] = (!descr.globalOverCurrent) << 3;
414: }
415: else
416: {
417: buf[3] |= 0x10;
418: }
419: length--;
420: }
421: if(length > 0)
422: {
423: /* Flags high byte */
424: buf[4] = 0;
425: length--;
426: }
427: if(length > 0)
428: {
429: /* power on to good */
430: buf[5] = 50; /* 100 ms? */
431: length--;
432: }
433: if(length > 0)
434: {
435: /* Hub controller current */
436: buf[6] = 0; /* no cuurrent from bus */
437: length--;
438: }
439: if(length > 0)
440: {
441: copy = length;
442: if(copy > bytesOfFlags)
443: {
444: copy = bytesOfFlags;
445: }
446: usb_BlockMoveData(&descr.portFlags[0], &buf[7], copy);
447: length -= copy;
448: }
449: if(length > 0)
450: {
451: int copy2;
452: copy2 = length;
453: if(copy2 > bytesOfFlags)
454: {
455: copy2 = bytesOfFlags;
456: }
457: usb_BlockMoveData(&descr.portFlags[copy], &buf[7+copy], copy2);
458: length -= copy2;
459: }
460:
461: *bufLen -= length;
462: return(false);
463: }
464:
465: return(true);
466:
467:
468: }
469: static Boolean SimulateClearPortFeature(setupPacket *packet)
470: {
471: UInt16 feature, port;
472: OSStatus err = -1;
473: feature = USBToHostWord(packet->word[wValue]);
474: port = USBToHostWord(packet->word[wIndex]);
475:
476: switch(feature)
477: {
478: case kUSBHubPortConnectionChangeFeature :
479: err =OHCIRootHubResetChangeConnection(UIM_Bus, port);
480: break;
481:
482: case kUSBHubPortSuspendChangeFeature :
483: err =OHCIRootHubResetSuspendChange(UIM_Bus, port);
484: break;
485:
486: case kUSBHubPortEnablenFeature :
487: err =OHCIRootHubPortEnable(UIM_Bus, port, false);
488: break;
489:
490: case kUSBHubPortPowerFeature :
491: err =OHCIRootHubPortPower(UIM_Bus, port, false);
492: // Now need to check if all ports are switched off and
493: // gang off if in gang mode
494: break;
495:
496: case kUSBHubPortResetChangeFeature :
497: err =OHCIRootHubResetResetChange(UIM_Bus, port);
498: break;
499:
500: case kUSBHubPortEnableChangeFeature :
501: err =OHCIRootHubResetEnableChange(UIM_Bus, port);
502: break;
503:
504: case kUSBHubPortOverCurrentChangeFeature :
505: err =OHCIRootHubResetOverCurrentChange(UIM_Bus, port);
506: break;
507:
508:
509: default:
510: //DebugStr("\pUnknown port clear");
511: USBExpertStatus(0,"\pUSL - Unknown port clear in root hub simulation", 0);
512: break;
513: }
514: return(err != noErr);
515: }
516:
517: static Boolean SimulateGetHubStatus(setupPacket *packet, UInt8 *buf, UInt32 *bufLen)
518: {
519: OSStatus err = -1;
520: static struct{
521: UInt16 status;
522: UInt16 change;
523: }hubStatus = {0,0}; /* Change this is overcurrent is implimeneted */
524: UInt32 rhStatus;
525:
526: if( (packet->word[wValue] == 0) && (packet->word[wIndex] == 0) )
527: {
528: if ((err = OHCIGetRhStatus(UIM_Bus, &rhStatus)) == noErr){
529:
530: // wouldn't it be handy to have HostToUSBLong
531: hubStatus.status = HostToUSBWord(rhStatus & 0x0FFFF);
532: hubStatus.change = HostToUSBWord((rhStatus >> 16) & 0x0FFFF);
533:
534: if(*bufLen > sizeof(hubStatus))
535: {
536: *bufLen = sizeof(hubStatus);
537: }
538: usb_BlockMoveData(&hubStatus, buf, *bufLen);
539: err = noErr;
540: }
541: }
542: return(err != noErr);
543: }
544:
545:
546: static Boolean SimulateGetPortStatus(setupPacket *packet, UInt8 *buf, UInt32 *bufLen)
547: {
548: struct uslRootHubPortStatus stat; //naga added struct
549: OSStatus err = -1;
550: UInt32 length;
551:
552: if(packet->word[wValue] == 0)
553: {
554: err = OHCIRootHubGetPortStatus(UIM_Bus, USBToHostWord(packet->word[wIndex]), &stat);
555: stat.portChangeFlags = USBToHostWord(stat.portChangeFlags);
556: stat.portFlags = USBToHostWord(stat.portFlags);
557: if(err == noErr)
558: {
559: length = *bufLen;
560: if(length > sizeof(stat))
561: {
562: length = sizeof(stat);
563: }
564: usb_BlockMoveData(&stat, buf, length);
565: *bufLen -= length;
566: }
567: }
568: return(err != noErr);
569: }
570: static Boolean SimulateSetPortFeature(setupPacket *packet)
571: {
572: UInt16 feature, port;
573: OSStatus err = -1;
574: feature = USBToHostWord(packet->word[wValue]);
575: port = USBToHostWord(packet->word[wIndex]);
576: switch(feature)
577: {
578: case kUSBHubPortSuspecdFeature :
579: err = OHCIRootHubPortSuspend(UIM_Bus, port, true);
580: break;
581:
582: case kUSBHubPortResetFeature :
583: err = OHCIRootHubResetPort(UIM_Bus, port);
584: break;
585:
586: case kUSBHubPortEnablenFeature :
587: err = OHCIRootHubPortEnable(UIM_Bus, port, true);
588: break;
589:
590: case kUSBHubPortPowerFeature :
591: err = OHCIRootHubPortPower(UIM_Bus, port, true);
592: if(err == noErr)
593: {
594: err = OHCIRootHubPower(UIM_Bus, true);
595: }
596: break;
597:
598: default:
599: // DebugStr("\pUnknown port set");
600: USBExpertStatus(0,"\pUSL - Unknown port set in root hub simulation", 0);
601: break;
602: }
603: return(err != noErr);
604: }
605:
606: static Boolean SimulateHubClearFeature(setupPacket *packet)
607: {
608: OSStatus err = -1;
609: if(packet->word[wValue] == kUSBHubLocalPowerChangeFeature)
610: {
611: USBExpertStatus(0,"\pRoot hub simulation - unimplemented Clear Power Change Feature", 0);
612: // err = OHCIRootHubLPSChange(UIM_Bus, false); // not implemented yet
613: }
614: if(packet->word[wValue] == kUSBHubOverCurrentChangeFeature)
615: {
616: USBExpertStatus(0,"\pRoot hub simulation - unimplemented Clear Overcurrent Change Feature", 0);
617: // err = OHCIRootHubOCChange(UIM_Bus, false); // not implemented yet
618: }
619: return(err != noErr);
620: }
621: static Boolean SimulateHubSetFeature(setupPacket *packet)
622: {
623: OSStatus err = -1;
624: if(packet->word[wValue] == kUSBHubLocalPowerChangeFeature)
625: {
626: USBExpertStatus(0,"\pRoot hub simulation - unimplemented Set Power Change Feature", 0);
627: // err = OHCIRootHubLPSChange(UIM_Bus, true); // not implemented yet
628: }
629: if(packet->word[wValue] == kUSBHubOverCurrentChangeFeature)
630: {
631: USBExpertStatus(0,"\pRoot hub simulation - unimplemented Set Overcurrent Change Feature", 0);
632: // err = OHCIRootHubOCChange(UIM_Bus, true); // not implemented yet
633: }
634: return(err != noErr);
635: }
636:
637:
638: void rootHubStatusChangeHandler(void)
639: { /* Only called if the RHSC bit is set at int. */
640: UInt16 statusChanged; /* only have 15 ports in OHCI */
641: UInt32 status, statusBit;
642: struct uslRootHubDescriptor descr; //naga added struct
643: static numPorts=0;
644: int index, move;
645: struct uslRootHubPortStatus stat; //naga added struct
646: intTrans last;
647:
648: last = outstanding[0];
649: /*naga
650: */
651: if(last.handler == nil)
652: {
653: kprintf("rootHubStatusChangeHandler: last handler = nil\n");
654: return;
655: }
656: if(CompareAndSwap(0, 1, &intLock))
657: {
658: for(index = 1; index < kMaxOutstandingTrans ; index++)
659: {
660: outstanding[index-1] = outstanding[index];
661: if(outstanding[index].handler == nil)
662: {
663: break;
664: }
665: }
666:
667: statusChanged = 0;
668: statusBit = 1;
669: if(OHCIGetRhStatus(UIM_Bus, &status) == noErr)
670: {
671: if( (status & kOHCIHcRhStatus_Change ) != 0)
672: {
673: kprintf("Hub status change bit set to 1 \n");
674: statusChanged |= statusBit; /* Hub status change bit */
675: }
676:
677: if(numPorts == 0)
678: {
679: if(OHCIGetRootDescriptor(UIM_Bus, &descr) == noErr)
680: {
681: numPorts = descr.numPorts;
682: kprintf("#ports=%d\n",numPorts);
683: }
684: else
685: {
686: //DebugStr("\pRoot hub int simulation hosed. No ports, tell Barry");
687: kprintf("USL - Root hub int simulation hosed. No ports, tell Barry");
688: }
689: }
690:
691: for(index = 1; index <= numPorts; index++)
692: {
693: statusBit <<= 1; /* Next bit */
694:
695: if(OHCIRootHubGetPortStatus(UIM_Bus, index, &stat) == noErr)
696: {
697: if(stat.portChangeFlags != 0)
698: {
699: statusChanged |= statusBit; /* Hub status change bit */
700: }
701: }
702:
703: }
704:
705: }
706:
707: move = last.bufLen;
708: if(move > sizeof(statusChanged))
709: {
710: move = sizeof(statusChanged);
711: }
712: if(numPorts < 8)
713: {
714: move = 1;
715: }
716: statusChanged = HostToUSBWord(statusChanged);
717: usb_BlockMoveData(&statusChanged, last.buf, move);
718: CompareAndSwap(1, 0, &intLock); /* Unlock the queue */
719: //naga (*last.handler)(last.refCon, noErr, last.bufLen - move);
720: (*last.handler)(last.refCon, noErr, last.bufLen - move);
721: }
722: }
723:
724:
725:
726: void pollRootHubSim(void)
727: {
728: UInt32 intrStatus;
729: //naga if(outstanding[0].handler != nil)
730: if(outstanding[0].handler != nil)
731: {
732: if( (OHCIGetInterruptStatus(UIM_Bus, &intrStatus) == noErr) &&
733: ((intrStatus & kOHCIHcInterrupt_RHSC) != 0) )
734: {
735: OHCIClearInterruptStatus(UIM_Bus, kOHCIHcInterrupt_RHSC);
736: //kprintf("calling rootHubStatusChange handler\n");
737: rootHubStatusChangeHandler();
738: }
739: }
740: }
741:
742: void SimulateRootHubInt(UInt8 endpoint, UInt8 *buf, UInt32 bufLen,
743: CallBackFuncPtr handler, UInt32 refCon)
744: {
745: int index;
746:
747: if(endpoint != 1)
748: {
749: (*handler)(refCon, -1, bufLen);
750: return;
751: }
752:
753: if(!CompareAndSwap(0, 1, &intLock))
754: { /* Busy */
755: (*handler)(refCon, -1, bufLen);
756: return;
757: }
758:
759: for(index = 0; index < kMaxOutstandingTrans; index++)
760: {
761: if(outstanding[0].handler == nil)
762: {
763: /* found free trans */
764: outstanding[0].buf = buf;
765: outstanding[0].bufLen = bufLen;
766: outstanding[0].handler = handler;
767: outstanding[0].refCon = refCon;
768: CompareAndSwap(1, 0, &intLock); /* Unlock the queue */
769: return;
770: }
771: }
772:
773: CompareAndSwap(1, 0, &intLock); /* Unlock the queue */
774: (*handler)(refCon, -1, bufLen); /* too many trans */
775:
776: }
777:
778: static Boolean SimulateRootHub(setupPacket *packet, UInt8 *buf, UInt32 *bufLen)
779: {
780: UInt8 dirn, type, recipient;
781: Boolean stall;
782:
783: #if 0
784: typedef union{
785: UInt8 byte[8];
786: UInt16 word[4];
787: }setupPacket;
788:
789: enum{
790: /* Byte offsets */
791: bmRqType = 0,
792: bUsedFlag = bmRqType,
793: bRequest,
794: /* Word offsets */
795: wValue =1,
796: wIndex,
797: wLength
798: };
799: #endif
800:
801: stall = false;
802: dirn = (packet->byte[bmRqType] >> kUSBRqDirnShift) & kUSBRqDirnMask;
803: type = (packet->byte[bmRqType] >> kUSBRqTypeShift) & kUSBRqTypeMask;
804: recipient = packet->byte[bmRqType] & kUSBRqRecipientMask;
805: //kprintf("SimulateRootHub:request=0x%x,type=0x%x\n",packet->byte[bRequest],type);
806: if(type == kUSBStandard)
807: {
808:
809: #if 0
810: Standard Requests
811:
812: bmRequestType bRequest wValue wIndex wLength Data
813: 00000000B CLEAR_FEATURE device
814: 00000001B Interface
815: 00000010B Endpoint
816:
817: 10000000B GET_CONFIGURATION Zero Zero One Configuration
818: 10000000B GET_DESCRIPTOR Descriptor
819: 10000001B GET_INTERFACE Zero Interface One Alternate
820:
821: 10000000B GET_STATUS device
822: 10000001B Interface
823: 10000010B Endpoint
824:
825: 00000000B SET_ADDRESS Device
826: 00000000B SET_CONFIGURATION Configuration
827: 00000000B SET_DESCRIPTOR Descriptor
828:
829: 00000000B SET_FEATURE device
830: 00000001B Interface
831: 00000010B Endpoint
832:
833: 00000001B SET_INTERFACE Alternate
834: 10000010B SYNCH_FRAME Zero Endpoint Two Frame Number#endif
835: #endif
836: switch(packet->byte[bRequest])
837: {
838: case kUSBRqClearFeature:
839: if(packet->byte[bmRqType] == 0x00)
840: {
841: /* Clear Device Feature */
842: stall = SimulateHubClearFeature(packet);
843: }
844: else if(packet->byte[bmRqType] == 0x01)
845: {
846: /* Clear Interface Feature */
847: stall = true;
848: //DebugStr("\pRoot hub not implemented yet 2");
849: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 2", 0);
850: }
851: else if(packet->byte[bmRqType] == 0x02)
852: {
853: /* Clear Endpoint Feature */
854: stall = true;
855: //DebugStr("\pRoot hub not implemented yet 3");
856: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 3", 0);
857: }
858: else
859: {
860: stall = true;
861: }
862: break;
863:
864: case kUSBRqGetConfig:
865: if(packet->byte[bmRqType] == 0x80)
866: {
867: /* Get configuration */
868: stall = true;
869: //DebugStr("\pRoot hub not implemented yet 4");
870: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 4", 0);
871: }
872: else
873: {
874: stall = true;
875: }
876: break;
877:
878: case kUSBRqGetDescriptor:
879: if(packet->byte[bmRqType] == 0x80)
880: {
881: /* Get descriptor */
882: stall = SimulateGetADeviceDescriptor(packet, buf, bufLen);
883: }
884: else
885: {
886: stall = true;
887: }
888:
889: break;
890:
891: case kUSBRqGetInterface:
892: if(packet->byte[bmRqType] == 0x81)
893: {
894: /* Get interface */
895: stall = true;
896: //DebugStr("\pRoot hub not implemented yet 6");
897: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 6", 0);
898: }
899: else
900: {
901: stall = true;
902: }
903: break;
904:
905: case kUSBRqGetStatus:
906: if(packet->byte[bmRqType] == 0x80)
907: {
908: UInt16 status;
909: int copy;
910: /* Get Device Status */
911: stall = false;
912: status = USB_CONSTANT16(1); // self powered
913: copy = sizeof(status);
914: if(copy > *bufLen)
915: {
916: copy = *bufLen;
917: }
918: usb_BlockMoveData(&status, buf, copy);
919: *bufLen -= copy;
920:
921: }
922: else if(packet->byte[bmRqType] == 0x81)
923: {
924: /* Get Interface Status */
925: stall = true;
926: //DebugStr("\pRoot hub not implemented yet 8");
927: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 8", 0);
928: }
929: else if(packet->byte[bmRqType] == 0x82)
930: {
931: /* Get Endpoint Status */
932: stall = true;
933: //DebugStr("\pRoot hub not implemented yet 9");
934: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 9", 0);
935: }
936: else
937: {
938: stall = true;
939: }
940: break;
941:
942: case kUSBRqSetAddress:
943: if(packet->byte[bmRqType] == 0x00)
944: {
945: /* Set address */
946: stall = OHCISetOurAddress(UIM_Bus, USBToHostWord(packet->word[wValue]));
947: }
948: else
949: {
950: stall = true;
951: }
952: break;
953:
954: case kUSBRqSetConfig:
955: if(packet->byte[bmRqType] == 0x00)
956: {
957: /* Set configuration */
958: stall = SimulateSetConfiguration(USBToHostWord(packet->word[wValue]));
959: }
960: else
961: {
962: stall = true;
963: }
964: break;
965:
966: case kUSBRqSetDescriptor:
967: if(packet->byte[bmRqType] == 0x00)
968: {
969: /* Set descriptor */
970: stall = true;
971: //DebugStr("\pRoot hub not implemented yet 12");
972: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 12", 0);
973: }
974: else
975: {
976: stall = true;
977: }
978: break;
979:
980: case kUSBRqSetFeature:
981: if(packet->byte[bmRqType] == 0x00)
982: {
983: /* Set Device Feature */
984: stall = SimulateHubSetFeature(packet);
985: }
986: else if(packet->byte[bmRqType] == 0x01)
987: {
988: /* Set Interface Feature */
989: stall = true;
990: //DebugStr("\pRoot hub not implemented yet 14");
991: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 14", 0);
992: }
993: else if(packet->byte[bmRqType] == 0x02)
994: {
995: /* Set Endpoint Feature */
996: stall = true;
997: //DebugStr("\pRoot hub not implemented yet 15");
998: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 15", 0);
999: }
1000: else
1001: {
1002: stall = true;
1003: }
1004: break;
1005:
1006: case kUSBRqSetInterface:
1007: if(packet->byte[bmRqType] == 0x01)
1008: {
1009: /* Set interface */
1010: stall = true;
1011: //DebugStr("\pRoot hub not implemented yet 16");
1012: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 16", 0);
1013: }
1014: else
1015: {
1016: stall = true;
1017: }
1018: break;
1019:
1020: case kUSBRqSyncFrame:
1021: stall = true;
1022: break;
1023:
1024: default:
1025: stall = true;
1026: break;
1027:
1028: }
1029: }
1030: else if(type == kUSBClass)
1031: {
1032:
1033: #if 0
1034: Class-specific Requests
1035:
1036: ClearHubFeature 0010 0000B CLEAR_FEATURE Feature
1037: ClearPortFeature 0010 0011B CLEAR_FEATURE Feature
1038: GetBusState 1010 0011B GET_STATE Zero Port One Per Port
1039: GetHubDescriptor 1010 0000B GET_DESCRIPTOR Descriptor
1040: GetHubStatus 1010 0000B GET_STATUS Zero Zero Four Hub Status
1041: GetPortStatus 1010 0011B GET_STATUS Zero Port Four Port Status
1042: SetHubDescriptor 0010 0000B SET_DESCRIPTOR Descriptor
1043: SetHubFeature 0010 0000B SET_FEATURE Feature
1044: SetPortFeature 0010 0011B SET_FEATURE Feature
1045: #endif
1046: switch(packet->byte[bRequest])
1047: {
1048: case kUSBRqClearFeature:
1049: if(packet->byte[bmRqType] == 0x20)
1050: {
1051: /* ClearHubFeature */
1052: stall = true;
1053: //DebugStr("\pRoot hub not implemented yet 17");
1054: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 17", 0);
1055: }
1056: else if(packet->byte[bmRqType] == 0x23)
1057: {
1058: stall = SimulateClearPortFeature(packet);
1059: }
1060: else
1061: {
1062: stall = true;
1063: }
1064:
1065: break;
1066:
1067: case kUSBRqReserved1 /*GET_STATE*/:
1068: if(packet->byte[bmRqType] == 0xA3)
1069: {
1070: /* GetBusState */
1071: stall = true;
1072: //DebugStr("\pRoot hub not implemented yet 18");
1073: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 18", 0);
1074: }
1075: else
1076: {
1077: stall = true;
1078: }
1079: break;
1080:
1081: case kUSBRqGetDescriptor:
1082: if(packet->byte[bmRqType] == 0xA0)
1083: {
1084: /* GetHubDescriptor */
1085: SimulateGetHubDescriptor(packet, buf, bufLen);
1086: }
1087: else
1088: {
1089: stall = true;
1090: }
1091:
1092: break;
1093:
1094: case kUSBRqGetStatus:
1095: if(packet->byte[bmRqType] == 0xA0)
1096: {
1097: /* GetHubStatus */
1098: stall = SimulateGetHubStatus(packet, buf, bufLen);
1099: }
1100: else if(packet->byte[bmRqType] == 0xA3)
1101: {
1102: stall = SimulateGetPortStatus(packet, buf, bufLen);
1103: }
1104: else
1105: {
1106: stall = true;
1107: }
1108:
1109: break;
1110:
1111: case kUSBRqSetDescriptor:
1112: if(packet->byte[bmRqType] == 0x20)
1113: {
1114: /* SetHubDescriptor */
1115: stall = true;
1116: //DebugStr("\pRoot hub not implemented yet 20");
1117: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 20", 0);
1118: }
1119: else
1120: {
1121: stall = true;
1122: }
1123:
1124: break;
1125:
1126: case kUSBRqSetFeature :
1127: if(packet->byte[bmRqType] == 0x20)
1128: {
1129: /* SetHubFeature */
1130: stall = true;
1131: //DebugStr("\pRoot hub not implemented yet 21");
1132: USBExpertStatus(0,"\pUSL - Root hub not implemented yet 21", 0);
1133: }
1134: else if(packet->byte[bmRqType] == 0x23)
1135: {
1136: stall = SimulateSetPortFeature(packet);
1137: }
1138: else
1139: {
1140: stall = true;
1141: }
1142: break;
1143:
1144: default:
1145: stall = true;
1146: break;
1147: }
1148:
1149: }
1150: else
1151: {
1152: stall = true;
1153: }
1154:
1155: if(stall)
1156: {
1157: //DebugStr("\pSim Stall");
1158: USBExpertStatus(0,"\pUSL - Root hub simulated stall", 0);
1159: }
1160:
1161: return(stall);
1162: }
1163:
1164: typedef struct{
1165: setupPacket *packet;
1166: UInt8 *buf;
1167: UInt32 bufLen;
1168: CallBackFuncPtr handler1;
1169: UInt32 refCon1;
1170: CallBackFuncPtr handler2;
1171: UInt32 refCon2;
1172: CallBackFuncPtr handler3;
1173: UInt32 refCon3;
1174: Boolean stall;
1175: int state;
1176: } RHTransaction;
1177:
1178: static RHTransaction tr;
1179: #define kMaxRHtr 16
1180: static RHTransaction RHDone[kMaxRHtr];
1181: static UInt32 inUse[kMaxRHtr];
1182:
1183: enum{
1184: kNone = 0,
1185: kSetupReceived,
1186: kDataRecevied,
1187: kStatusDone
1188: };
1189:
1190:
1191: static void cleanState(RHTransaction *tr)
1192: {
1193: if( (tr->state != kDataRecevied) && (tr->state != kStatusDone) )
1194: {
1195: tr->buf = nil;
1196: tr->bufLen = 0;
1197: tr->handler2 = nil;
1198: tr->refCon2 = 0;
1199: tr->handler3 = nil;
1200: tr->refCon3 = 0;
1201: if(tr->state != kSetupReceived)
1202: {
1203: tr->handler1 = nil;
1204: tr->refCon1 = 0;
1205: tr->packet = nil;
1206: tr->state = kNone;
1207: }
1208: }
1209: }
1210:
1211:
1212: static RHTransaction *queueTR(RHTransaction *tr)
1213: {
1214: int i;
1215:
1216: for(i = 0; i< kMaxRHtr; i++)
1217: {
1218: if(CompareAndSwap(0, 1, &inUse[i]))
1219: {
1220: RHDone[i] = *tr;
1221: tr->state = kNone;
1222: cleanState(tr);
1223: inUse[i]++;
1224: return(&RHDone[i]);
1225: }
1226: }
1227: return(tr);
1228: }
1229:
1230: OSStatus UIMSimulateRootHubStages(
1231: UInt32 refcon,
1232: CallBackFuncPtr handler,
1233: UInt32 CBP,
1234: Boolean bufferRounding,
1235: short endpointNumber,
1236: short bufferSize,
1237: short direction);
1238: OSStatus UIMSimulateRootHubStages(
1239: UInt32 refcon,
1240: CallBackFuncPtr handler,
1241: UInt32 CBP,
1242: Boolean bufferRounding,
1243: short endpointNumber,
1244: short bufferSize,
1245: short direction)
1246: {
1247: static directionReceived;
1248: RHTransaction *trOut;
1249:
1250: if(endpointNumber != 0)
1251: {
1252: bufferRounding = 0; // stop annoying warning
1253: return(-1);
1254: }
1255:
1256: if( (direction != kUSBIn) && (direction != kUSBOut)) // setup packet
1257: { /* Setup packet over rides any previous state */
1258:
1259: if(tr.state != kNone) // no queues we only cope with one (complete) control per frame.
1260: {
1261: return(kUSBDeviceBusy);
1262: }
1263: cleanState(&tr);
1264:
1265: if(bufferSize != 8)
1266: {
1267: tr.state = kNone;
1268: }
1269:
1270: tr.packet = (void *)CBP;
1271: tr.handler1 = handler;
1272: tr.refCon1 = refcon;
1273: tr.state = kSetupReceived;
1274:
1275: directionReceived = (((*(UInt8 *)CBP) & 0x80) == 0)?kUSBOut:kUSBIn;
1276:
1277:
1278: }
1279: else
1280: {
1281: if(directionReceived != direction) // status phase is reverse data
1282: {
1283: tr.handler3 = handler;
1284: tr.refCon3 = refcon;
1285: trOut = queueTR(&tr);
1286: trOut->stall = SimulateRootHub(trOut->packet, trOut->buf, &trOut->bufLen);
1287: directionReceived = 0;
1288: trOut->state = kStatusDone;
1289: OHCISetFrameInterrupt();
1290: return(noErr);
1291: }
1292: else if(tr.state == kSetupReceived)
1293: {
1294: tr.buf = (void *)CBP;
1295: tr.bufLen = bufferSize;
1296: tr.handler2 = handler;
1297: tr.refCon2 = refcon;
1298: tr.state = kDataRecevied;
1299: }
1300: else
1301: {
1302: tr.state = kNone;
1303: }
1304:
1305: }
1306:
1307: cleanState(&tr);
1308: return(noErr);
1309: }
1310:
1311:
1312: static void rootHubDispatch(RHTransaction *tr)
1313: {
1314: CallBackFuncPtr handler;
1315: UInt32 refCon;
1316: UInt32 retBufLen;
1317: if(tr->state != kStatusDone)
1318: {
1319: return;
1320: }
1321:
1322: // need to sync to end of frame here
1323: if(tr->handler1 != nil)
1324: (*tr->handler1)(tr->refCon1, noErr, 0);
1325: if(tr->handler2 != nil)
1326: (*tr->handler2)(tr->refCon2, noErr, 0);
1327: handler = tr->handler3;
1328: refCon = tr->refCon3;
1329: retBufLen = tr->bufLen;
1330: tr->state = kNone;
1331: cleanState(tr);
1332: if(handler != nil)
1333: {
1334: (*handler)(refCon, tr->stall?4:noErr, retBufLen);
1335: }
1336:
1337: }
1338:
1339: OSStatus RootHubFrame(void *p1, void *p2)
1340: {
1341: int i;
1342:
1343: p1 = 0;
1344: p2 = 0;
1345:
1346: for(i = 0; i< kMaxRHtr; i++)
1347: {
1348: if(inUse[i] == 2)
1349: {
1350: rootHubDispatch(&RHDone[i]);
1351: cleanState(&RHDone[i]);
1352: inUse[i] = 0;
1353: }
1354: }
1355:
1356: rootHubDispatch(&tr);
1357: return(noErr);
1358: }
1359:
1360:
1361:
1362: OSStatus RootHubStatusChange(void *p1, void *p2)
1363: {
1364: p1 = 0;
1365: p2 = 0;
1366: //SysDebug();
1367: if(outstanding[0].handler != nil)
1368: {
1369: rootHubStatusChangeHandler();
1370: }
1371: return(noErr);
1372: }
1373:
1374: void OHCIPollRootHubSim(uslBusRef bus)
1375: {
1376: bus = 0;
1377: RootHubFrame(nil, nil);
1378: pollRootHubSim();
1379: }
1380:
1381:
1382:
1383: void ResetRootHubSimulation(void)
1384: {
1385: int index;
1386:
1387: for(index = 0; index < kMaxOutstandingTrans; index++)
1388: {
1389: outstanding[0].handler = nil; // clear out any outstanding transactions
1390: }
1391: intLock = 0;
1392: OHCISetOurAddress(0, 0);
1393: }
1394:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.