2 Copyright © 2015-2018, The AROS Development Team. All rights reserved.
5 Desc: Virtual 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>
26 #include <devices/timer.h>
28 #include "vusbhci_device.h"
30 #include LC_LIBDEFS_FILE
32 struct VUSBHCIUnit
*VUSBHCI_AddNewUnit200(void);
33 struct VUSBHCIUnit
*VUSBHCI_AddNewUnit300(void);
35 static void handler_task(struct Task
*parent
, struct VUSBHCIUnit
*unit
) {
36 mybug_unit(-1,("Starting %s handler task\n", unit
->name
));
37 mybug_unit(-1, ("Sending signal number %ld\n", unit
->handler_task_sig_run
));
38 Signal(parent
, (1L<<unit
->handler_task_sig_run
) );
40 ULONG check_handler
= 0;
42 unit
->mp
= CreateMsgPort();
44 unit
->tr
= (struct timerequest
*)CreateIORequest(unit
->mp
, sizeof(struct timerequest
));
46 FreeSignal(unit
->mp
->mp_SigBit
);
47 if (!OpenDevice((STRPTR
)"timer.device", UNIT_MICROHZ
, (struct IORequest
*)unit
->tr
, 0)) {
48 /* Allocate a signal within this task context */
49 unit
->tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
= SIGB_SINGLE
;
50 unit
->tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigTask
= FindTask(NULL
);
51 /* Specify the request */
52 unit
->tr
->tr_node
.io_Command
= TR_ADDREQUEST
;
54 /* FIXME: Use signals */
56 //mybug(-1,("[handler_task] Ping...\n"));
58 if(!unit
->ctrlxfer_pending
) {
59 /* Try and get a lock on the semaphore, if not then just move on as some housekeeping is being done */
60 AttemptSemaphore(&unit
->ctrlxfer_queue_lock
); {
61 ForeachNode(&unit
->ctrlxfer_queue
, unit
->ioreq_ctrl
) {
62 /* Now the iorequest lives only on our pointer */
63 Remove(&unit
->ioreq_ctrl
->iouh_Req
.io_Message
.mn_Node
);
64 mybug(-1,("[handler_task] Control transfer caught...\n"));
65 unit
->ctrlxfer_pending
= TRUE
;
66 do_libusb_ctrl_transfer(unit
->ioreq_ctrl
);
68 } ReleaseSemaphore(&unit
->ctrlxfer_queue_lock
);
71 if(!unit
->intrxfer_pending
) {
72 AttemptSemaphore(&unit
->intrxfer_queue_lock
); {
73 ForeachNode(&unit
->intrxfer_queue
, unit
->ioreq_intr
) {
74 /* Now the iorequest lives only on our pointer */
75 Remove(&unit
->ioreq_intr
->iouh_Req
.io_Message
.mn_Node
);
76 unit
->intrxfer_pending
= TRUE
;
77 do_libusb_intr_transfer(unit
->ioreq_intr
);
79 } ReleaseSemaphore(&unit
->intrxfer_queue_lock
);
82 if(!unit
->bulkxfer_pending
) {
83 AttemptSemaphore(&unit
->bulkxfer_queue_lock
); {
84 ForeachNode(&unit
->bulkxfer_queue
, unit
->ioreq_bulk
) {
85 /* Now the iorequest lives only on our pointer */
86 Remove(&unit
->ioreq_bulk
->iouh_Req
.io_Message
.mn_Node
);
87 unit
->bulkxfer_pending
= TRUE
;
88 do_libusb_bulk_transfer(unit
->ioreq_bulk
);
90 } ReleaseSemaphore(&unit
->bulkxfer_queue_lock
);
93 if(!unit
->isocxfer_pending
) {
94 AttemptSemaphore(&unit
->isocxfer_queue_lock
); {
95 ForeachNode(&unit
->isocxfer_queue
, unit
->ioreq_isoc
) {
96 /* Now the iorequest lives only on our pointer */
97 Remove(&unit
->ioreq_isoc
->iouh_Req
.io_Message
.mn_Node
);
98 unit
->isocxfer_pending
= TRUE
;
99 do_libusb_isoc_transfer(unit
->ioreq_isoc
);
101 } ReleaseSemaphore(&unit
->isocxfer_queue_lock
);
105 if((check_handler
==0)|(unit
->ctrlxfer_pending
|unit
->intrxfer_pending
|unit
->bulkxfer_pending
|unit
->isocxfer_pending
)) {
107 call_libusb_event_handler();
112 unit
->tr
->tr_time
.tv_secs
= 0;
113 unit
->tr
->tr_time
.tv_micro
= 100000;
114 DoIO((struct IORequest
*)unit
->tr
);
116 if(check_handler
>0) {
120 CloseDevice((struct IORequest
*)unit
->tr
);
122 DeleteIORequest((struct IORequest
*)unit
->tr
);
123 unit
->mp
->mp_SigBit
= AllocSignal(-1);
125 DeleteMsgPort(unit
->mp
);
128 mybug(-1,("Exiting %s handler task\n", unit
->name
));
130 //Signal(parent, SIGF_CHILD);
133 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR VUSBHCIBase
) {
134 mybug(-1,("[VUSBHCI] Init: Entering function\n"));
136 if(!libusb_bridge_init(VUSBHCIBase
)) {
140 VUSBHCIBase
->usbunit200
= VUSBHCI_AddNewUnit200();
141 if(VUSBHCIBase
->usbunit200
== NULL
) {
142 mybug(-1, ("[VUSBHCI] Init: Failed to create new USB2.0 unit!\n"));
146 VUSBHCIBase
->usbunit300
= VUSBHCI_AddNewUnit300();
147 if(VUSBHCIBase
->usbunit300
== NULL
) {
148 mybug(-1, ("[VUSBHCI] Init: Failed to create new USB3.0 unit!\n"));
155 static int GM_UNIQUENAME(Open
)(LIBBASETYPEPTR VUSBHCIBase
, struct IOUsbHWReq
*ioreq
, ULONG unitnum
, ULONG flags
) {
156 mybug(-1, ("[VUSBHCI] Open: Entering function\n"));
157 mybug(-1, ("[VUSBHCI] Open: Unit %d\n", unitnum
));
159 struct VUSBHCIUnit
*unit
;
161 /* Default to open failure. */
162 ioreq
->iouh_Req
.io_Error
= IOERR_OPENFAIL
;
163 ioreq
->iouh_Req
.io_Unit
= NULL
;
166 unit
= VUSBHCIBase
->usbunit200
;
167 } else if(unitnum
== 1) {
168 unit
= VUSBHCIBase
->usbunit300
;
173 if(ioreq
->iouh_Req
.io_Message
.mn_Length
< sizeof(struct IOUsbHWReq
)) {
174 mybug(-1, ("[VUSBHCI] Open: Invalid MN_LENGTH!\n"));
175 ioreq
->iouh_Req
.io_Error
= IOERR_BADLENGTH
;
178 ioreq
->iouh_Req
.io_Unit
= NULL
;
180 if(unit
->allocated
) {
181 ioreq
->iouh_Req
.io_Error
= IOERR_UNITBUSY
;
182 ioreq
->iouh_Req
.io_Unit
= NULL
;
183 mybug(-1, ("Unit already in use!\n\n"));
186 unit
->allocated
= TRUE
;
187 ioreq
->iouh_Req
.io_Unit
= (struct Unit
*) unit
;
190 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
191 ioreq
->iouh_Req
.io_Error
= 0;
198 static int GM_UNIQUENAME(Close
)(LIBBASETYPEPTR VUSBHCIBase
, struct IOUsbHWReq
*ioreq
) {
199 mybug(-1, ("[VUSBHCI] Close: Entering function\n"));
201 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*)ioreq
->iouh_Req
.io_Unit
;
203 mybug_unit(-1, ("Closing unit %p\n", unit
));
206 unit
->allocated
= FALSE
;
208 ioreq
->iouh_Req
.io_Unit
= (APTR
) -1;
209 ioreq
->iouh_Req
.io_Device
= (APTR
) -1;
214 ioreq
->iouh_Req
.io_Error
= IOERR_BADADDRESS
;
215 ioreq
->iouh_Req
.io_Unit
= (APTR
) -1;
216 ioreq
->iouh_Req
.io_Device
= (APTR
) -1;
218 mybug(-1, (" Bad unit structure in ioreq, nothing done!\n\n"));
222 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
223 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
224 ADD2CLOSEDEV(GM_UNIQUENAME(Close
), 0)
226 AROS_LH1(void, BeginIO
, AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
), struct VUSBHCIBase
*, VUSBHCIBase
, 5, VUSBHCI
) {
231 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
232 ioreq
->iouh_Req
.io_Error
= UHIOERR_NO_ERROR
;
234 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
236 mybug_unit(0, ("Entering function\n"));
240 switch (ioreq
->iouh_Req
.io_Command
) {
242 mybug_unit(-1, ("CMD_RESET\n"));
245 mybug_unit(-1, ("CMD_FLUSH\n"));
247 case UHCMD_QUERYDEVICE
:
248 mybug_unit(-1, ("UHCMD_QUERYDEVICE\n"));
249 ret
= cmdQueryDevice(ioreq
);
252 mybug_unit(0, ("UHCMD_USBRESET\n"));
253 ret
= cmdUsbReset(ioreq
);
255 case UHCMD_USBRESUME
:
256 mybug_unit(-1, ("UHCMD_USBRESUME\n"));
258 case UHCMD_USBSUSPEND
:
259 mybug_unit(-1, ("UHCMD_USBSUSPEND\n"));
262 mybug_unit(-1, ("UHCMD_USBOPER\n"));
263 //ret = cmdUsbOper(ioreq);
265 case UHCMD_CONTROLXFER
:
266 ret
= cmdControlXFer(ioreq
);
269 ret
= cmdIntXFer(ioreq
);
272 ret
= cmdBulkXFer(ioreq
);
275 ret
= cmdISOXFer(ioreq
);
278 /* Poseidon doesn't actually check this, ever... */
279 case NSCMD_DEVICEQUERY
:
280 mybug_unit(-1, ("NSCMD_DEVICEQUERY\n"));
282 static const UWORD NSDSupported
[] = {
283 CMD_FLUSH
, CMD_RESET
,
297 struct NSDeviceQueryResult
*nsdq
= (struct NSDeviceQueryResult
*)((struct IOStdReq
*)(ioreq
))->io_Data
;
298 nsdq
->DevQueryFormat
= 0;
299 nsdq
->SizeAvailable
= sizeof(struct NSDeviceQueryResult
);
300 nsdq
->DeviceType
= NSDEVTYPE_USBHARDWARE
;
301 nsdq
->DeviceSubType
= 0;
302 nsdq
->SupportedCommands
= (UWORD
*)NSDSupported
;
306 mybug_unit(-1, ("IOERR_NOCMD\n"));
311 /* We have aborted the request as unit is invalid */
315 if(ret
!= RC_DONTREPLY
) {
316 /* Set error codes */
318 ioreq
->iouh_Req
.io_Error
= ret
& 0xff;
320 /* Terminate the iorequest */
321 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
322 /* If not quick I/O, reply the message */
323 if(!(ioreq
->iouh_Req
.io_Flags
& IOF_QUICK
)) {
324 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
331 AROS_LH1(LONG
, AbortIO
, AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
), struct VUSBHCIBase
*, VUSBHCIBase
, 6, VUSBHCI
) {
333 mybug(-1, ("[VUSBHCI] AbortIO: Entering function\n"));
335 if(ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
) {
336 if(cmdAbortIO(ioreq
)) {
345 WORD
cmdQueryDevice(struct IOUsbHWReq
*ioreq
) {
346 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
348 mybug_unit(-1, ("Entering function\n"));
350 struct TagItem
*taglist
= (struct TagItem
*) ioreq
->iouh_Data
;
354 while((tag
= LibNextTagItem(&taglist
)) != NULL
) {
355 switch (tag
->ti_Tag
) {
356 case UHA_Manufacturer
:
357 *((STRPTR
*) tag
->ti_Data
) = "The AROS Development Team";
361 *((ULONG
*) tag
->ti_Data
) = VERSION_NUMBER
;
365 *((ULONG
*) tag
->ti_Data
) = REVISION_NUMBER
;
369 *((STRPTR
*) tag
->ti_Data
) = "©2015-2017 The AROS Development Team";
372 case UHA_ProductName
:
373 if(unit
->roothub
.devdesc
.bcdUSB
== AROS_WORD2LE(0x0200)) {
374 *((STRPTR
*) tag
->ti_Data
) = "VUSBHCI Host Controller USB2.0";
376 *((STRPTR
*) tag
->ti_Data
) = "VUSBHCI Host Controller USB3.0";
380 case UHA_Description
:
381 *((STRPTR
*) tag
->ti_Data
) = "Hosted Host Controller Interface (libusb)";
384 case UHA_Capabilities
:
385 if(unit
->roothub
.devdesc
.bcdUSB
== AROS_WORD2LE(0x0200)) {
386 *((ULONG
*) tag
->ti_Data
) = (UHCF_USB20
|UHCF_ISO
);
388 *((ULONG
*) tag
->ti_Data
) = (UHCF_USB30
|UHCF_ISO
);
397 mybug_unit(-1, ("Done\n\n"));
399 ioreq
->iouh_Actual
= count
;
403 struct VUSBHCIUnit
*VUSBHCI_AddNewUnit200(void) {
405 struct VUSBHCIUnit
*unit
;
407 static const char name
[] = {"[VUSBHCI2.00]"};
409 unit
= AllocVec(sizeof(struct VUSBHCIUnit
), MEMF_ANY
|MEMF_CLEAR
);
412 mybug(-1, ("[VUSBHCI] VUSBHCI_AddNewUnit: Failed to create new unit structure\n"));
415 unit
->state
= UHSF_SUSPENDED
;
416 unit
->allocated
= FALSE
;
418 unit
->ctrlxfer_pending
= FALSE
;
419 unit
->intrxfer_pending
= FALSE
;
420 unit
->bulkxfer_pending
= FALSE
;
421 unit
->isocxfer_pending
= FALSE
;
423 NEWLIST(&unit
->ctrlxfer_queue
);
424 NEWLIST(&unit
->intrxfer_queue
);
425 NEWLIST(&unit
->bulkxfer_queue
);
426 NEWLIST(&unit
->isocxfer_queue
);
428 NEWLIST(&unit
->roothub
.intrxfer_queue
);
430 /* This is our root hub device descriptor */
431 unit
->roothub
.devdesc
.bLength
= sizeof(struct UsbStdDevDesc
);
432 unit
->roothub
.devdesc
.bDescriptorType
= UDT_DEVICE
;
433 unit
->roothub
.devdesc
.bcdUSB
= AROS_WORD2LE(0x0200);
434 unit
->roothub
.devdesc
.bDeviceClass
= HUB_CLASSCODE
;
435 unit
->roothub
.devdesc
.bDeviceSubClass
= 0;
436 unit
->roothub
.devdesc
.bDeviceProtocol
= 0;
437 unit
->roothub
.devdesc
.bMaxPacketSize0
= 64; // Valid values are 8, 9(SuperSpeed), 16, 32, 64
438 unit
->roothub
.devdesc
.idVendor
= AROS_WORD2LE(0x0000);
439 unit
->roothub
.devdesc
.idProduct
= AROS_WORD2LE(0x0000);
440 unit
->roothub
.devdesc
.bcdDevice
= AROS_WORD2LE(0x0200);
441 unit
->roothub
.devdesc
.iManufacturer
= 1;
442 unit
->roothub
.devdesc
.iProduct
= 2;
443 unit
->roothub
.devdesc
.iSerialNumber
= 0;
444 unit
->roothub
.devdesc
.bNumConfigurations
= 1;
446 /* This is our root hub config descriptor */
447 unit
->roothub
.config
.cfgdesc
.bLength
= sizeof(struct UsbStdCfgDesc
);
448 unit
->roothub
.config
.cfgdesc
.bLength
= sizeof(struct UsbStdCfgDesc
);
449 unit
->roothub
.config
.cfgdesc
.bDescriptorType
= UDT_CONFIGURATION
;
450 unit
->roothub
.config
.cfgdesc
.wTotalLength
= AROS_WORD2LE(sizeof(struct RHConfig
));
451 unit
->roothub
.config
.cfgdesc
.bNumInterfaces
= 1;
452 unit
->roothub
.config
.cfgdesc
.bConfigurationValue
= 1;
453 unit
->roothub
.config
.cfgdesc
.iConfiguration
= 0;
454 unit
->roothub
.config
.cfgdesc
.bmAttributes
= (USCAF_SELF_POWERED
);
455 unit
->roothub
.config
.cfgdesc
.bMaxPower
= 0;
457 unit
->roothub
.config
.ifdesc
.bLength
= sizeof(struct UsbStdIfDesc
);
458 unit
->roothub
.config
.ifdesc
.bDescriptorType
= UDT_INTERFACE
;
459 unit
->roothub
.config
.ifdesc
.bInterfaceNumber
= 0;
460 unit
->roothub
.config
.ifdesc
.bAlternateSetting
= 0;
461 unit
->roothub
.config
.ifdesc
.bNumEndpoints
= 1;
462 unit
->roothub
.config
.ifdesc
.bInterfaceClass
= HUB_CLASSCODE
;
463 unit
->roothub
.config
.ifdesc
.bInterfaceSubClass
= 0;
464 unit
->roothub
.config
.ifdesc
.bInterfaceProtocol
= 0;
465 unit
->roothub
.config
.ifdesc
.iInterface
= 0;
467 unit
->roothub
.config
.epdesc
.bLength
= sizeof(struct UsbStdEPDesc
);
468 unit
->roothub
.config
.epdesc
.bDescriptorType
= UDT_ENDPOINT
;
469 unit
->roothub
.config
.epdesc
.bEndpointAddress
= (URTF_IN
|1);
470 unit
->roothub
.config
.epdesc
.bmAttributes
= USEAF_INTERRUPT
;
471 unit
->roothub
.config
.epdesc
.wMaxPacketSize
= AROS_WORD2LE(4);
472 unit
->roothub
.config
.epdesc
.bInterval
= 12;
474 /* This is our root hub hub descriptor */
475 unit
->roothub
.hubdesc
.bLength
= sizeof(struct UsbHubDesc
);
476 unit
->roothub
.hubdesc
.bDescriptorType
= UDT_HUB
;
477 unit
->roothub
.hubdesc
.bNbrPorts
= 1;
478 unit
->roothub
.hubdesc
.wHubCharacteristics
= AROS_WORD2LE(UHCF_INDIVID_POWER
|UHCF_INDIVID_OVP
);
479 unit
->roothub
.hubdesc
.bPwrOn2PwrGood
= 1;
480 unit
->roothub
.hubdesc
.bHubContrCurrent
= 1;
481 unit
->roothub
.hubdesc
.DeviceRemovable
= 0;
482 unit
->roothub
.hubdesc
.PortPwrCtrlMask
= (1<<1);
484 //unit->roothub.portstatus.wPortStatus = 0;
485 //unit->roothub.portstatus.wPortChange = 0;
487 //unit->roothub.hubstatus->wHubStatus = 0;
488 //unit->roothub.hubstatus->wHubChange = 0;
492 InitSemaphore(&unit
->ctrlxfer_queue_lock
);
493 InitSemaphore(&unit
->intrxfer_queue_lock
);
494 InitSemaphore(&unit
->bulkxfer_queue_lock
);
495 InitSemaphore(&unit
->isocxfer_queue_lock
);
497 InitSemaphore(&unit
->roothub
.intrxfer_queue_lock
);
499 /* Create periodic handler task */
500 if (-1 == (unit
->handler_task_sig_run
= AllocSignal(-1))) {
501 mybug_unit(-1, ("No signal bits available\n\n"));
503 mybug_unit(-1, ("allocated signal number %ld\n", unit
->handler_task_sig_run
));
506 unit
->handler_task
= NewCreateTask(TASKTAG_NAME
, "libusb handler task usb 2.0",
507 TASKTAG_PC
, handler_task
,
508 TASKTAG_ARG1
, FindTask(NULL
),
513 mybug_unit(-1, ("Waiting for %s handler task\n", unit
->name
));
514 Wait( (1L<<unit
->handler_task_sig_run
) );
515 mybug_unit(-1, ("%s handler task responded\n\n", unit
->name
));
516 //FreeSignal(unit->handler_task_sig_run);
522 struct VUSBHCIUnit
*VUSBHCI_AddNewUnit300(void) {
524 struct VUSBHCIUnit
*unit
;
526 static const char name
[] = {"[VUSBHCI3.00]"};
528 unit
= AllocVec(sizeof(struct VUSBHCIUnit
), MEMF_ANY
|MEMF_CLEAR
);
531 mybug(-1, ("[VUSBHCI] VUSBHCI_AddNewUnit: Failed to create new unit structure\n"));
534 unit
->state
= UHSF_SUSPENDED
;
535 unit
->allocated
= FALSE
;
537 NEWLIST(&unit
->ctrlxfer_queue
);
538 NEWLIST(&unit
->intrxfer_queue
);
539 NEWLIST(&unit
->bulkxfer_queue
);
540 NEWLIST(&unit
->isocxfer_queue
);
542 NEWLIST(&unit
->roothub
.intrxfer_queue
);
544 /* This is our root hub device descriptor */
545 unit
->roothub
.devdesc
.bLength
= sizeof(struct UsbStdDevDesc
);
546 unit
->roothub
.devdesc
.bDescriptorType
= UDT_DEVICE
;
547 unit
->roothub
.devdesc
.bcdUSB
= AROS_WORD2LE(0x0300);
548 unit
->roothub
.devdesc
.bDeviceClass
= HUB_CLASSCODE
;
549 unit
->roothub
.devdesc
.bDeviceSubClass
= 0;
550 unit
->roothub
.devdesc
.bDeviceProtocol
= 0;
551 unit
->roothub
.devdesc
.bMaxPacketSize0
= 9; // Valid values are 8, 9(SuperSpeed), 16, 32, 64
552 unit
->roothub
.devdesc
.idVendor
= AROS_WORD2LE(0x0000);
553 unit
->roothub
.devdesc
.idProduct
= AROS_WORD2LE(0x0000);
554 unit
->roothub
.devdesc
.bcdDevice
= AROS_WORD2LE(0x0300);
555 unit
->roothub
.devdesc
.iManufacturer
= 1;
556 unit
->roothub
.devdesc
.iProduct
= 2;
557 unit
->roothub
.devdesc
.iSerialNumber
= 0;
558 unit
->roothub
.devdesc
.bNumConfigurations
= 1;
560 /* This is our root hub config descriptor */
561 unit
->roothub
.config
.cfgdesc
.bLength
= sizeof(struct UsbStdCfgDesc
);
562 unit
->roothub
.config
.cfgdesc
.bLength
= sizeof(struct UsbStdCfgDesc
);
563 unit
->roothub
.config
.cfgdesc
.bDescriptorType
= UDT_CONFIGURATION
;
564 unit
->roothub
.config
.cfgdesc
.wTotalLength
= AROS_WORD2LE(sizeof(struct RHConfig
));
565 unit
->roothub
.config
.cfgdesc
.bNumInterfaces
= 1;
566 unit
->roothub
.config
.cfgdesc
.bConfigurationValue
= 1;
567 unit
->roothub
.config
.cfgdesc
.iConfiguration
= 0;
568 unit
->roothub
.config
.cfgdesc
.bmAttributes
= (USCAF_SELF_POWERED
);
569 unit
->roothub
.config
.cfgdesc
.bMaxPower
= 0;
571 unit
->roothub
.config
.ifdesc
.bLength
= sizeof(struct UsbStdIfDesc
);
572 unit
->roothub
.config
.ifdesc
.bDescriptorType
= UDT_INTERFACE
;
573 unit
->roothub
.config
.ifdesc
.bInterfaceNumber
= 0;
574 unit
->roothub
.config
.ifdesc
.bAlternateSetting
= 0;
575 unit
->roothub
.config
.ifdesc
.bNumEndpoints
= 1;
576 unit
->roothub
.config
.ifdesc
.bInterfaceClass
= HUB_CLASSCODE
;
577 unit
->roothub
.config
.ifdesc
.bInterfaceSubClass
= 0;
578 unit
->roothub
.config
.ifdesc
.bInterfaceProtocol
= 0;
579 unit
->roothub
.config
.ifdesc
.iInterface
= 0;
581 unit
->roothub
.config
.epdesc
.bLength
= sizeof(struct UsbStdEPDesc
);
582 unit
->roothub
.config
.epdesc
.bDescriptorType
= UDT_ENDPOINT
;
583 unit
->roothub
.config
.epdesc
.bEndpointAddress
= (URTF_IN
|1);
584 unit
->roothub
.config
.epdesc
.bmAttributes
= USEAF_INTERRUPT
;
585 unit
->roothub
.config
.epdesc
.wMaxPacketSize
= AROS_WORD2LE(4);
586 unit
->roothub
.config
.epdesc
.bInterval
= 12;
588 /* This is our root hub hub descriptor */
589 unit
->roothub
.sshubdesc
.bLength
= sizeof(struct UsbSSHubDesc
);
590 unit
->roothub
.sshubdesc
.bDescriptorType
= UDT_SSHUB
;
591 unit
->roothub
.sshubdesc
.bNbrPorts
= 1;
592 unit
->roothub
.sshubdesc
.wHubCharacteristics
= AROS_WORD2LE(UHCF_INDIVID_POWER
|UHCF_INDIVID_OVP
);
593 unit
->roothub
.sshubdesc
.bPwrOn2PwrGood
= 1;
594 unit
->roothub
.sshubdesc
.bHubContrCurrent
= 1;
595 unit
->roothub
.sshubdesc
.bHubHdrDecLat
= 0;
596 unit
->roothub
.sshubdesc
.wHubDelay
= 0;
597 unit
->roothub
.sshubdesc
.DeviceRemovable
= 0;
601 InitSemaphore(&unit
->ctrlxfer_queue_lock
);
602 InitSemaphore(&unit
->intrxfer_queue_lock
);
603 InitSemaphore(&unit
->bulkxfer_queue_lock
);
604 InitSemaphore(&unit
->isocxfer_queue_lock
);
606 InitSemaphore(&unit
->roothub
.intrxfer_queue_lock
);
608 /* Create periodic handler task */
609 if (-1 == (unit
->handler_task_sig_run
= AllocSignal(-1))) {
610 mybug_unit(-1, ("No signal bits available\n\n"));
612 mybug_unit(-1, ("allocated signal number %ld\n", unit
->handler_task_sig_run
));
615 unit
->handler_task
= NewCreateTask(TASKTAG_NAME
, "libusb handler task usb 3.0",
616 TASKTAG_PC
, handler_task
,
617 TASKTAG_ARG1
, FindTask(NULL
),
622 mybug_unit(-1, ("Waiting for %s handler task\n", unit
->name
));
623 Wait( (1L<<unit
->handler_task_sig_run
) );
624 mybug_unit(-1, ("%s handler task responded\n\n", unit
->name
));
625 //FreeSignal(unit->handler_task_sig_run);