2 Copyright © 2015-2017, The AROS Development Team. All rights reserved.
5 Desc: VUSBHCI USB host controller
14 #include <aros/debug.h>
15 #include <aros/macros.h>
16 #include <aros/asmcall.h>
17 #include <aros/symbolsets.h>
19 #include <proto/exec.h>
20 #include <proto/arossupport.h>
22 #include <devices/usb.h>
23 #include <devices/usb_hub.h>
24 #include <devices/newstyle.h>
25 #include <devices/usbhardware.h>
27 #include "vusbhci_device.h"
30 FIXME: cmdAbortIO does not work for the request that is already passed to libusb
32 BOOL
cmdAbortIO(struct IOUsbHWReq
*ioreq
) {
33 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
34 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
36 /* If not quick I/O, reply the message */
37 if (!(ioreq
->iouh_Req
.io_Flags
& IOF_QUICK
)) {
38 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
44 WORD
cmdUsbReset(struct IOUsbHWReq
*ioreq
) {
45 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
47 mybug_unit(0, ("Entering function\n"));
49 /* We should do a proper reset sequence with a real driver */
50 unit
->state
= UHSF_RESET
;
51 unit
->roothub
.addr
= 0;
52 unit
->state
= UHSF_OPERATIONAL
;
53 mybug_unit(0, ("Done\n\n"));
57 /* Standard Requests */
61 bmRequestType (URTF_IN|URTF_STANDARD|URTF_DEVICE) 10000000B
62 bRequest USR_GET_STATUS
68 CHECKME: U_GSB_SELF_POWERED=8 and U_GSB_REMOTE_WAKEUP=9, should they be 0 and 1?
71 UWORD
GetStatus(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
72 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
73 mybug_unit(-1, ("Entering function\n"));
76 devicestatus
= ioreq
->iouh_Data
;
78 *devicestatus
= (U_GSF_SELF_POWERED
& (~U_GSF_REMOTE_WAKEUP
));
80 ioreq
->iouh_Actual
= wLength
;
82 mybug_unit(-1, ("GetStatus(%ld) %02x\n", wLength
, *devicestatus
));
84 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
85 return UHIOERR_NO_ERROR
;
90 bmRequestType (URTF_IN|URTF_STANDARD|URTF_DEVICE) 00000000B
91 bRequest CLEAR_FEATURE
92 wValue Feature Selector
97 UWORD
ClearFeature(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
98 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
99 mybug_unit(-1, ("Entering function\n"));
101 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
102 return UHIOERR_NO_ERROR
;
107 bmRequestType (URTF_IN|URTF_STANDARD|URTF_DEVICE) 00000000B
109 wValue Feature Selector
114 UWORD
SetFeature(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
115 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
116 mybug_unit(-1, ("Entering function\n"));
118 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
119 return UHIOERR_NO_ERROR
;
124 bmRequestType (URTF_OUT|URTF_STANDARD|URTF_DEVICE) 00000000B
125 bRequest USR_SET_ADDRESS
126 wValue Device Address
131 UWORD
SetAddress(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
132 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
133 mybug_unit(-1, ("Entering function\n"));
135 mybug_unit(-1, ("SetAddress (address %d)\n", wValue
));
137 /* It is a Request Error if wValue, wIndex, or wLength are other than as specified above. */
138 if( (wValue
) && (!(wIndex
)) && (!(wLength
)) ) {
140 unit
->roothub
.addr
= wValue
;
141 ioreq
->iouh_Actual
= wLength
;
143 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
144 return UHIOERR_NO_ERROR
;
147 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
148 return UHIOERR_BADPARAMS
;
153 bmRequestType (URTF_OUT|URTF_STANDARD|URTF_DEVICE) 10000000B
154 bRequest GET_DESCRIPTOR
155 wValue Descriptor Type & Index
156 wIndex Zero or Language ID
157 wLength Descriptor Length
160 UWORD
GetDescriptor(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
161 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
162 mybug_unit(-1, ("Entering function\n"));
164 CONST_STRPTR roothubstring
= NULL
;
165 CONST_STRPTR roothubstrings
[] = {"The AROS Development Team.", "VUSBHCI root hub (USB2.00)", "VUSBHCI root hub (USB3.00)", "Standard Config", "Hub interface" };
168 switch((wValue
>>8)) {
170 mybug_unit(-1, ("GetDeviceDescriptor UDT_DEVICE (length %ld)\n", wLength
));
172 ioreq
->iouh_Actual
= (wLength
> sizeof(struct UsbStdDevDesc
)) ? sizeof(struct UsbStdDevDesc
) : wLength
;
173 CopyMem((APTR
) &unit
->roothub
.devdesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
175 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
176 return UHIOERR_NO_ERROR
;
179 case UDT_CONFIGURATION
:
180 index
= (wValue
& 0xff);
182 mybug_unit(-1, ("GetDeviceDescriptor UDT_CONFIGURATION (configuration %d, length %ld)\n",index
, wLength
));
186 ioreq
->iouh_Actual
= (wLength
> sizeof(struct RHConfig
)) ? sizeof(struct RHConfig
) : wLength
;
187 CopyMem((APTR
) &unit
->roothub
.config
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
189 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
190 return UHIOERR_NO_ERROR
;
193 mybug_unit(-1, ("Our roothub supports only one configuration\n"));
194 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
195 return UHIOERR_BADPARAMS
;
199 index
= (wValue
& 0xff);
201 mybug_unit(-1, ("GetStringDescriptor UDT_STRING (index %d)\n", index
));
203 struct UsbStdStrDesc
*strdesc
= (struct UsbStdStrDesc
*) ioreq
->iouh_Data
;
208 strdesc
->bLength
= sizeof(struct UsbStdStrDesc
);
209 strdesc
->bDescriptorType
= UDT_STRING
;
210 ioreq
->iouh_Actual
= 2;
213 strdesc
->bString
[0] = AROS_WORD2LE(0x0409); // English (Yankee)
214 ioreq
->iouh_Actual
= sizeof(struct UsbStdStrDesc
);
217 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
218 return UHIOERR_NO_ERROR
;
221 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
222 return UHIOERR_BADPARAMS
; //CHECKME: Should we return stall?
226 roothubstring
= roothubstrings
[0];
230 if(unit
->roothub
.devdesc
.bcdUSB
== AROS_WORD2LE(0x0200)) {
231 roothubstring
= roothubstrings
[1];
233 roothubstring
= roothubstrings
[2];
238 roothubstring
= roothubstrings
[3];
242 roothubstring
= roothubstrings
[4];
246 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
247 return UHIOERR_BADPARAMS
; //CHECKME: Should we return stall?
251 UBYTE i
= strlen(roothubstring
);
253 strdesc
->bLength
= (i
*sizeof(strdesc
->bString
))+sizeof(strdesc
->bLength
)+sizeof(strdesc
->bDescriptorType
);
254 strdesc
->bDescriptorType
= UDT_STRING
;
255 ioreq
->iouh_Actual
= 2;
258 for(i
=0; i
<wLength
; i
++) {
259 strdesc
->bString
[i
] = AROS_WORD2LE((UWORD
)roothubstring
[i
]);
263 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
264 return UHIOERR_NO_ERROR
;
267 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
268 return UHIOERR_BADPARAMS
; //CHECKME: Should we return stall?
273 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
274 return UHIOERR_BADPARAMS
; //CHECKME: Should we return stall?
279 bmRequestType (URTF_OUT|URTF_STANDARD|URTF_DEVICE) 00000000B
280 bRequest SET_DESCRIPTOR
281 wValue Descriptor Type & Index
282 wIndex Zero or Language ID
283 wLength Descriptor Length
286 UWORD
SetDescriptor(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
287 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
288 mybug_unit(-1, ("Entering function\n"));
290 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
291 return UHIOERR_NO_ERROR
;
296 bmRequestType (URTF_IN|URTF_STANDARD|URTF_DEVICE) 10000000B
297 bRequest USR_GET_CONFIGURATION
301 Data Configuration Value
303 UWORD
GetConfiguration(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
304 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
305 mybug_unit(-1, ("Entering function\n"));
307 UWORD
*configurationvalue
;
308 configurationvalue
= ioreq
->iouh_Data
;
310 *configurationvalue
= unit
->roothub
.config
.cfgdesc
.bConfigurationValue
;
312 ioreq
->iouh_Actual
= wLength
;
314 mybug_unit(-1, ("GetConfiguration() %ld\n", configurationvalue
));
316 return UHIOERR_NO_ERROR
;
321 bmRequestType (URTF_OUT|URTF_STANDARD|URTF_DEVICE) 00000000B
322 bRequest USR_SET_CONFIGURATION
323 wValue Configuration Value
329 We have only one configuration, but implement some sanity still
330 If more than one configuration is specified we ignore the rest in GetDescriptor(UDT_CONFIGURATION)
333 UWORD
SetConfiguration(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
334 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
335 mybug_unit(-1, ("Entering function\n"));
337 mybug_unit(-1, ("SetConfiguration (configuration %d)\n", wValue
));
339 /* It is a Request Error if wValue, wIndex, or wLength are other than as specified above. */
340 if( (wValue
== unit
->roothub
.config
.cfgdesc
.bConfigurationValue
) && (!(wIndex
)) && (!(wLength
)) ) {
342 ioreq
->iouh_Actual
= wLength
;
344 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
345 return UHIOERR_NO_ERROR
;
348 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
349 return UHIOERR_BADPARAMS
;
352 /* Hub Class Requests */
356 bmRequestType (URTF_OUT|URTF_CLASS|URTF_DEVICE) 00100000B
357 bRequest USR_CLEAR_FEATURE
358 wValue Feature Selector
363 UWORD
ClearHubFeature(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
364 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
365 mybug_unit(-1, ("Entering function\n"));
367 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
368 return UHIOERR_NO_ERROR
;
373 bmRequestType (URTF_OUT|URTF_CLASS|URTF_OTHER) 00100011B
374 bRequest USR_CLEAR_FEATURE
375 wValue Feature Selector
376 wIndex (Selector|Port)
380 FIXME: Check what flags to set and clear on this and SetPortFeature
383 UWORD
ClearPortFeature(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
384 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
385 mybug_unit(-1, ("Entering function\n"));
387 mybug_unit(-1, ("Clearing feature 0x%02x on port %d\n",wValue
, (wIndex
& 0xff)));
389 if( ((!(wIndex
& 0xff)) || ((wIndex
& 0xff) > unit
->roothub
.hubdesc
.bNbrPorts
)) ) {
390 mybug_unit(-1, ("Port %ld out of range\n", (wIndex
& 0xff)));
391 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
392 return UHIOERR_BADPARAMS
;
396 case UFS_PORT_ENABLE
:
397 mybug_unit(-1, ("UFS_PORT_ENABLE\n"));
398 unit
->roothub
.portstatus
.wPortStatus
&= ~UPSF_PORT_ENABLE
;
401 case UFS_PORT_SUSPEND
:
402 mybug_unit(-1, ("UFS_PORT_SUSPEND\n"));
406 mybug_unit(-1, ("UFS_PORT_POWER\n"));
407 unit
->roothub
.portstatus
.wPortStatus
&= ~UPSF_PORT_POWER
;
410 case UFS_PORT_INDICATOR
:
411 mybug_unit(-1, ("UFS_PORT_INDICATOR\n"));
412 unit
->roothub
.portstatus
.wPortChange
&= ~UPSF_PORT_INDICATOR
;
415 case UFS_C_PORT_CONNECTION
:
416 mybug_unit(-1, ("UFS_C_PORT_CONNECTION\n"));
417 unit
->roothub
.portstatus
.wPortChange
&= ~UPSF_PORT_CONNECTION
;
420 case UFS_C_PORT_RESET
:
421 mybug_unit(-1, ("UFS_C_PORT_RESET\n"));
422 unit
->roothub
.portstatus
.wPortChange
&= ~UPSF_PORT_RESET
;
425 case UFS_C_PORT_ENABLE
:
426 mybug_unit(-1, ("UFS_C_PORT_ENABLE\n"));
427 unit
->roothub
.portstatus
.wPortChange
&= ~UPSF_PORT_ENABLE
;
430 case UFS_C_PORT_SUSPEND
:
431 mybug_unit(-1, ("UFS_C_PORT_SUSPEND\n"));
432 unit
->roothub
.portstatus
.wPortChange
&= ~UPSF_PORT_SUSPEND
;
435 case UFS_C_PORT_OVER_CURRENT
:
436 mybug_unit(-1, ("UFS_C_PORT_OVER_CURRENT\n"));
437 unit
->roothub
.portstatus
.wPortChange
&= ~UPSF_PORT_OVER_CURRENT
;
441 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
442 return UHIOERR_NO_ERROR
;
448 bmRequestType (URTF_OUT|URTF_CLASS|URTF_DEVICE) 00100000B
449 bRequest USR_CLEAR_TT_BUFFER
450 wValue Dev_Addr, EP_Num
458 UWORD
ClearTTBuffer(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
459 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
460 mybug_unit(-1, ("Entering function\n"));
462 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
463 return UHIOERR_NO_ERROR
;
468 bmRequestType (URTF_IN|URTF_CLASS|URTF_DEVICE) 10100000B
469 bRequest USR_GET_DESCRIPTOR
470 wValue Descriptor Type and Descriptor Index
471 wIndex Zero (or language ID)
472 wLength Descriptor Length
475 UWORD
GetHubDescriptor(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
476 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
477 mybug_unit(-1, ("Entering function\n"));
479 switch((wValue
>>8)) {
481 mybug_unit(-1, ("GetHubDescriptor UDT_HUB (length %ld)\n", wLength
));
483 ioreq
->iouh_Actual
= (wLength
> sizeof(struct UsbHubDesc
)) ? sizeof(struct UsbHubDesc
) : wLength
;
484 CopyMem((APTR
) &unit
->roothub
.hubdesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
486 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
487 return UHIOERR_NO_ERROR
;
492 mybug_unit(-1, ("GetHubDescriptor UDT_SSHUB (length %ld)\n", wLength));
494 ioreq->iouh_Actual = (wLength > sizeof(struct UsbHubSSDesc)) ? sizeof(struct UsbHubSSDesc) : wLength;
495 CopyMem((APTR) &unit->roothub.hubdesc, ioreq->iouh_Data, ioreq->iouh_Actual);
497 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
498 return UHIOERR_NO_ERROR;
503 return UHIOERR_BADPARAMS
;
508 bmRequestType (URTF_IN|URTF_CLASS|URTF_DEVICE) 10100000B
509 bRequest USR_GET_STATUS
513 Data Hub Status and Change Status
515 UWORD
GetHubStatus(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
516 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
517 mybug_unit(-1, ("Entering function\n"));
519 /* It is a Request Error if wValue, wIndex, or wLength are other than as specified above. */
520 if( (!(wValue
)) && (!(wIndex
)) && (wLength
== 4) ) {
522 struct UsbHubStatus
*usbhubstatus
= (struct UsbHubStatus
*) ioreq
->iouh_Data
;
524 usbhubstatus
->wHubStatus
= unit
->roothub
.hubstatus
.wHubStatus
;
525 usbhubstatus
->wHubChange
= unit
->roothub
.hubstatus
.wHubChange
;
527 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
528 return UHIOERR_NO_ERROR
;
531 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
532 return UHIOERR_BADPARAMS
;
537 bmRequestType (URTF_IN|URTF_CLASS|URTF_OTHER) 10100011B
538 bRequest USR_GET_STATUS
542 Data Port Status and Change Status
544 UWORD
GetPortStatus(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
545 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
546 mybug_unit(-1, ("Entering function\n"));
548 mybug_unit(-1, ("Port #%ld\n", wIndex
));
550 if( (wValue
) || (wLength
!= 4) || (!wIndex
) || (wIndex
> unit
->roothub
.hubdesc
.bNbrPorts
) ) {
551 mybug_unit(-1, ("Port %ld out of range\n", wIndex
));
552 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
553 return UHIOERR_BADPARAMS
;
556 struct UsbPortStatus
*usbportstatus
= (struct UsbPortStatus
*) ioreq
->iouh_Data
;
558 /* We have only one port per 'controller' */
559 usbportstatus
->wPortStatus
= unit
->roothub
.portstatus
.wPortStatus
;
560 usbportstatus
->wPortChange
= unit
->roothub
.portstatus
.wPortChange
;
562 mybug_unit(-1, ("usbportstatus->wPortStatus %01x\n", usbportstatus
->wPortStatus
));
563 mybug_unit(-1, ("usbportstatus->wPortChange %01x\n", usbportstatus
->wPortChange
));
565 if(usbportstatus
->wPortStatus
&UPSF_PORT_CONNECTION
) {
566 mybug_unit(-1, (" - UPSF_PORT_CONNECTION\n"));
569 if(usbportstatus
->wPortStatus
&UPSF_PORT_ENABLE
) {
570 mybug_unit(-1, (" - UPSF_PORT_ENABLE\n"));
573 if(usbportstatus
->wPortStatus
&UPSF_PORT_SUSPEND
) {
574 mybug_unit(-1, (" - UPSF_PORT_SUSPEND\n"));
577 if(usbportstatus
->wPortStatus
&UPSF_PORT_OVER_CURRENT
) {
578 mybug_unit(-1, (" - UPSF_PORT_OVER_CURRENT\n"));
581 if(usbportstatus
->wPortStatus
&UPSF_PORT_RESET
) {
582 mybug_unit(-1, (" - UPSF_PORT_RESET\n"));
585 if(usbportstatus
->wPortStatus
&UPSF_PORT_POWER
) {
586 mybug_unit(-1, (" - UPSF_PORT_POWER\n"));
589 if(usbportstatus
->wPortStatus
&UPSF_PORT_LOW_SPEED
) {
590 mybug_unit(-1, (" - UPSF_PORT_LOW_SPEED\n"));
593 if(usbportstatus
->wPortStatus
&UPSF_PORT_HIGH_SPEED
) {
594 mybug_unit(-1, (" - UPSF_PORT_HIGH_SPEED\n"));
597 if(usbportstatus
->wPortStatus
&UPSF_PORT_TEST_MODE
) {
598 mybug_unit(-1, (" - UPSF_PORT_TEST_MODE\n"));
601 if(usbportstatus
->wPortStatus
&UPSF_PORT_INDICATOR
) {
602 mybug_unit(-1, (" - UPSF_PORT_INDICATOR\n"));
605 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
606 return UHIOERR_NO_ERROR
;
611 bmRequestType (URTF_IN|URTF_CLASS|URTF_OTHER) 10100011B
612 bRequest USR_PORT_ERR_COUNT (Check: Has it been defined?)
616 Data Number of link errors on this port
618 UWORD
GetPortErrorCount(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
619 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
620 mybug_unit(-1, ("Entering function\n"));
622 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
623 return UHIOERR_NO_ERROR
;
628 bmRequestType (URTF_OUT|URTF_CLASS|URTF_OTHER) 00100011B
629 bRequest USR_RESET_TT
637 UWORD
ResetTT(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
638 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
639 mybug_unit(-1, ("Entering function\n"));
641 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
642 return UHIOERR_NO_ERROR
;
647 bmRequestType (URTF_OUT|URTF_CLASS|URTF_DEVICE) 00100000B
648 bRequest USR_SET_DESCRIPTOR
649 wValue Descriptor Type and Descriptor Index
650 wIndex Zero or Language ID
651 wLength Descriptor Length
654 UWORD
SetHubDescriptor(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
655 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
656 mybug_unit(-1, ("Entering function\n"));
658 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
659 return UHIOERR_NO_ERROR
;
664 bmRequestType (URTF_OUT|URTF_CLASS|URTF_DEVICE) 00100000B
665 bRequest USR_SET_FEATURE
666 wValue Feature Selector
671 UWORD
SetHubFeature(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
672 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
673 mybug_unit(-1, ("Entering function\n"));
675 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
676 return UHIOERR_NO_ERROR
;
681 bmRequestType (URTF_OUT|URTF_CLASS|URTF_DEVICE) 00100000B
682 bRequest USR_SET_HUB_DEPTH (Check: Has it been defined?)
688 UWORD
SetHubDepth(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
689 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
690 mybug_unit(-1, ("Entering function\n"));
692 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
693 return UHIOERR_NO_ERROR
;
698 bmRequestType (URTF_OUT|URTF_CLASS|URTF_OTHER) 00100011B
699 bRequest USR_SET_FEATURE
700 wValue Feature Selector
701 wIndex (Selector|Port)
704 FIXME: Check what flags to set and clear on this and ClearPortFeature
707 UWORD
SetPortFeature(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
708 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
709 mybug_unit(-1, ("Entering function\n"));
711 mybug_unit(-1, ("Setting feature 0x%02x on port %d\n",wValue
, (wIndex
& 0xff)));
713 if( ((!(wIndex
& 0xff)) || ((wIndex
& 0xff) > unit
->roothub
.hubdesc
.bNbrPorts
)) ) {
714 mybug_unit(-1, ("Port %ld out of range\n", (wIndex
& 0xff)));
715 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
716 return UHIOERR_BADPARAMS
;
721 /* Features that can be set with this request */
723 mybug_unit(-1, ("UFS_PORT_RESET\n"));
724 unit
->roothub
.portstatus
.wPortStatus
|= (UPSF_PORT_ENABLE
|UPSF_PORT_POWER
);
727 case UFS_PORT_SUSPEND
:
728 mybug_unit(-1, ("UFS_PORT_SUSPEND\n"));
732 mybug_unit(-1, ("UFS_PORT_POWER\n"));
733 unit
->roothub
.portstatus
.wPortStatus
|= UPSF_PORT_POWER
;
737 mybug_unit(-1, ("UFS_PORT_TEST\n"));
740 case UFS_PORT_INDICATOR
:
741 mybug_unit(-1, ("UFS_PORT_INDICATOR\n"));
744 /* Features that can be set with this request but are not required */
745 case UFS_C_PORT_CONNECTION
:
746 mybug_unit(-1, ("UFS_C_PORT_CONNECTION\n"));
749 case UFS_C_PORT_RESET
:
750 mybug_unit(-1, ("UFS_C_PORT_RESET\n"));
753 case UFS_C_PORT_ENABLE
:
754 mybug_unit(-1, ("UFS_C_PORT_ENABLE\n"));
757 case UFS_C_PORT_SUSPEND
:
758 mybug_unit(-1, ("UFS_C_PORT_SUSPEND\n"));
761 case UFS_C_PORT_OVER_CURRENT
:
762 mybug_unit(-1, ("UFS_C_PORT_OVER_CURRENT\n"));
766 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
767 return UHIOERR_BADPARAMS
;
772 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
773 return UHIOERR_NO_ERROR
;
778 bmRequestType (URTF_IN|URTF_CLASS|URTF_OTHER) 10100011B
779 bRequest USR_GET_TT_STATE
782 wLength TT State Length
787 UWORD
GetTTState(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
788 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
789 mybug_unit(-1, ("Entering function\n"));
791 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
792 return UHIOERR_NO_ERROR
;
797 bmRequestType (URTF_OUT|URTF_CLASS|URTF_OTHER) 00100011B
806 UWORD
StopTT(struct IOUsbHWReq
*ioreq
, UWORD wValue
, UWORD wIndex
, UWORD wLength
) {
807 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
808 mybug_unit(-1, ("Entering function\n"));
810 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
811 return UHIOERR_NO_ERROR
;
814 WORD
cmdControlXFerRootHub(struct IOUsbHWReq
*ioreq
) {
816 UWORD bmRequestType
= (ioreq
->iouh_SetupData
.bmRequestType
) & (URTF_STANDARD
| URTF_CLASS
| URTF_VENDOR
);
817 UWORD bmRequestDirection
= (ioreq
->iouh_SetupData
.bmRequestType
) & (URTF_IN
| URTF_OUT
);
818 UWORD bmRequestRecipient
= (ioreq
->iouh_SetupData
.bmRequestType
) & (URTF_DEVICE
| URTF_INTERFACE
| URTF_ENDPOINT
| URTF_OTHER
);
820 UWORD bRequest
= (ioreq
->iouh_SetupData
.bRequest
);
821 UWORD wValue
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wValue
);
822 UWORD wIndex
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
);
823 UWORD wLength
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wLength
);
825 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
827 /* Endpoint 0 is used for control transfers only and can not be assigned to any other function. */
828 if(ioreq
->iouh_Endpoint
!= 0) {
829 mybug_unit(-1, ("Wrong endpoint number! %ld\n", ioreq
->iouh_Endpoint
));
830 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
831 return UHIOERR_BADPARAMS
;
834 switch(((ULONG
)ioreq
->iouh_SetupData
.bmRequestType
<<16)|((ULONG
)ioreq
->iouh_SetupData
.bRequest
)) {
836 /* Standard Requests */
837 case (((URTF_IN
|URTF_STANDARD
|URTF_DEVICE
)<<16)|(USR_GET_STATUS
)):
838 return(GetStatus(ioreq
, wValue
, wIndex
, wLength
));
840 case (((URTF_IN
|URTF_STANDARD
|URTF_DEVICE
)<<16)|(USR_CLEAR_FEATURE
)):
841 return(ClearFeature(ioreq
, wValue
, wIndex
, wLength
));
843 case (((URTF_IN
|URTF_STANDARD
|URTF_DEVICE
)<<16)|(USR_SET_FEATURE
)):
844 return(SetFeature(ioreq
, wValue
, wIndex
, wLength
));
846 case ((((URTF_OUT
|URTF_STANDARD
|URTF_DEVICE
))<<16)|(USR_SET_ADDRESS
)):
847 return(SetAddress(ioreq
, wValue
, wIndex
, wLength
));
849 case (((URTF_IN
|URTF_STANDARD
|URTF_DEVICE
)<<16)|(USR_GET_DESCRIPTOR
)):
850 return(GetDescriptor(ioreq
, wValue
, wIndex
, wLength
));
852 case (((URTF_OUT
|URTF_STANDARD
|URTF_DEVICE
)<<16)|(USR_SET_DESCRIPTOR
)):
853 return(SetDescriptor(ioreq
, wValue
, wIndex
, wLength
));
855 case ((((URTF_OUT
|URTF_STANDARD
|URTF_DEVICE
))<<16)|(USR_GET_CONFIGURATION
)):
856 return(GetConfiguration(ioreq
, wValue
, wIndex
, wLength
));
858 case ((((URTF_OUT
|URTF_STANDARD
|URTF_DEVICE
))<<16)|(USR_SET_CONFIGURATION
)):
859 return(SetConfiguration(ioreq
, wValue
, wIndex
, wLength
));
861 /* Hub Class Requests. Check here if the command is for USB2 or USB3 hub... */
862 case (((URTF_OUT
|URTF_CLASS
|URTF_DEVICE
)<<16)|(USR_CLEAR_FEATURE
)):
863 return(ClearHubFeature(ioreq
, wValue
, wIndex
, wLength
));
865 case (((URTF_OUT
|URTF_CLASS
|URTF_OTHER
)<<16)|(USR_CLEAR_FEATURE
)):
866 return(ClearPortFeature(ioreq
, wValue
, wIndex
, wLength
));
868 case (((URTF_OUT
|URTF_CLASS
|URTF_DEVICE
)<<16)|(USR_SET_FEATURE
)):
869 return(SetHubFeature(ioreq
, wValue
, wIndex
, wLength
));
871 case (((URTF_OUT
|URTF_CLASS
|URTF_OTHER
)<<16)|(USR_SET_FEATURE
)):
872 return(SetPortFeature(ioreq
, wValue
, wIndex
, wLength
));
874 case (((URTF_IN
|URTF_CLASS
|URTF_DEVICE
)<<16)|(USR_GET_DESCRIPTOR
)):
875 return(GetHubDescriptor(ioreq
, wValue
, wIndex
, wLength
));
877 case ((((URTF_IN
|URTF_CLASS
|URTF_DEVICE
))<<16)|(USR_GET_STATUS
)):
878 return(GetHubStatus(ioreq
, wValue
, wIndex
, wLength
));
880 case ((((URTF_IN
|URTF_CLASS
|URTF_OTHER
))<<16)|(USR_GET_STATUS
)):
881 return(GetPortStatus(ioreq
, wValue
, wIndex
, wLength
));
883 // case (((( X ))<<16)|( X )):
884 // return( X (ioreq));
890 mybug_unit(-1, ("Nothing done!\n\n"));
891 return UHIOERR_BADPARAMS
;
894 WORD
cmdIntXFerRootHub(struct IOUsbHWReq
*ioreq
) {
895 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
897 mybug_unit(0, ("Entering function\n"));
899 if((ioreq
->iouh_Endpoint
!= 1) || (!ioreq
->iouh_Length
)) {
900 mybug_unit(-1, ("UHIOERR_BADPARAMS\n"));
901 return(UHIOERR_BADPARAMS
); // was UHIOERR_STALL
905 if(unit
->roothub
.portstatus
.wPortChange
) {
906 mybug_unit(-1, ("unit->roothub.portstatus.wPortChange = %02x\n", unit
->roothub
.portstatus
.wPortChange
));
907 *((UBYTE
*) ioreq
->iouh_Data
) = unit
->roothub
.portstatus
.wPortChange
;
908 ioreq
->iouh_Actual
= 1;
909 unit
->roothub
.portstatus
.wPortChange
&= ~UPSF_PORT_CONNECTION
;
910 mybug_unit(-1, ("unit->roothub.portstatus.wPortChange = %02x\n", unit
->roothub
.portstatus
.wPortChange
));
915 mybug_unit(0, ("ioreq added to roothub intrxfer_queue\n"));
917 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
918 ObtainSemaphore(&unit
->roothub
.intrxfer_queue_lock
);
919 AddTail(&unit
->roothub
.intrxfer_queue
, (struct Node
*) ioreq
);
920 ReleaseSemaphore(&unit
->roothub
.intrxfer_queue_lock
);
922 return(RC_DONTREPLY
);
926 WORD
cmdControlXFer(struct IOUsbHWReq
*ioreq
) {
927 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
929 mybug_unit(0, ("Entering function\n"));
931 mybug_unit(0, ("ioreq->iouh_DevAddr %lx\n", ioreq
->iouh_DevAddr
));
932 mybug_unit(0, ("unit->roothub.addr %lx\n", unit
->roothub
.addr
));
935 Check the status of the controller
936 We might encounter these states:
937 UHSB_OPERATIONAL USB can be used for transfers
938 UHSB_RESUMING USB is currently resuming
939 UHSB_SUSPENDED USB is in suspended state
940 UHSB_RESET USB is just inside a reset phase
943 if(unit
->state
== UHSF_OPERATIONAL
) {
944 mybug_unit(0, ("Unit state is operational\n"));
946 mybug_unit(-1, ("Unit state is not operational!\n"));
947 return UHIOERR_USBOFFLINE
;
950 if(ioreq
->iouh_DevAddr
== unit
->roothub
.addr
) {
951 return(cmdControlXFerRootHub(ioreq
));
954 mybug_unit(0, ("Sending transfer request to libusb\n\n"));
955 return(do_libusb_ctrl_transfer(ioreq
));
958 WORD
cmdIntXFer(struct IOUsbHWReq
*ioreq
) {
959 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
961 mybug_unit(0, ("Entering function\n"));
963 mybug_unit(0, ("ioreq->iouh_DevAddr %lx\n", ioreq
->iouh_DevAddr
));
964 mybug_unit(0, ("unit->roothub.addr %lx\n", unit
->roothub
.addr
));
967 Check the status of the controller
968 We might encounter these states:
969 UHSB_OPERATIONAL USB can be used for transfers
970 UHSB_RESUMING USB is currently resuming
971 UHSB_SUSPENDED USB is in suspended state
972 UHSB_RESET USB is just inside a reset phase
975 if(unit
->state
== UHSF_OPERATIONAL
) {
976 mybug_unit(0, ("Unit state is operational\n"));
978 mybug_unit(-1, ("Unit state is not operational!\n"));
979 return UHIOERR_USBOFFLINE
;
982 if(ioreq
->iouh_DevAddr
== unit
->roothub
.addr
) {
983 return(cmdIntXFerRootHub(ioreq
));
986 mybug_unit(0, ("Adding INTR transfer request to queue\n"));
987 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
988 ioreq
->iouh_Actual
= 0;
990 ObtainSemaphore(&unit
->intrxfer_queue_lock
);
991 AddTail(&unit
->intrxfer_queue
, (struct Node
*) ioreq
);
992 ReleaseSemaphore(&unit
->intrxfer_queue_lock
);
994 return(RC_DONTREPLY
);
997 WORD
cmdBulkXFer(struct IOUsbHWReq
*ioreq
) {
998 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
1000 mybug_unit(0, ("Entering function\n"));
1002 mybug_unit(0, ("ioreq->iouh_DevAddr %lx\n", ioreq
->iouh_DevAddr
));
1003 mybug_unit(0, ("unit->roothub.addr %lx\n", unit
->roothub
.addr
));
1006 Check the status of the controller
1007 We might encounter these states:
1008 UHSB_OPERATIONAL USB can be used for transfers
1009 UHSB_RESUMING USB is currently resuming
1010 UHSB_SUSPENDED USB is in suspended state
1011 UHSB_RESET USB is just inside a reset phase
1014 if(unit
->state
== UHSF_OPERATIONAL
) {
1015 mybug_unit(0, ("Unit state is operational\n"));
1017 mybug_unit(-1, ("Unit state is not operational!\n"));
1018 return UHIOERR_USBOFFLINE
;
1021 mybug_unit(0, ("Adding BULK transfer request to queue\n"));
1022 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1023 ioreq
->iouh_Actual
= 0;
1025 ObtainSemaphore(&unit
->bulkxfer_queue_lock
);
1026 AddTail(&unit
->bulkxfer_queue
, (struct Node
*) ioreq
);
1027 ReleaseSemaphore(&unit
->bulkxfer_queue_lock
);
1029 return(RC_DONTREPLY
);
1032 WORD
cmdISOXFer(struct IOUsbHWReq
*ioreq
) {
1033 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
1035 mybug_unit(0, ("Entering function\n"));
1037 mybug_unit(0, ("ioreq->iouh_DevAddr %lx\n", ioreq
->iouh_DevAddr
));
1038 mybug_unit(0, ("unit->roothub.addr %lx\n", unit
->roothub
.addr
));
1041 Check the status of the controller
1042 We might encounter these states:
1043 UHSB_OPERATIONAL USB can be used for transfers
1044 UHSB_RESUMING USB is currently resuming
1045 UHSB_SUSPENDED USB is in suspended state
1046 UHSB_RESET USB is just inside a reset phase
1049 if(unit
->state
== UHSF_OPERATIONAL
) {
1050 mybug_unit(0, ("Unit state is operational\n"));
1052 mybug_unit(-1, ("Unit state is not operational!\n"));
1053 return UHIOERR_USBOFFLINE
;
1056 mybug_unit(0, ("Adding ISOC transfer request to queue\n"));
1057 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1058 ioreq
->iouh_Actual
= 0;
1060 ObtainSemaphore(&unit
->isocxfer_queue_lock
);
1061 AddTail(&unit
->isocxfer_queue
, (struct Node
*) ioreq
);
1062 ReleaseSemaphore(&unit
->isocxfer_queue_lock
);
1064 return(RC_DONTREPLY
);
1067 void uhwCheckRootHubChanges(struct VUSBHCIUnit
*unit
) {
1068 mybug_unit(0, ("Entering function\n"));
1070 mybug_unit(0, ("usbportstatus->wPortStatus %01x\n", unit
->roothub
.portstatus
.wPortStatus
));
1071 mybug_unit(0, ("usbportstatus->wPortChange %01x\n", unit
->roothub
.portstatus
.wPortChange
));
1073 struct IOUsbHWReq
*ioreq
;
1075 ObtainSemaphore(&unit
->roothub
.intrxfer_queue_lock
);
1076 if(unit
->roothub
.portstatus
.wPortChange
&& unit
->roothub
.intrxfer_queue
.lh_Head
->ln_Succ
) {
1077 ioreq
= (struct IOUsbHWReq
*) unit
->roothub
.intrxfer_queue
.lh_Head
;
1078 while(((struct Node
*) ioreq
)->ln_Succ
) {
1079 Remove(&ioreq
->iouh_Req
.io_Message
.mn_Node
);
1081 *((UBYTE
*) ioreq
->iouh_Data
) = (1<<1);
1082 ioreq
->iouh_Actual
= 1;
1084 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
1085 ioreq
= (struct IOUsbHWReq
*) unit
->roothub
.intrxfer_queue
.lh_Head
;
1089 ReleaseSemaphore(&unit
->roothub
.intrxfer_queue_lock
);