2 Copyright © 2014, The AROS Development Team. All rights reserved.
14 #include <aros/macros.h>
16 #include <proto/exec.h>
17 #include <proto/stdc.h>
18 #include <proto/arossupport.h>
20 #include <devices/usb.h>
21 #include <devices/usb_hub.h>
22 #include <devices/newstyle.h>
23 #include <devices/usbhardware.h>
25 #include "vxhci_device.h"
27 #include LC_LIBDEFS_FILE
29 WORD
cmdQueryDevice(struct IOUsbHWReq
*ioreq
) {
30 mybug(0, ("[VXHCI] cmdQueryDevice: Entering function\n"));
32 struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
34 struct TagItem
*taglist
= (struct TagItem
*) ioreq
->iouh_Data
;
38 while((tag
= LibNextTagItem(&taglist
)) != NULL
) {
39 switch (tag
->ti_Tag
) {
40 case UHA_Manufacturer
:
41 *((STRPTR
*) tag
->ti_Data
) = "The AROS Development Team";
45 *((ULONG
*) tag
->ti_Data
) = VERSION_NUMBER
;
49 *((ULONG
*) tag
->ti_Data
) = REVISION_NUMBER
;
53 *((STRPTR
*) tag
->ti_Data
) ="©2014 The AROS Development Team";
58 static char productname
[100];
59 sprintf(productname
, "VXHCI (USB%x.%x ports)", AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>8)&0xf, AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>4)&0xf);
60 *((STRPTR
*) tag
->ti_Data
) = productname
;
66 static char description
[100];
67 sprintf(description
, "Virtual XHCI (USB%x.%x ports)", AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>8)&0xf, AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>4)&0xf);
68 *((STRPTR
*) tag
->ti_Data
) = description
;
72 case UHA_Capabilities
:
74 if( (AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
) >= 0x200) && (AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
) < 0x300)) {
75 *((ULONG
*) tag
->ti_Data
) = (UHCF_USB20
);
77 *((ULONG
*) tag
->ti_Data
) = (UHCF_USB30
);
80 *((ULONG
*) tag
->ti_Data
) = (UHCF_USB20
|UHCF_USB30
);
89 mybug_unit(0, ("Done\n\n"));
91 ioreq
->iouh_Actual
= count
;
95 WORD
cmdUsbReset(struct IOUsbHWReq
*ioreq
) {
96 mybug(0, ("[VXHCI] cmdUsbReset: Entering function\n"));
98 struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
100 /* We should do a proper reset sequence with a real driver */
101 unit
->state
= UHSF_RESET
;
102 unit
->roothub
.addr
= 0;
103 unit
->state
= UHSF_OPERATIONAL
;
104 mybug_unit(0, ("Done\n\n"));
108 WORD
cmdControlXFer(struct IOUsbHWReq
*ioreq
) {
109 mybug(0, ("[VXHCI] cmdControlXFer: Entering function\n"));
111 struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
113 mybug_unit(0, ("ioreq->iouh_DevAddr %lx\n", ioreq
->iouh_DevAddr
));
114 mybug_unit(0, ("unit->roothub.addr %lx\n", unit
->roothub
.addr
));
117 Check the status of the controller
118 We might encounter these states:
119 UHSB_OPERATIONAL USB can be used for transfers
120 UHSB_RESUMING USB is currently resuming
121 UHSB_SUSPENDED USB is in suspended state
122 UHSB_RESET USB is just inside a reset phase
125 if(unit
->state
== UHSF_OPERATIONAL
) {
126 mybug_unit(0, ("Unit state is operational\n"));
128 mybug_unit(-1, ("Unit state is not operational!\n"));
129 return UHIOERR_USBOFFLINE
;
132 if(ioreq
->iouh_DevAddr
== unit
->roothub
.addr
) {
133 return(cmdControlXFerRootHub(ioreq
));
139 WORD
cmdControlXFerRootHub(struct IOUsbHWReq
*ioreq
) {
140 mybug(0, ("[VXHCI] cmdControlXFerRootHub: Entering function\n"));
142 UWORD bmRequestType
= (ioreq
->iouh_SetupData
.bmRequestType
) & (URTF_STANDARD
| URTF_CLASS
| URTF_VENDOR
);
143 UWORD bmRequestDirection
= (ioreq
->iouh_SetupData
.bmRequestType
) & (URTF_IN
| URTF_OUT
);
144 UWORD bmRequestRecipient
= (ioreq
->iouh_SetupData
.bmRequestType
) & (URTF_DEVICE
| URTF_INTERFACE
| URTF_ENDPOINT
| URTF_OTHER
);
146 UWORD bRequest
= (ioreq
->iouh_SetupData
.bRequest
);
147 D(UWORD wIndex
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
));
148 UWORD wValue
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wValue
);
149 UWORD wLength
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wLength
);
151 struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
153 /* Endpoint 0 is used for control transfers only and can not be assigned to any other function. */
154 if(ioreq
->iouh_Endpoint
!= 0) {
155 mybug_unit(-1, ("Wrong endpoint number! %ld\n", ioreq
->iouh_Endpoint
));
156 return UHIOERR_BADPARAMS
;
159 /* Check the request */
160 if(bmRequestDirection
) {
161 mybug_unit(0, ("Request direction is device to host\n"));
163 switch(bmRequestType
) {
165 mybug_unit(0, ("URTF_STANDARD\n"));
167 switch(bmRequestRecipient
) {
169 mybug_unit(0, ("URTF_DEVICE\n"));
172 case USR_GET_DESCRIPTOR
:
173 mybug_unit(0, ("USR_GET_DESCRIPTOR\n"));
175 switch( (wValue
>>8) ) {
177 mybug_unit(0, ("UDT_DEVICE\n"));
178 mybug_unit(0, ("GetDeviceDescriptor (%ld)\n", wLength
));
180 ioreq
->iouh_Actual
= (wLength
> sizeof(struct UsbStdDevDesc
)) ? sizeof(struct UsbStdDevDesc
) : wLength
;
181 CopyMem((APTR
) &unit
->roothub
.devdesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
183 mybug_unit(0, ("Done\n\n"));
187 case UDT_CONFIGURATION
:
188 mybug_unit(0, ("UDT_CONFIGURATION\n"));
189 mybug_unit(0, ("GetConfigDescriptor (%ld)\n", wLength
));
191 ioreq
->iouh_Actual
= (wLength
> sizeof(struct RHConfig
)) ? sizeof(struct RHConfig
) : wLength
;
192 CopyMem((APTR
) &unit
->roothub
.config
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
194 //bug("sizeof(struct RHConfig) = %ld (should be 25)\n", sizeof(struct RHConfig));
195 mybug_unit(0, ("Done\n\n"));
201 mybug_unit(0, ("UDT_STRING id %d\n", (wValue
& 0xff)));
204 switch( (wValue
& 0xff) ) {
206 mybug_unit(0, ("GetStringDescriptor (%ld)\n", wLength
));
208 /* This is our root hub string descriptor */
209 struct UsbStdStrDesc
*strdesc
= (struct UsbStdStrDesc
*) ioreq
->iouh_Data
;
211 strdesc
->bLength
= sizeof(struct UsbStdStrDesc
);
212 strdesc
->bDescriptorType
= UDT_STRING
;
215 strdesc
->bString
[0] = AROS_WORD2LE(0x0409); // English (Yankee)
216 ioreq
->iouh_Actual
= sizeof(struct UsbStdStrDesc
);
217 mybug_unit(0, ("Done\n\n"));
220 ioreq
->iouh_Actual
= wLength
;
221 mybug_unit(0, ("Done\n\n"));
228 return cmdGetString(ioreq
, "The AROS Development Team.");
232 char roothubname
[100];
233 sprintf(roothubname
, "VXHCI root hub (USB%x.%x)", AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>8)&0xf, AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>4)&0xf);
234 return cmdGetString(ioreq
, roothubname
);
239 return cmdGetString(ioreq
, "Standard Config");
243 return cmdGetString(ioreq
, "Hub interface");
254 bug("[VXHCI] cmdControlXFerRootHub: UDT_INTERFACE\n");
258 bug("[VXHCI] cmdControlXFerRootHub: UDT_ENDPOINT\n");
261 case UDT_DEVICE_QUALIFIER
:
262 bug("[VXHCI] cmdControlXFerRootHub: UDT_DEVICE_QUALIFIER\n");
265 case UDT_OTHERSPEED_QUALIFIER
:
266 bug("[VXHCI] cmdControlXFerRootHub: UDT_OTHERSPEED_QUALIFIER\n");
269 case UDT_INTERFACE_POWER
:
270 bug("[VXHCI] cmdControlXFerRootHub: UDT_INTERFACE_POWER\n");
274 bug("[VXHCI] cmdControlXFerRootHub: UDT_OTG\n");
278 bug("[VXHCI] cmdControlXFerRootHub: UDT_DEBUG\n");
281 case UDT_INTERFACE_ASSOCIATION
:
282 bug("[VXHCI] cmdControlXFerRootHub: UDT_INTERFACE_ASSOCIATION\n");
286 bug("[VXHCI] cmdControlXFerRootHub: UDT_SECURITY\n");
289 case UDT_ENCRYPTION_TYPE
:
290 bug("[VXHCI] cmdControlXFerRootHub: UDT_ENCRYPTION_TYPE\n");
294 bug("[VXHCI] cmdControlXFerRootHub: UDT_BOS\n");
297 case UDT_DEVICE_CAPABILITY
:
298 bug("[VXHCI] cmdControlXFerRootHub: UDT_DEVICE_CAPABILITY\n");
301 case UDT_WIRELESS_EP_COMP
:
302 bug("[VXHCI] cmdControlXFerRootHub: UDT_WIRELESS_EP_COMP\n");
306 bug("[VXHCI] cmdControlXFerRootHub: switch( (wValue>>8) ) %ld\n", (wValue
>>8));
309 } /* switch( (wValue>>8) ) */
310 break; /* case USR_GET_DESCRIPTOR */
313 mybug_unit(0, ("USR_GET_STATUS\n"));
314 ((UWORD
*) ioreq
->iouh_Data
)[0] = AROS_WORD2LE(U_GSF_SELF_POWERED
);
315 ioreq
->iouh_Actual
= wLength
;
316 mybug_unit(0, ("Done\n\n"));
320 } /* switch(bRequest) */
321 break; /* case URTF_DEVICE: */
324 mybug_unit(0, ("URTF_INTERFACE\n"));
328 mybug_unit(0, ("URTF_ENDPOINT\n"));
332 mybug_unit(0, ("URTF_OTHER\n"));
336 mybug_unit(0, ("Request defaulting %ld\n", bRequest
));
339 } /* switch(bmRequestRecipient) */
343 mybug_unit(0, ("URTF_CLASS\n"));
345 switch(bmRequestRecipient
) {
347 mybug_unit(0, ("URTF_DEVICE\n"));
351 mybug_unit(-1, ("USR_GET_STATUS\n"));
352 UWORD
*mptr
= ioreq
->iouh_Data
;
353 if(wLength
< sizeof(struct UsbHubStatus
)) {
354 return(UHIOERR_STALL
);
358 ioreq
->iouh_Actual
= 4;
359 mybug_unit(-1, ("Something done, check me...\n\n"));
364 case USR_GET_DESCRIPTOR
:
365 mybug_unit(0, ("[VXHCI] cmdControlXFerRootHub: USR_GET_DESCRIPTOR\n"));
367 switch( (wValue
>>8) ) {
369 mybug_unit(0, ("UDT_HUB\n"));
370 mybug_unit(0, ("GetRootHubDescriptor USB2.0 (%ld)\n", wLength
));
372 ioreq
->iouh_Actual
= (wLength
> sizeof(struct UsbHubDesc
)) ? sizeof(struct UsbHubDesc
) : wLength
;
373 CopyMem((APTR
) &unit
->roothub
.hubdesc
.usb20
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
375 mybug_unit(0, ("Done\n\n"));
380 mybug_unit(0, ("UDT_SSHUB\n"));
381 mybug_unit(0, ("GetRootHubDescriptor USB3.0 (%ld)\n", wLength
));
383 ioreq
->iouh_Actual
= (wLength
> sizeof(struct UsbSSHubDesc
)) ? sizeof(struct UsbSSHubDesc
) : wLength
;
384 CopyMem((APTR
) &unit
->roothub
.hubdesc
.usb30
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
386 mybug_unit(0, ("Done\n\n"));
391 mybug_unit(0, ("Done\n\n"));
397 } /* case URTF_CLASS */
401 mybug_unit(0, ("URTF_VENDOR\n"));
403 } /* switch(bmRequestType) */
405 } else { /* if(bmRequestDirection) */
406 mybug_unit(0, ("Request direction is host to device\n"));
408 switch(bmRequestType
) {
410 mybug_unit(0, ("[VXHCI] cmdControlXFerRootHub: URTF_STANDARD\n"));
412 switch(bmRequestRecipient
) {
414 mybug_unit(0, ("[VXHCI] cmdControlXFerRootHub: URTF_DEVICE\n"));
417 case USR_SET_ADDRESS
:
418 mybug_unit(0, ("USR_SET_ADDRESS\n"));
419 unit
->roothub
.addr
= wValue
;
420 ioreq
->iouh_Actual
= wLength
;
421 mybug_unit(0, ("Done\n\n"));
425 case USR_SET_CONFIGURATION
:
426 /* We do not have alternative configuration */
427 mybug_unit(0, ("USR_SET_CONFIGURATION\n"));
428 ioreq
->iouh_Actual
= wLength
;
429 mybug_unit(0, ("Done\n\n"));
433 } /* switch(bRequest) */
437 mybug_unit(0, ("URTF_INTERFACE\n"));
441 mybug_unit(0, ("URTF_ENDPOINT\n"));
445 mybug_unit(0, ("URTF_OTHER\n"));
448 } /* switch(bmRequestRecipient) */
452 mybug_unit(0, ("URTF_CLASS\n"));
456 mybug_unit(0, ("URTF_VENDOR\n"));
459 } /* switch(bmRequestType) */
461 } /* if(bmRequestDirection) */
463 D( mybug_unit(-1, ("bmRequestDirection "));
464 switch (bmRequestDirection
) {
466 mybug(-1, ("URTF_IN\n"));
469 mybug(-1, ("URTF_OUT\n"));
473 mybug_unit(-1, ("bmRequestType "));
474 switch(bmRequestType
) {
476 mybug(-1, ("URTF_STANDARD\n"));
479 mybug(-1, ("URTF_CLASS\n"));
482 mybug(-1, ("URTF_VENDOR\n"));
486 mybug_unit(-1, ("bmRequestRecipient "));
487 switch (bmRequestRecipient
) {
489 mybug(-1, ("URTF_DEVICE\n"));
492 mybug(-1, ("URTF_INTERFACE\n"));
495 mybug(-1, ("URTF_ENDPOINT\n"));
498 mybug(-1, ("URTF_OTHER\n"));
502 mybug_unit(-1, ("bRequest "));
505 bug("USR_GET_STATUS\n");
507 case USR_CLEAR_FEATURE
:
508 mybug(-1, ("USR_CLEAR_FEATURE\n"));
510 case USR_SET_FEATURE
:
511 mybug(-1, ("USR_SET_FEATURE\n"));
513 case USR_SET_ADDRESS
:
514 mybug(-1, ("USR_SET_ADDRESS\n"));
516 case USR_GET_DESCRIPTOR
:
517 mybug(-1, ("USR_GET_DESCRIPTOR\n"));
519 case USR_SET_DESCRIPTOR
:
520 mybug(-1, ("USR_SET_DESCRIPTOR\n"));
522 case USR_GET_CONFIGURATION
:
523 mybug(-1, ("USR_GET_CONFIGURATION\n"););
525 case USR_SET_CONFIGURATION
:
526 mybug(-1, ("USR_SET_CONFIGURATION\n"));
528 case USR_GET_INTERFACE
:
529 mybug(-1, ("USR_GET_INTERFACE\n"));
531 case USR_SET_INTERFACE
:
532 mybug(-1, ("USR_SET_INTERFACE\n"));
534 case USR_SYNCH_FRAME
:
535 mybug(-1, ("USR_SYNCH_FRAME\n"));
539 mybug_unit(-1, ("wIndex %x\n", wIndex
));
540 mybug_unit(-1, ("wValue %x\n", wValue
));
541 mybug_unit(-1, ("wLength %d\n", wLength
));
543 mybug_unit(-1, ("Nothing done!\n\n")) );
546 return UHIOERR_BADPARAMS
;
549 WORD
cmdIntXFer(struct IOUsbHWReq
*ioreq
) {
550 mybug(-1, ("[VXHCI] cmdIntXFer: Entering function\n"));
552 struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
554 mybug_unit(-1, ("ioreq->iouh_DevAddr %lx\n", ioreq
->iouh_DevAddr
));
555 mybug_unit(-1, ("unit->roothub.addr %lx\n", unit
->roothub
.addr
));
558 Check the status of the controller
559 We might encounter these states:
560 UHSB_OPERATIONAL USB can be used for transfers
561 UHSB_RESUMING USB is currently resuming
562 UHSB_SUSPENDED USB is in suspended state
563 UHSB_RESET USB is just inside a reset phase
566 if(unit
->state
== UHSF_OPERATIONAL
) {
567 mybug_unit(0, ("Unit state is operational\n"));
569 mybug_unit(-1, ("Unit state is not operational!\n"));
570 return UHIOERR_USBOFFLINE
;
573 if(ioreq
->iouh_DevAddr
== unit
->roothub
.addr
) {
574 mybug_unit(-1, ("Entering cmdIntXFerRootHub\n"));
575 return(cmdIntXFerRootHub(ioreq
));
578 mybug_unit(-1, ("Nothing done!\n\n"));
582 WORD
cmdIntXFerRootHub(struct IOUsbHWReq
*ioreq
) {
583 mybug(-1, ("[VXHCI] cmdIntXFerRootHub: Entering function\n"));
584 D(struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
);
586 mybug_unit(-1, ("Nothing done!\n\n"));
590 WORD
cmdGetString(struct IOUsbHWReq
*ioreq
, char *cstring
) {
591 mybug(0, ("[VXHCI] cmdGetString: Entering function\n"));
593 UWORD wLength
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wLength
);
595 struct UsbStdStrDesc
*strdesc
= (struct UsbStdStrDesc
*) ioreq
->iouh_Data
;
596 strdesc
->bDescriptorType
= UDT_STRING
;
597 strdesc
->bLength
= (strlen(cstring
)*sizeof(strdesc
->bString
))+sizeof(strdesc
->bLength
) + sizeof(strdesc
->bDescriptorType
);
600 ioreq
->iouh_Actual
= 2;
601 while(ioreq
->iouh_Actual
<wLength
) {
602 strdesc
->bString
[(ioreq
->iouh_Actual
-2)/sizeof(strdesc
->bString
)] = AROS_WORD2LE(*cstring
);
603 ioreq
->iouh_Actual
+= sizeof(strdesc
->bString
);
606 mybug(0, ("[VXHCI] cmdGetString: Done\n\n"));
612 ioreq
->iouh_Actual
= wLength
;
613 mybug(0, ("[VXHCI] cmdGetString: Done\n\n"));
617 return UHIOERR_BADPARAMS
;