Added new calls to libusb
[AROS.git] / rom / usb / vusbhc / vusbhci_commands.c
blobac82053bb5c9da56fcefb2c70394c59d2f78ae72
1 /*
2 Copyright © 2015, 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"
29 BOOL cmdAbortIO(struct IOUsbHWReq *ioreq) {
30 ioreq->iouh_Req.io_Error = IOERR_ABORTED;
31 ioreq->iouh_Req.io_Message.mn_Node.ln_Type = NT_FREEMSG;
33 /* If not quick I/O, reply the message */
34 if (!(ioreq->iouh_Req.io_Flags & IOF_QUICK)) {
35 ReplyMsg(&ioreq->iouh_Req.io_Message);
38 return TRUE;
41 WORD cmdUsbReset(struct IOUsbHWReq *ioreq) {
42 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
44 mybug_unit(0, ("Entering function\n"));
46 /* We should do a proper reset sequence with a real driver */
47 unit->state = UHSF_RESET;
48 unit->roothub.addr = 0;
49 unit->state = UHSF_OPERATIONAL;
50 mybug_unit(0, ("Done\n\n"));
51 return RC_OK;
55 D7 Data Phase Transfer Direction
56 0 = Host to Device
57 1 = Device to Host
58 D6..5 Type
59 0 = Standard
60 1 = Class
61 2 = Vendor
62 3 = Reserved
63 D4..0 Recipient
64 0 = Device
65 1 = Interface
66 2 = Endpoint
67 3 = Other
68 4..31 = Reserved
70 #define URTF_OUT 0x00 // direction: host to device
71 #define URTF_IN 0x80 // direction: device to host
73 #define URTF_STANDARD 0x00 // type: usb standard request
74 #define URTF_CLASS 0x20 // type: class request
75 #define URTF_VENDOR 0x40 // type: vendor specific request
77 #define URTF_DEVICE 0x00 // target: device
78 #define URTF_INTERFACE 0x01 // target: interface
79 #define URTF_ENDPOINT 0x02 // target: endpoint
80 #define URTF_OTHER 0x03 // target: other
83 /* Standard Requests */
85 SetAddress:
86 bmRequestType (URTF_OUT|URTF_STANDARD|URTF_DEVICE) 00000000B
87 bRequest USR_SET_ADDRESS
88 wValue Device Address
89 wIndex Zero
90 wLength Zero
91 Data None
93 UWORD SetAddress(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
94 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
95 mybug_unit(-1, ("Entering function\n"));
97 mybug_unit(-1, ("SetAddress (address %d)\n", wValue));
99 /* It is a Request Error if wValue, wIndex, or wLength are other than as specified above. */
100 if( (wValue) && (!(wIndex)) && (!(wLength)) ) {
102 unit->roothub.addr = wValue;
103 ioreq->iouh_Actual = wLength;
105 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
106 return UHIOERR_NO_ERROR;
109 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
110 return UHIOERR_BADPARAMS;
114 SetConfiguration:
115 bmRequestType (URTF_OUT|URTF_STANDARD|URTF_DEVICE) 00000000B
116 bRequest USR_SET_CONFIGURATION
117 wValue Configuration Value
118 wIndex Zero
119 wLength Zero
120 Data None
122 Note:
123 We have only one configuration, but implement some sanity still
124 If more than one configuration is specified we ignore the rest in GetDescriptor(UDT_CONFIGURATION)
127 UWORD SetConfiguration(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
128 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
129 mybug_unit(-1, ("Entering function\n"));
131 mybug_unit(-1, ("SetConfiguration (configuration %d)\n", wValue));
133 /* It is a Request Error if wValue, wIndex, or wLength are other than as specified above. */
134 if( (wValue) && (wValue<=unit->roothub.devdesc.bNumConfigurations) && (!(wIndex)) && (!(wLength)) ) {
136 ioreq->iouh_Actual = wLength;
138 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
139 return UHIOERR_NO_ERROR;
142 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
143 return UHIOERR_BADPARAMS;
147 GetStatus:
148 bmRequestType (URTF_IN|URTF_STANDARD|URTF_DEVICE) 10000000B
149 bRequest USR_GET_STATUS
150 wValue Zero
151 wIndex Zero
152 wLength Two
153 Data None
155 UWORD GetStatus(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
156 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
157 mybug_unit(-1, ("Entering function\n"));
159 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
160 return UHIOERR_NO_ERROR;
164 GetDescriptor:
166 UWORD GetDescriptor(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
167 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
168 mybug_unit(-1, ("Entering function\n"));
170 CONST_STRPTR roothubstring = NULL;
171 CONST_STRPTR roothubstrings[] = {"The AROS Development Team.", "VUSBHCI root hub (USB2.00)", "VUSBHCI root hub (USB3.00)", "Standard Config", "Hub interface" };
172 UBYTE index;
174 switch((wValue>>8)) {
175 case UDT_DEVICE:
176 mybug_unit(-1, ("GetDeviceDescriptor UDT_DEVICE (length %ld)\n", wLength));
178 ioreq->iouh_Actual = (wLength > sizeof(struct UsbStdDevDesc)) ? sizeof(struct UsbStdDevDesc) : wLength;
179 CopyMem((APTR) &unit->roothub.devdesc, ioreq->iouh_Data, ioreq->iouh_Actual);
181 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
182 return UHIOERR_NO_ERROR;
183 break;
185 case UDT_CONFIGURATION:
186 index = (wValue & 0xff);
188 mybug_unit(-1, ("GetDeviceDescriptor UDT_CONFIGURATION (configuration %d, length %ld)\n",index, wLength));
190 if(index == 0) {
192 ioreq->iouh_Actual = (wLength > sizeof(struct RHConfig)) ? sizeof(struct RHConfig) : wLength;
193 CopyMem((APTR) &unit->roothub.config, ioreq->iouh_Data, ioreq->iouh_Actual);
195 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
196 return UHIOERR_NO_ERROR;
199 mybug_unit(-1, ("Our roothub supports only one configuration\n"));
200 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
201 return UHIOERR_BADPARAMS;
202 break;
204 case UDT_STRING:
205 index = (wValue & 0xff);
207 mybug_unit(-1, ("GetStringDescriptor UDT_STRING (index %d)\n", index));
209 struct UsbStdStrDesc *strdesc = (struct UsbStdStrDesc *) ioreq->iouh_Data;
211 switch(index) {
212 case 0:
213 if(wLength > 1) {
214 strdesc->bLength = sizeof(struct UsbStdStrDesc);
215 strdesc->bDescriptorType = UDT_STRING;
216 ioreq->iouh_Actual = 2;
218 if(wLength > 3) {
219 strdesc->bString[0] = AROS_WORD2LE(0x0409); // English (Yankee)
220 ioreq->iouh_Actual = sizeof(struct UsbStdStrDesc);
223 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
224 return UHIOERR_NO_ERROR;
227 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
228 return UHIOERR_BADPARAMS; //CHECKME: Should we return stall?
229 break;
231 case 1:
232 roothubstring = roothubstrings[0];
233 break;
235 case 2:
236 if(unit->roothub.devdesc.bcdUSB == AROS_WORD2LE(0x0200)) {
237 roothubstring = roothubstrings[1];
238 } else {
239 roothubstring = roothubstrings[2];
241 break;
243 case 3:
244 roothubstring = roothubstrings[3];
245 break;
247 case 4:
248 roothubstring = roothubstrings[4];
249 break;
251 default:
252 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
253 return UHIOERR_BADPARAMS; //CHECKME: Should we return stall?
256 if(wLength > 1) {
257 UBYTE i = strlen(roothubstring);
259 strdesc->bLength = (i*sizeof(strdesc->bString))+sizeof(strdesc->bLength)+sizeof(strdesc->bDescriptorType);
260 strdesc->bDescriptorType = UDT_STRING;
261 ioreq->iouh_Actual = 2;
263 if(wLength > 3) {
264 for(i=0; i<wLength; i++) {
265 strdesc->bString[i] = AROS_WORD2LE((UWORD)roothubstring[i]);
269 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
270 return UHIOERR_NO_ERROR;
273 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
274 return UHIOERR_BADPARAMS; //CHECKME: Should we return stall?
275 break;
279 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
280 return UHIOERR_BADPARAMS; //CHECKME: Should we return stall?
284 SetDescriptor:
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 //while(1);
292 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
293 return UHIOERR_NO_ERROR;
297 /* Hub Class Requests */
299 ClearHubFeature:
300 bmRequestType (URTF_OUT|URTF_CLASS|URTF_DEVICE) 00100000B
301 bRequest USR_CLEAR_FEATURE
302 wValue Feature Selector
303 wIndex Zero
304 wLength Zero
305 Data None
307 Usb Hub Feature Selectors
308 #define UFS_C_HUB_LOCAL_POWER 0x00
309 #define UFS_C_HUB_OVER_CURRENT 0x01
310 #define UFS_PORT_CONNECTION 0x00
311 #define UFS_PORT_ENABLE 0x01
312 #define UFS_PORT_SUSPEND 0x02
313 #define UFS_PORT_OVER_CURRENT 0x03
314 #define UFS_PORT_RESET 0x04
315 #define UFS_PORT_POWER 0x08
316 #define UFS_PORT_LOW_SPEED 0x09
317 #define UFS_C_PORT_CONNECTION 0x10
318 #define UFS_C_PORT_ENABLE 0x11
319 #define UFS_C_PORT_SUSPEND 0x12
320 #define UFS_C_PORT_OVER_CURRENT 0x13
321 #define UFS_C_PORT_RESET 0x14
322 #define UFS_PORT_TEST 0x15
323 #define UFS_PORT_INDICATOR 0x16
326 UWORD ClearHubFeature(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
327 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
328 mybug_unit(-1, ("Entering function\n"));
330 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
331 return UHIOERR_NO_ERROR;
335 SetHubFeature:
336 bmRequestType (URTF_OUT|URTF_CLASS|URTF_DEVICE) 00100000B
337 bRequest USR_SET_FEATURE
338 wValue Feature Selector
339 wIndex Zero
340 wLength Zero
341 Data None
343 UWORD SetHubFeature(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
344 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
345 mybug_unit(-1, ("Entering function\n"));
347 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
348 return UHIOERR_NO_ERROR;
352 ClearTTBuffer:
354 UWORD ClearTTBuffer(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
355 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
356 mybug_unit(-1, ("Entering function\n"));
358 return UHIOERR_NO_ERROR;
362 GetHubDescriptor: (URTF_IN|URTF_CLASS|URTF_DEVICE) 10100000B
364 UWORD GetHubDescriptor(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
365 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
366 mybug_unit(-1, ("Entering function\n"));
368 switch((wValue>>8)) {
369 case UDT_HUB:
370 mybug_unit(-1, ("GetHubDescriptor UDT_HUB (length %ld)\n", wLength));
372 ioreq->iouh_Actual = (wLength > sizeof(struct UsbHubDesc)) ? sizeof(struct UsbHubDesc) : wLength;
373 CopyMem((APTR) &unit->roothub.hubdesc, ioreq->iouh_Data, ioreq->iouh_Actual);
375 //unit->roothub.hubdesc.PortPwrCtrlMask = (1<<1);
376 //unit->roothub.hubdesc.DeviceRemovable = 0;
377 //unit->roothub.hubdesc.PortPwrCtrlMask = (1<<(1+2))-2;
379 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
380 return UHIOERR_NO_ERROR;
381 break;
383 case UDT_SSHUB:
384 mybug_unit(-1, ("GetHubDescriptor UDT_SSHUB (length %ld)\n", wLength));
386 ioreq->iouh_Actual = (wLength > sizeof(struct UsbHubDesc)) ? sizeof(struct UsbHubDesc) : wLength;
387 CopyMem((APTR) &unit->roothub.hubdesc, ioreq->iouh_Data, ioreq->iouh_Actual);
389 //unit->roothub.hubdesc.PortPwrCtrlMask = (1<<1);
390 //unit->roothub.hubdesc.DeviceRemovable = 0;
391 //unit->roothub.hubdesc.PortPwrCtrlMask = (1<<(1+2))-2;
393 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
394 return UHIOERR_NO_ERROR;
395 break;
397 } /* switch( (wValue>>8) ) */
399 return UHIOERR_BADPARAMS;
403 GetHubStatus:
404 bmRequestType (URTF_IN|URTF_CLASS|URTF_DEVICE) 10100000B
405 bRequest USR_GET_STATUS
406 wValue Zero
407 wIndex Zero
408 wLength Four
409 Data Hub Status and Change Status
411 UWORD GetHubStatus(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
412 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
413 mybug_unit(-1, ("Entering function\n"));
415 /* It is a Request Error if wValue, wIndex, or wLength are other than as specified above. */
416 if( (!(wValue)) && (!(wIndex)) && (wLength == 4) ) {
418 struct UsbHubStatus *usbhubstatus = (struct UsbHubStatus *) ioreq->iouh_Data;
420 usbhubstatus->wHubStatus = unit->roothub.hubstatus.wHubStatus;
421 usbhubstatus->wHubChange = unit->roothub.hubstatus.wHubChange;
423 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
424 return UHIOERR_NO_ERROR;
427 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
428 return UHIOERR_BADPARAMS;
432 GetPortStatus:
433 bmRequestType (URTF_IN|URTF_CLASS|URTF_OTHER) 10100011B
434 bRequest USR_GET_STATUS
435 wValue Zero
436 wIndex Port
437 wLength Four
438 Data Port Status and Change Status
440 UWORD GetPortStatus(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
441 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
442 mybug_unit(-1, ("Entering function\n"));
444 if( (!wIndex) || (wIndex > unit->roothub.hubdesc.bNbrPorts) ) {
445 mybug_unit(-1, ("Port %ld out of range\n", wIndex));
446 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
447 return UHIOERR_BADPARAMS;
450 /* FIXME: Check wLength */
452 struct UsbPortStatus *usbportstatus = (struct UsbPortStatus *) ioreq->iouh_Data;
454 /* Fake connection */
455 //unit->roothub.portstatus.wPortStatus |= AROS_WORD2LE(UPSF_PORT_CONNECTION);
456 //unit->roothub.portstatus.wPortChange |= AROS_WORD2LE(UPSF_PORT_CONNECTION);
458 /* We have only one port per 'controller' */
459 usbportstatus->wPortStatus = unit->roothub.portstatus.wPortStatus;
460 usbportstatus->wPortChange = unit->roothub.portstatus.wPortChange;
462 mybug_unit(-1, ("usbportstatus->wPortStatus %01x\n", usbportstatus->wPortStatus));
464 if(usbportstatus->wPortStatus&UPSF_PORT_CONNECTION) {
465 mybug_unit(-1, (" - UPSF_PORT_CONNECTION\n"));
468 if(usbportstatus->wPortStatus&UPSF_PORT_ENABLE) {
469 mybug_unit(-1, (" - UPSF_PORT_ENABLE\n"));
472 if(usbportstatus->wPortStatus&UPSF_PORT_SUSPEND) {
473 mybug_unit(-1, (" - UPSF_PORT_SUSPEND\n"));
476 if(usbportstatus->wPortStatus&UPSF_PORT_OVER_CURRENT) {
477 mybug_unit(-1, (" - UPSF_PORT_OVER_CURRENT\n"));
480 if(usbportstatus->wPortStatus&UPSF_PORT_RESET) {
481 mybug_unit(-1, (" - UPSF_PORT_RESET\n"));
484 if(usbportstatus->wPortStatus&UPSF_PORT_POWER) {
485 mybug_unit(-1, (" - UPSF_PORT_POWER\n"));
488 if(usbportstatus->wPortStatus&UPSF_PORT_LOW_SPEED) {
489 mybug_unit(-1, (" - UPSF_PORT_LOW_SPEED\n"));
492 if(usbportstatus->wPortStatus&UPSF_PORT_HIGH_SPEED) {
493 mybug_unit(-1, (" - UPSF_PORT_HIGH_SPEED\n"));
496 if(usbportstatus->wPortStatus&UPSF_PORT_TEST_MODE) {
497 mybug_unit(-1, (" - UPSF_PORT_TEST_MODE\n"));
500 if(usbportstatus->wPortStatus&UPSF_PORT_INDICATOR) {
501 mybug_unit(-1, (" - UPSF_PORT_INDICATOR\n"));
504 mybug_unit(-1, ("usbportstatus->wPortChange %01x\n", usbportstatus->wPortChange));
506 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
507 return UHIOERR_NO_ERROR;
512 UWORD ResetTT(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
513 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
514 mybug_unit(-1, ("Entering function\n"));
516 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
517 return UHIOERR_NO_ERROR;
522 UWORD SetHubDescriptor(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
523 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
524 mybug_unit(-1, ("Entering function\n"));
526 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
527 return UHIOERR_NO_ERROR;
531 SetPortFeature:
532 bmRequestType (URTF_OUT|URTF_CLASS|URTF_OTHER) 00100011B
533 bRequest USR_SET_FEATURE
534 wValue Feature Selector
535 wIndex (Selector|Port)
536 wLength Zero
537 Data None
539 Note:
540 FIXME: Check valid port range, remove some switches if needed (copy paste from definitions)
543 UWORD SetPortFeature(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
544 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
545 mybug_unit(-1, ("Entering function\n"));
547 UBYTE port;
549 port = (wIndex & 0xff);
551 mybug_unit(-1, ("Setting feature 0x%02x on port %d\n",wValue, port));
553 switch(wValue) {
554 case 0x00:
555 mybug_unit(-1, ("UFS_PORT_CONNECTION 0x00\n"));
556 break;
557 case 0x01:
558 mybug_unit(-1, ("UFS_PORT_ENABLE 0x01\n"));
559 unit->roothub.portstatus.wPortStatus |= UPSF_PORT_ENABLE;
560 break;
561 case 0x02:
562 mybug_unit(-1, ("UFS_PORT_SUSPEND 0x02\n"));
563 break;
564 case 0x03:
565 mybug_unit(-1, ("UFS_PORT_OVER_CURRENT 0x03\n"));
566 break;
567 case 0x04:
568 mybug_unit(-1, ("UFS_PORT_RESET 0x04\n"));
569 unit->roothub.portstatus.wPortStatus |= (UPSF_PORT_ENABLE|UPSF_PORT_POWER);
570 break;
571 case 0x08:
572 mybug_unit(-1, ("UFS_PORT_POWER 0x08\n"));
573 unit->roothub.portstatus.wPortStatus |= UPSF_PORT_POWER;
574 break;
575 case 0x09:
576 mybug_unit(-1, ("UFS_PORT_LOW_SPEED 0x09\n"));
577 break;
578 case 0x10:
579 mybug_unit(-1, ("UFS_C_PORT_CONNECTION 0x10\n"));
580 break;
581 case 0x11:
582 mybug_unit(-1, ("UFS_C_PORT_ENABLE 0x11\n"));
583 break;
584 case 0x12:
585 mybug_unit(-1, ("UFS_C_PORT_SUSPEND 0x12\n"));
586 break;
587 case 0x13:
588 mybug_unit(-1, ("UFS_C_PORT_OVER_CURRENT 0x13\n"));
589 break;
590 case 0x14:
591 mybug_unit(-1, ("UFS_C_PORT_RESET 0x14\n"));
592 break;
593 case 0x15:
594 mybug_unit(-1, ("UFS_PORT_TEST 0x15\n"));
595 break;
596 case 0x16:
597 mybug_unit(-1, ("UFS_PORT_INDICATOR 0x16\n"));
598 break;
601 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
602 return UHIOERR_NO_ERROR;
606 ClearPortFeature:
607 bmRequestType (URTF_OUT|URTF_CLASS|URTF_OTHER) 00100011B
608 bRequest USR_CLEAR_FEATURE
609 wValue Feature Selector
610 wIndex (Selector|Port)
611 wLength Zero
612 Data None
614 Note:
615 FIXME: Check valid port range, remove some switches if needed (copy paste from definitions)
618 UWORD ClearPortFeature(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 UBYTE port;
624 port = (wIndex & 0xff);
626 mybug_unit(-1, ("Clearing feature 0x%02x on port %d\n",wValue, port));
629 #define UPSF_PORT_CONNECTION 0x0001
630 #define UPSF_PORT_ENABLE 0x0002
631 #define UPSF_PORT_SUSPEND 0x0004
632 #define UPSF_PORT_OVER_CURRENT 0x0008
633 #define UPSF_PORT_RESET 0x0010
634 #define UPSF_PORT_POWER 0x0100
635 #define UPSF_PORT_LOW_SPEED 0x0200
636 #define UPSF_PORT_HIGH_SPEED 0x0400
637 #define UPSF_PORT_TEST_MODE 0x0800
638 #define UPSF_PORT_INDICATOR 0x1000
640 switch(wValue) {
641 case 0x00:
642 mybug_unit(-1, ("UFS_PORT_CONNECTION 0x00\n"));
643 unit->roothub.portstatus.wPortStatus &= ~UPSF_PORT_CONNECTION;
644 break;
645 case 0x01:
646 mybug_unit(-1, ("UFS_PORT_ENABLE 0x01\n"));
647 unit->roothub.portstatus.wPortStatus &= ~UPSF_PORT_ENABLE;
648 break;
649 case 0x02:
650 mybug_unit(-1, ("UFS_PORT_SUSPEND 0x02\n"));
651 break;
652 case 0x03:
653 mybug_unit(-1, ("UFS_PORT_OVER_CURRENT 0x03\n"));
654 break;
655 case 0x04:
656 mybug_unit(-1, ("UFS_PORT_RESET 0x04\n"));
657 unit->roothub.portstatus.wPortStatus &= ~UPSF_PORT_RESET;
658 break;
659 case 0x08:
660 mybug_unit(-1, ("UFS_PORT_POWER 0x08\n"));
661 unit->roothub.portstatus.wPortStatus &= ~UPSF_PORT_POWER;
662 break;
663 case 0x09:
664 mybug_unit(-1, ("UFS_PORT_LOW_SPEED 0x09\n"));
665 break;
666 case 0x10:
667 mybug_unit(-1, ("UFS_C_PORT_CONNECTION 0x10\n"));
668 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_CONNECTION;
669 break;
670 case 0x11:
671 mybug_unit(-1, ("UFS_C_PORT_ENABLE 0x11\n"));
672 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_ENABLE;
673 break;
674 case 0x12:
675 mybug_unit(-1, ("UFS_C_PORT_SUSPEND 0x12\n"));
676 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_SUSPEND;
677 break;
678 case 0x13:
679 mybug_unit(-1, ("UFS_C_PORT_OVER_CURRENT 0x13\n"));
680 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_OVER_CURRENT;
681 break;
682 case 0x14:
683 mybug_unit(-1, ("UFS_C_PORT_RESET 0x14\n"));
684 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_RESET;
685 break;
686 case 0x15:
687 mybug_unit(-1, ("UFS_PORT_TEST 0x15\n"));
688 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_TEST_MODE;
689 break;
690 case 0x16:
691 mybug_unit(-1, ("UFS_PORT_INDICATOR 0x16\n"));
692 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_INDICATOR;
693 break;
696 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
697 return UHIOERR_NO_ERROR;
702 UWORD GetTTState(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
703 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
704 mybug_unit(-1, ("Entering function\n"));
706 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
707 return UHIOERR_NO_ERROR;
712 UWORD StopTT(struct IOUsbHWReq *ioreq, UWORD wValue, UWORD wIndex, UWORD wLength) {
713 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
714 mybug_unit(-1, ("Entering function\n"));
716 mybug_unit(-1, ("return UHIOERR_NO_ERROR\n\n"));
717 return UHIOERR_NO_ERROR;
721 WORD cmdControlXFerRootHub(struct IOUsbHWReq *ioreq) {
723 UWORD bmRequestType = (ioreq->iouh_SetupData.bmRequestType) & (URTF_STANDARD | URTF_CLASS | URTF_VENDOR);
724 UWORD bmRequestDirection = (ioreq->iouh_SetupData.bmRequestType) & (URTF_IN | URTF_OUT);
725 UWORD bmRequestRecipient = (ioreq->iouh_SetupData.bmRequestType) & (URTF_DEVICE | URTF_INTERFACE | URTF_ENDPOINT | URTF_OTHER);
727 UWORD bRequest = (ioreq->iouh_SetupData.bRequest);
728 UWORD wValue = AROS_WORD2LE(ioreq->iouh_SetupData.wValue);
729 UWORD wIndex = AROS_WORD2LE(ioreq->iouh_SetupData.wIndex);
730 UWORD wLength = AROS_WORD2LE(ioreq->iouh_SetupData.wLength);
732 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
734 /* Endpoint 0 is used for control transfers only and can not be assigned to any other function. */
735 if(ioreq->iouh_Endpoint != 0) {
736 mybug_unit(-1, ("Wrong endpoint number! %ld\n", ioreq->iouh_Endpoint));
737 mybug_unit(-1, ("return UHIOERR_BADPARAMS\n\n"));
738 return UHIOERR_BADPARAMS;
741 switch(((ULONG)ioreq->iouh_SetupData.bmRequestType<<16)|((ULONG)ioreq->iouh_SetupData.bRequest)) {
743 /* Standard Requests */
744 case ((((URTF_OUT|URTF_STANDARD|URTF_DEVICE))<<16)|(USR_SET_ADDRESS)):
745 return(SetAddress(ioreq, wValue, wIndex, wLength));
747 case ((((URTF_OUT|URTF_STANDARD|URTF_DEVICE))<<16)|(USR_SET_CONFIGURATION)):
748 return(SetConfiguration(ioreq, wValue, wIndex, wLength));
750 case (((URTF_IN|URTF_STANDARD|URTF_DEVICE)<<16)|(USR_GET_STATUS)):
751 return(GetStatus(ioreq, wValue, wIndex, wLength));
753 case (((URTF_IN|URTF_STANDARD|URTF_DEVICE)<<16)|(USR_GET_DESCRIPTOR)):
754 return(GetDescriptor(ioreq, wValue, wIndex, wLength));
756 case (((URTF_OUT|URTF_STANDARD|URTF_DEVICE)<<16)|(USR_SET_DESCRIPTOR)):
757 return(SetDescriptor(ioreq, wValue, wIndex, wLength));
759 /* Hub Class Requests */
760 case (((URTF_OUT|URTF_CLASS|URTF_DEVICE)<<16)|(USR_CLEAR_FEATURE)):
761 return(ClearHubFeature(ioreq, wValue, wIndex, wLength));
763 case (((URTF_OUT|URTF_CLASS|URTF_DEVICE)<<16)|(USR_SET_FEATURE)):
764 return(SetHubFeature(ioreq, wValue, wIndex, wLength));
766 case (((URTF_OUT|URTF_CLASS|URTF_OTHER)<<16)|(USR_CLEAR_FEATURE)):
767 return(ClearPortFeature(ioreq, wValue, wIndex, wLength));
769 case (((URTF_OUT|URTF_CLASS|URTF_OTHER)<<16)|(USR_SET_FEATURE)):
770 return(SetPortFeature(ioreq, wValue, wIndex, wLength));
772 case (((URTF_IN|URTF_CLASS|URTF_DEVICE)<<16)|(USR_GET_DESCRIPTOR)):
773 return(GetHubDescriptor(ioreq, wValue, wIndex, wLength));
775 case ((((URTF_IN|URTF_CLASS|URTF_DEVICE))<<16)|(USR_GET_STATUS)):
776 return(GetHubStatus(ioreq, wValue, wIndex, wLength));
778 case ((((URTF_IN|URTF_CLASS|URTF_OTHER))<<16)|(USR_GET_STATUS)):
779 return(GetPortStatus(ioreq, wValue, wIndex, wLength));
781 // case (((( X ))<<16)|( X )):
782 // return( X (ioreq));
784 default:
785 break;
788 D( mybug_unit(-1, ("bmRequestDirection "));
789 switch (bmRequestDirection) {
790 case URTF_IN:
791 mybug(-1, ("URTF_IN\n"));
792 break;
793 case URTF_OUT:
794 mybug(-1, ("URTF_OUT\n"));
795 break;
798 mybug_unit(-1, ("bmRequestType "));
799 switch(bmRequestType) {
800 case URTF_STANDARD:
801 mybug(-1, ("URTF_STANDARD\n"));
802 break;
803 case URTF_CLASS:
804 mybug(-1, ("URTF_CLASS\n"));
805 break;
806 case URTF_VENDOR:
807 mybug(-1, ("URTF_VENDOR\n"));
808 break;
811 mybug_unit(-1, ("bmRequestRecipient "));
812 switch (bmRequestRecipient) {
813 case URTF_DEVICE:
814 mybug(-1, ("URTF_DEVICE\n"));
815 break;
816 case URTF_INTERFACE:
817 mybug(-1, ("URTF_INTERFACE\n"));
818 break;
819 case URTF_ENDPOINT:
820 mybug(-1, ("URTF_ENDPOINT\n"));
821 break;
822 case URTF_OTHER:
823 mybug(-1, ("URTF_OTHER\n"));
824 break;
827 mybug_unit(-1, ("bRequest "));
828 switch(bRequest) {
829 case USR_GET_STATUS:
830 bug("USR_GET_STATUS\n");
831 break;
832 case USR_CLEAR_FEATURE:
833 mybug(-1, ("USR_CLEAR_FEATURE\n"));
834 break;
835 case USR_SET_FEATURE:
836 mybug(-1, ("USR_SET_FEATURE\n"));
837 break;
838 case USR_SET_ADDRESS:
839 mybug(-1, ("USR_SET_ADDRESS\n"));
840 break;
841 case USR_GET_DESCRIPTOR:
842 mybug(-1, ("USR_GET_DESCRIPTOR\n"));
843 break;
844 case USR_SET_DESCRIPTOR:
845 mybug(-1, ("USR_SET_DESCRIPTOR\n"));
846 break;
847 case USR_GET_CONFIGURATION:
848 mybug(-1, ("USR_GET_CONFIGURATION\n"););
849 break;
850 case USR_SET_CONFIGURATION:
851 mybug(-1, ("USR_SET_CONFIGURATION\n"));
852 break;
853 case USR_GET_INTERFACE:
854 mybug(-1, ("USR_GET_INTERFACE\n"));
855 break;
856 case USR_SET_INTERFACE:
857 mybug(-1, ("USR_SET_INTERFACE\n"));
858 break;
859 case USR_SYNCH_FRAME:
860 mybug(-1, ("USR_SYNCH_FRAME\n"));
861 break;
864 mybug_unit(-1, ("wIndex %x\n", wIndex));
865 mybug_unit(-1, ("wValue %x\n", wValue));
866 mybug_unit(-1, ("wLength %d\n", wLength));
868 mybug_unit(-1, ("Nothing done!\n\n")) );
869 return UHIOERR_BADPARAMS;
872 WORD cmdIntXFerRootHub(struct IOUsbHWReq *ioreq) {
873 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
875 mybug_unit(0, ("Entering function\n"));
877 if((ioreq->iouh_Endpoint != 1) || (!ioreq->iouh_Length)) {
878 mybug_unit(-1, ("UHIOERR_BADPARAMS\n"));
879 return(UHIOERR_BADPARAMS); // was UHIOERR_STALL
882 #if 0
883 if(unit->roothub.portstatus.wPortChange) {
884 mybug_unit(-1, ("unit->roothub.portstatus.wPortChange = %02x\n", unit->roothub.portstatus.wPortChange));
885 *((UBYTE *) ioreq->iouh_Data) = unit->roothub.portstatus.wPortChange;
886 ioreq->iouh_Actual = 1;
887 unit->roothub.portstatus.wPortChange &= ~UPSF_PORT_CONNECTION;
888 mybug_unit(-1, ("unit->roothub.portstatus.wPortChange = %02x\n", unit->roothub.portstatus.wPortChange));
889 return(0);
891 #endif
893 mybug_unit(0, ("ioreq added to roothub intrxfer_queue\n"));
895 ioreq->iouh_Req.io_Flags &= ~IOF_QUICK;
896 Disable();
897 AddTail(&unit->roothub.intrxfer_queue, (struct Node *) ioreq);
898 Enable();
899 return(RC_DONTREPLY);
903 WORD cmdControlXFer(struct IOUsbHWReq *ioreq) {
904 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
906 mybug_unit(0, ("Entering function\n"));
908 mybug_unit(0, ("ioreq->iouh_DevAddr %lx\n", ioreq->iouh_DevAddr));
909 mybug_unit(0, ("unit->roothub.addr %lx\n", unit->roothub.addr));
912 Check the status of the controller
913 We might encounter these states:
914 UHSB_OPERATIONAL USB can be used for transfers
915 UHSB_RESUMING USB is currently resuming
916 UHSB_SUSPENDED USB is in suspended state
917 UHSB_RESET USB is just inside a reset phase
920 if(unit->state == UHSF_OPERATIONAL) {
921 mybug_unit(0, ("Unit state is operational\n"));
922 } else {
923 mybug_unit(-1, ("Unit state is not operational!\n"));
924 return UHIOERR_USBOFFLINE;
927 if(ioreq->iouh_DevAddr == unit->roothub.addr) {
928 return(cmdControlXFerRootHub(ioreq));
931 mybug_unit(-1, ("Sending transfer request to libusb\n"));
932 return(do_libusb_ctrl_transfer(ioreq));
935 WORD cmdIntXFer(struct IOUsbHWReq *ioreq) {
936 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
938 mybug_unit(0, ("Entering function\n"));
940 mybug_unit(0, ("ioreq->iouh_DevAddr %lx\n", ioreq->iouh_DevAddr));
941 mybug_unit(0, ("unit->roothub.addr %lx\n", unit->roothub.addr));
944 Check the status of the controller
945 We might encounter these states:
946 UHSB_OPERATIONAL USB can be used for transfers
947 UHSB_RESUMING USB is currently resuming
948 UHSB_SUSPENDED USB is in suspended state
949 UHSB_RESET USB is just inside a reset phase
952 if(unit->state == UHSF_OPERATIONAL) {
953 mybug_unit(0, ("Unit state is operational\n"));
954 } else {
955 mybug_unit(-1, ("Unit state is not operational!\n"));
956 return UHIOERR_USBOFFLINE;
959 if(ioreq->iouh_DevAddr == unit->roothub.addr) {
960 return(cmdIntXFerRootHub(ioreq));
963 mybug_unit(-1, ("Sending transfer request to libusb\n"));
964 return(do_libusb_intr_transfer(ioreq));
965 return(RC_DONTREPLY);
968 WORD cmdBulkXFer(struct IOUsbHWReq *ioreq) {
969 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
971 mybug_unit(-1, ("Entering function\n"));
973 mybug_unit(-1, ("ioreq->iouh_DevAddr %lx\n", ioreq->iouh_DevAddr));
974 mybug_unit(-1, ("unit->roothub.addr %lx\n", unit->roothub.addr));
977 Check the status of the controller
978 We might encounter these states:
979 UHSB_OPERATIONAL USB can be used for transfers
980 UHSB_RESUMING USB is currently resuming
981 UHSB_SUSPENDED USB is in suspended state
982 UHSB_RESET USB is just inside a reset phase
985 if(unit->state == UHSF_OPERATIONAL) {
986 mybug_unit(0, ("Unit state is operational\n"));
987 } else {
988 mybug_unit(-1, ("Unit state is not operational!\n"));
989 return UHIOERR_USBOFFLINE;
992 mybug_unit(-1, ("Sending transfer request to libusb\n"));
993 return(do_libusb_bulk_transfer(ioreq));
994 return(RC_DONTREPLY);
997 WORD cmdISOXFer(struct IOUsbHWReq *ioreq) {
998 struct VUSBHCIUnit *unit = (struct VUSBHCIUnit *) ioreq->iouh_Req.io_Unit;
1000 mybug_unit(-1, ("Entering function\n"));
1002 mybug_unit(-1, ("ioreq->iouh_DevAddr %lx\n", ioreq->iouh_DevAddr));
1003 mybug_unit(-1, ("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(-1, ("Sending transfer request to libusb\n"));
1022 do_libusb_isoc_transfer(ioreq);
1024 return RC_DONTREPLY;
1027 void uhwCheckRootHubChanges(struct VUSBHCIUnit *unit) {
1028 mybug_unit(0, ("Entering function\n"));
1030 mybug_unit(0, ("usbportstatus->wPortStatus %01x\n", unit->roothub.portstatus.wPortStatus));
1031 mybug_unit(0, ("usbportstatus->wPortChange %01x\n", unit->roothub.portstatus.wPortChange));
1033 struct IOUsbHWReq *ioreq;
1035 if(unit->roothub.portstatus.wPortChange && unit->roothub.intrxfer_queue.lh_Head->ln_Succ) {
1036 Disable();
1037 ioreq = (struct IOUsbHWReq *) unit->roothub.intrxfer_queue.lh_Head;
1038 while(((struct Node *) ioreq)->ln_Succ) {
1039 Remove(&ioreq->iouh_Req.io_Message.mn_Node);
1041 *((UBYTE *) ioreq->iouh_Data) = (1<<1);
1042 ioreq->iouh_Actual = 1;
1044 ReplyMsg(&ioreq->iouh_Req.io_Message);
1045 ioreq = (struct IOUsbHWReq *) unit->roothub.intrxfer_queue.lh_Head;
1047 Enable();