- Inserted some USB3 hub class request skeletons
[AROS.git] / rom / usb / vusbhc / vusbhci_commands.c
blob90bcbdb114598b161c5951a864499487f4873a06
1 /*
2 Copyright © 2015-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: VUSBHCI USB host controller
6 Lang: English
7 */
9 #ifdef DEBUG
10 #undef DEBUG
11 #endif
12 #define DEBUG 1
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);
41 return TRUE;
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"));
54 return RC_OK;
57 /* Standard Requests */
60 GetStatus:
61 bmRequestType (URTF_IN|URTF_STANDARD|URTF_DEVICE) 10000000B
62 bRequest USR_GET_STATUS
63 wValue Zero
64 wIndex Zero
65 wLength Two
66 Data Device 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"));
75 UWORD *devicestatus;
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;
89 ClearFeature:
90 bmRequestType (URTF_IN|URTF_STANDARD|URTF_DEVICE) 00000000B
91 bRequest CLEAR_FEATURE
92 wValue Feature Selector
93 wIndex Zero
94 wLength Zero
95 Data None
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;
106 SetFeature:
107 bmRequestType (URTF_IN|URTF_STANDARD|URTF_DEVICE) 00000000B
108 bRequest SET_FEATURE
109 wValue Feature Selector
110 wIndex Zero
111 wLength Zero
112 Data None
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;
123 SetAddress:
124 bmRequestType (URTF_OUT|URTF_STANDARD|URTF_DEVICE) 00000000B
125 bRequest USR_SET_ADDRESS
126 wValue Device Address
127 wIndex Zero
128 wLength Zero
129 Data None
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;
152 GetDescriptor:
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
158 Data Descriptor
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" };
166 UBYTE index;
168 switch((wValue>>8)) {
169 case UDT_DEVICE:
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;
177 break;
179 case UDT_CONFIGURATION:
180 index = (wValue & 0xff);
182 mybug_unit(-1, ("GetDeviceDescriptor UDT_CONFIGURATION (configuration %d, length %ld)\n",index, wLength));
184 if(index == 0) {
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;
196 break;
198 case UDT_STRING:
199 index = (wValue & 0xff);
201 mybug_unit(-1, ("GetStringDescriptor UDT_STRING (index %d)\n", index));
203 struct UsbStdStrDesc *strdesc = (struct UsbStdStrDesc *) ioreq->iouh_Data;
205 switch(index) {
206 case 0:
207 if(wLength > 1) {
208 strdesc->bLength = sizeof(struct UsbStdStrDesc);
209 strdesc->bDescriptorType = UDT_STRING;
210 ioreq->iouh_Actual = 2;
212 if(wLength > 3) {
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?
223 break;
225 case 1:
226 roothubstring = roothubstrings[0];
227 break;
229 case 2:
230 if(unit->roothub.devdesc.bcdUSB == AROS_WORD2LE(0x0200)) {
231 roothubstring = roothubstrings[1];
232 } else {
233 roothubstring = roothubstrings[2];
235 break;
237 case 3:
238 roothubstring = roothubstrings[3];
239 break;
241 case 4:
242 roothubstring = roothubstrings[4];
243 break;
245 default:
246 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
247 return UHIOERR_BADPARAMS; //CHECKME: Should we return stall?
250 if(wLength > 1) {
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;
257 if(wLength > 3) {
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?
269 break;
273 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
274 return UHIOERR_BADPARAMS; //CHECKME: Should we return stall?
278 SetDescriptor:
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
284 Data Descriptor
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;
295 GetConfiguration:
296 bmRequestType (URTF_IN|URTF_STANDARD|URTF_DEVICE) 10000000B
297 bRequest USR_GET_CONFIGURATION
298 wValue Zero
299 wIndex Zero
300 wLength 1
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;
320 SetConfiguration:
321 bmRequestType (URTF_OUT|URTF_STANDARD|URTF_DEVICE) 00000000B
322 bRequest USR_SET_CONFIGURATION
323 wValue Configuration Value
324 wIndex Zero
325 wLength Zero
326 Data None
328 Note:
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 */
355 ClearHubFeature:
356 bmRequestType (URTF_OUT|URTF_CLASS|URTF_DEVICE) 00100000B
357 bRequest USR_CLEAR_FEATURE
358 wValue Feature Selector
359 wIndex Zero
360 wLength Zero
361 Data None
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;
372 ClearPortFeature:
373 bmRequestType (URTF_OUT|URTF_CLASS|URTF_OTHER) 00100011B
374 bRequest USR_CLEAR_FEATURE
375 wValue Feature Selector
376 wIndex (Selector|Port)
377 wLength Zero
378 Data None
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;
395 switch(wValue) {
396 case UFS_PORT_ENABLE:
397 mybug_unit(-1, ("UFS_PORT_ENABLE\n"));
398 unit->roothub.portstatus.wPortStatus &= ~UPSF_PORT_ENABLE;
399 break;
401 case UFS_PORT_SUSPEND:
402 mybug_unit(-1, ("UFS_PORT_SUSPEND\n"));
403 break;
405 case UFS_PORT_POWER:
406 mybug_unit(-1, ("UFS_PORT_POWER\n"));
407 unit->roothub.portstatus.wPortStatus &= ~UPSF_PORT_POWER;
408 break;
410 case UFS_PORT_INDICATOR:
411 mybug_unit(-1, ("UFS_PORT_INDICATOR\n"));
412 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_INDICATOR;
413 break;
415 case UFS_C_PORT_CONNECTION:
416 mybug_unit(-1, ("UFS_C_PORT_CONNECTION\n"));
417 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_CONNECTION;
418 break;
420 case UFS_C_PORT_RESET:
421 mybug_unit(-1, ("UFS_C_PORT_RESET\n"));
422 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_RESET;
423 break;
425 case UFS_C_PORT_ENABLE:
426 mybug_unit(-1, ("UFS_C_PORT_ENABLE\n"));
427 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_ENABLE;
428 break;
430 case UFS_C_PORT_SUSPEND:
431 mybug_unit(-1, ("UFS_C_PORT_SUSPEND\n"));
432 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_SUSPEND;
433 break;
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;
438 break;
441 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
442 return UHIOERR_NO_ERROR;
447 ClearTTBuffer:
448 bmRequestType (URTF_OUT|URTF_CLASS|URTF_DEVICE) 00100000B
449 bRequest USR_CLEAR_TT_BUFFER
450 wValue Dev_Addr, EP_Num
451 wIndex TT_port
452 wLength Zero
453 Data None
455 Not for USB3
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;
467 GetHubDescriptor:
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
473 Data Descriptor
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)) {
480 case UDT_HUB:
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;
488 break;
491 case UDT_SSHUB:
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;
499 break;
503 return UHIOERR_BADPARAMS;
507 GetHubStatus:
508 bmRequestType (URTF_IN|URTF_CLASS|URTF_DEVICE) 10100000B
509 bRequest USR_GET_STATUS
510 wValue Zero
511 wIndex Zero
512 wLength Four
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;
536 GetPortStatus:
537 bmRequestType (URTF_IN|URTF_CLASS|URTF_OTHER) 10100011B
538 bRequest USR_GET_STATUS
539 wValue Zero
540 wIndex Port
541 wLength Four
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;
610 GetPortErrorCount:
611 bmRequestType (URTF_IN|URTF_CLASS|URTF_OTHER) 10100011B
612 bRequest USR_PORT_ERR_COUNT (Check: Has it been defined?)
613 wValue Zero
614 wIndex Port
615 wLength Two
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;
627 ResetTT:
628 bmRequestType (URTF_OUT|URTF_CLASS|URTF_OTHER) 00100011B
629 bRequest USR_RESET_TT
630 wValue Zero
631 wIndex Port
632 wLength Zero
633 Data None
635 Not for USB3
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;
646 SetHubDescriptor:
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
652 Data Descriptor
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;
663 SetHubFeature:
664 bmRequestType (URTF_OUT|URTF_CLASS|URTF_DEVICE) 00100000B
665 bRequest USR_SET_FEATURE
666 wValue Feature Selector
667 wIndex Zero
668 wLength Zero
669 Data None
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;
680 SetHubDescriptor:
681 bmRequestType (URTF_OUT|URTF_CLASS|URTF_DEVICE) 00100000B
682 bRequest USR_SET_HUB_DEPTH (Check: Has it been defined?)
683 wValue Hub Depth
684 wIndex Zero
685 wLength Zero
686 Data None
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;
697 SetPortFeature:
698 bmRequestType (URTF_OUT|URTF_CLASS|URTF_OTHER) 00100011B
699 bRequest USR_SET_FEATURE
700 wValue Feature Selector
701 wIndex (Selector|Port)
702 wLength Zero
703 Data None
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;
719 switch(wValue) {
721 /* Features that can be set with this request */
722 case UFS_PORT_RESET:
723 mybug_unit(-1, ("UFS_PORT_RESET\n"));
724 unit->roothub.portstatus.wPortStatus |= (UPSF_PORT_ENABLE|UPSF_PORT_POWER);
725 break;
727 case UFS_PORT_SUSPEND:
728 mybug_unit(-1, ("UFS_PORT_SUSPEND\n"));
729 break;
731 case UFS_PORT_POWER:
732 mybug_unit(-1, ("UFS_PORT_POWER\n"));
733 unit->roothub.portstatus.wPortStatus |= UPSF_PORT_POWER;
734 break;
736 case UFS_PORT_TEST:
737 mybug_unit(-1, ("UFS_PORT_TEST\n"));
738 break;
740 case UFS_PORT_INDICATOR:
741 mybug_unit(-1, ("UFS_PORT_INDICATOR\n"));
742 break;
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"));
747 break;
749 case UFS_C_PORT_RESET:
750 mybug_unit(-1, ("UFS_C_PORT_RESET\n"));
751 break;
753 case UFS_C_PORT_ENABLE:
754 mybug_unit(-1, ("UFS_C_PORT_ENABLE\n"));
755 break;
757 case UFS_C_PORT_SUSPEND:
758 mybug_unit(-1, ("UFS_C_PORT_SUSPEND\n"));
759 break;
761 case UFS_C_PORT_OVER_CURRENT:
762 mybug_unit(-1, ("UFS_C_PORT_OVER_CURRENT\n"));
763 break;
765 default:
766 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
767 return UHIOERR_BADPARAMS;
768 break;
772 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
773 return UHIOERR_NO_ERROR;
777 GetTTState:
778 bmRequestType (URTF_IN|URTF_CLASS|URTF_OTHER) 10100011B
779 bRequest USR_GET_TT_STATE
780 wValue TT_Flags
781 wIndex Port
782 wLength TT State Length
783 Data TT State
785 Not for USB3
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;
796 StopTT:
797 bmRequestType (URTF_OUT|URTF_CLASS|URTF_OTHER) 00100011B
798 bRequest USR_STOP_TT
799 wValue Zero
800 wIndex Port
801 wLength Zero
802 Data None
804 Not for USB3
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));
886 default:
887 break;
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
904 #if 0
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));
911 return(0);
913 #endif
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"));
945 } else {
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"));
977 } else {
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"));
1016 } else {
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"));
1051 } else {
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);