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);
34 struct VUSBHCIUnit *VUSBHCI_AddNewUnit300(void);
37 static void handler_task(struct Task
*parent
, struct VUSBHCIUnit
*unit
) {
38 mybug_unit(-1,("Starting %s handler task\n", unit
->name
));
39 mybug_unit(-1, ("Sending signal number %ld\n", unit
->handler_task_sig_run
));
40 Signal(parent
, (1L<<unit
->handler_task_sig_run
) );
42 ULONG check_handler
= 0;
44 unit
->mp
= CreateMsgPort();
46 unit
->tr
= (struct timerequest
*)CreateIORequest(unit
->mp
, sizeof(struct timerequest
));
48 FreeSignal(unit
->mp
->mp_SigBit
);
49 if (!OpenDevice((STRPTR
)"timer.device", UNIT_MICROHZ
, (struct IORequest
*)unit
->tr
, 0)) {
50 /* Allocate a signal within this task context */
51 unit
->tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
= SIGB_SINGLE
;
52 unit
->tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigTask
= FindTask(NULL
);
53 /* Specify the request */
54 unit
->tr
->tr_node
.io_Command
= TR_ADDREQUEST
;
56 /* FIXME: Use signals */
58 //mybug(-1,("[handler_task] Ping...\n"));
60 if(!unit
->ctrlxfer_pending
) {
61 /* Try and get a lock on the semaphore, if not then just move on as some housekeeping is being done */
62 AttemptSemaphore(&unit
->ctrlxfer_queue_lock
); {
63 ForeachNode(&unit
->ctrlxfer_queue
, unit
->ioreq_ctrl
) {
64 /* Now the iorequest lives only on our pointer */
65 Remove(&unit
->ioreq_ctrl
->iouh_Req
.io_Message
.mn_Node
);
66 mybug(-1,("[handler_task] Control transfer caught...\n"));
67 unit
->ctrlxfer_pending
= TRUE
;
68 do_libusb_ctrl_transfer(unit
->ioreq_ctrl
);
70 } ReleaseSemaphore(&unit
->ctrlxfer_queue_lock
);
73 if(!unit
->intrxfer_pending
) {
74 AttemptSemaphore(&unit
->intrxfer_queue_lock
); {
75 ForeachNode(&unit
->intrxfer_queue
, unit
->ioreq_intr
) {
76 /* Now the iorequest lives only on our pointer */
77 Remove(&unit
->ioreq_intr
->iouh_Req
.io_Message
.mn_Node
);
78 unit
->intrxfer_pending
= TRUE
;
79 do_libusb_intr_transfer(unit
->ioreq_intr
);
81 } ReleaseSemaphore(&unit
->intrxfer_queue_lock
);
84 if(!unit
->bulkxfer_pending
) {
85 AttemptSemaphore(&unit
->bulkxfer_queue_lock
); {
86 ForeachNode(&unit
->bulkxfer_queue
, unit
->ioreq_bulk
) {
87 /* Now the iorequest lives only on our pointer */
88 Remove(&unit
->ioreq_bulk
->iouh_Req
.io_Message
.mn_Node
);
89 unit
->bulkxfer_pending
= TRUE
;
90 do_libusb_bulk_transfer(unit
->ioreq_bulk
);
92 } ReleaseSemaphore(&unit
->bulkxfer_queue_lock
);
95 if(!unit
->isocxfer_pending
) {
96 AttemptSemaphore(&unit
->isocxfer_queue_lock
); {
97 ForeachNode(&unit
->isocxfer_queue
, unit
->ioreq_isoc
) {
98 /* Now the iorequest lives only on our pointer */
99 Remove(&unit
->ioreq_isoc
->iouh_Req
.io_Message
.mn_Node
);
100 unit
->isocxfer_pending
= TRUE
;
101 do_libusb_isoc_transfer(unit
->ioreq_isoc
);
103 } ReleaseSemaphore(&unit
->isocxfer_queue_lock
);
107 if((check_handler
==0)|(unit
->ctrlxfer_pending
|unit
->intrxfer_pending
|unit
->bulkxfer_pending
|unit
->isocxfer_pending
)) {
109 call_libusb_event_handler();
114 unit
->tr
->tr_time
.tv_secs
= 0;
115 unit
->tr
->tr_time
.tv_micro
= 100000;
116 DoIO((struct IORequest
*)unit
->tr
);
118 if(check_handler
>0) {
122 CloseDevice((struct IORequest
*)unit
->tr
);
124 DeleteIORequest((struct IORequest
*)unit
->tr
);
125 unit
->mp
->mp_SigBit
= AllocSignal(-1);
127 DeleteMsgPort(unit
->mp
);
130 mybug(-1,("Exiting %s handler task\n", unit
->name
));
132 //Signal(parent, SIGF_CHILD);
135 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR VUSBHCIBase
) {
136 mybug(-1,("[VUSBHCI] Init: Entering function\n"));
138 if(!libusb_bridge_init(VUSBHCIBase
)) {
142 VUSBHCIBase
->usbunit200
= VUSBHCI_AddNewUnit200();
143 if(VUSBHCIBase
->usbunit200
== NULL
) {
144 mybug(-1, ("[VUSBHCI] Init: Failed to create new USB2.0 unit!\n"));
149 VUSBHCIBase->usbunit300 = VUSBHCI_AddNewUnit300();
150 if(VUSBHCIBase->usbunit300 == NULL) {
151 mybug(-1, ("[VUSBHCI] Init: Failed to create new USB3.0 unit!\n"));
158 static int GM_UNIQUENAME(Open
)(LIBBASETYPEPTR VUSBHCIBase
, struct IOUsbHWReq
*ioreq
, ULONG unitnum
, ULONG flags
) {
159 mybug(-1, ("[VUSBHCI] Open: Entering function\n"));
160 mybug(-1, ("[VUSBHCI] Open: Unit %d\n", unitnum
));
162 struct VUSBHCIUnit
*unit
;
164 /* Default to open failure. */
165 ioreq
->iouh_Req
.io_Error
= IOERR_OPENFAIL
;
166 ioreq
->iouh_Req
.io_Unit
= NULL
;
169 unit
= VUSBHCIBase
->usbunit200
;
171 } else if(unitnum == 1) {
172 unit = VUSBHCIBase->usbunit300;
178 if(ioreq
->iouh_Req
.io_Message
.mn_Length
< sizeof(struct IOUsbHWReq
)) {
179 mybug(-1, ("[VUSBHCI] Open: Invalid MN_LENGTH!\n"));
180 ioreq
->iouh_Req
.io_Error
= IOERR_BADLENGTH
;
183 ioreq
->iouh_Req
.io_Unit
= NULL
;
185 if(unit
->allocated
) {
186 ioreq
->iouh_Req
.io_Error
= IOERR_UNITBUSY
;
187 ioreq
->iouh_Req
.io_Unit
= NULL
;
188 mybug(-1, ("Unit already in use!\n\n"));
191 unit
->allocated
= TRUE
;
192 ioreq
->iouh_Req
.io_Unit
= (struct Unit
*) unit
;
195 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
196 ioreq
->iouh_Req
.io_Error
= 0;
203 static int GM_UNIQUENAME(Close
)(LIBBASETYPEPTR VUSBHCIBase
, struct IOUsbHWReq
*ioreq
) {
204 mybug(-1, ("[VUSBHCI] Close: Entering function\n"));
206 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*)ioreq
->iouh_Req
.io_Unit
;
208 mybug_unit(-1, ("Closing unit %p\n", unit
));
211 unit
->allocated
= FALSE
;
213 ioreq
->iouh_Req
.io_Unit
= (APTR
) -1;
214 ioreq
->iouh_Req
.io_Device
= (APTR
) -1;
219 ioreq
->iouh_Req
.io_Error
= IOERR_BADADDRESS
;
220 ioreq
->iouh_Req
.io_Unit
= (APTR
) -1;
221 ioreq
->iouh_Req
.io_Device
= (APTR
) -1;
223 mybug(-1, (" Bad unit structure in ioreq, nothing done!\n\n"));
227 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
228 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
229 ADD2CLOSEDEV(GM_UNIQUENAME(Close
), 0)
231 AROS_LH1(void, BeginIO
, AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
), struct VUSBHCIBase
*, VUSBHCIBase
, 5, VUSBHCI
) {
236 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
237 ioreq
->iouh_Req
.io_Error
= UHIOERR_NO_ERROR
;
239 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
241 mybug_unit(0, ("Entering function\n"));
245 switch (ioreq
->iouh_Req
.io_Command
) {
247 mybug_unit(-1, ("CMD_RESET\n"));
250 mybug_unit(-1, ("CMD_FLUSH\n"));
251 ret
= cmdFlush(ioreq
);
253 case UHCMD_QUERYDEVICE
:
254 mybug_unit(-1, ("UHCMD_QUERYDEVICE\n"));
255 ret
= cmdQueryDevice(ioreq
);
258 mybug_unit(0, ("UHCMD_USBRESET\n"));
259 ret
= cmdUsbReset(ioreq
);
261 case UHCMD_USBRESUME
:
262 mybug_unit(-1, ("UHCMD_USBRESUME\n"));
264 case UHCMD_USBSUSPEND
:
265 mybug_unit(-1, ("UHCMD_USBSUSPEND\n"));
268 mybug_unit(-1, ("UHCMD_USBOPER\n"));
269 //ret = cmdUsbOper(ioreq);
271 case UHCMD_CONTROLXFER
:
272 ret
= cmdControlXFer(ioreq
);
275 ret
= cmdIntXFer(ioreq
);
278 ret
= cmdBulkXFer(ioreq
);
281 ret
= cmdISOXFer(ioreq
);
284 /* Poseidon doesn't actually check this, ever... */
285 case NSCMD_DEVICEQUERY
:
286 mybug_unit(-1, ("NSCMD_DEVICEQUERY\n"));
288 static const UWORD NSDSupported
[] = {
289 CMD_FLUSH
, CMD_RESET
,
303 struct NSDeviceQueryResult
*nsdq
= (struct NSDeviceQueryResult
*)((struct IOStdReq
*)(ioreq
))->io_Data
;
304 nsdq
->DevQueryFormat
= 0;
305 nsdq
->SizeAvailable
= sizeof(struct NSDeviceQueryResult
);
306 nsdq
->DeviceType
= NSDEVTYPE_USBHARDWARE
;
307 nsdq
->DeviceSubType
= 0;
308 nsdq
->SupportedCommands
= (UWORD
*)NSDSupported
;
312 mybug_unit(-1, ("IOERR_NOCMD\n"));
317 /* We have aborted the request as unit is invalid */
321 if(ret
!= RC_DONTREPLY
) {
322 /* Set error codes */
324 ioreq
->iouh_Req
.io_Error
= ret
& 0xff;
326 /* Terminate the iorequest */
327 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
328 /* If not quick I/O, reply the message */
329 if(!(ioreq
->iouh_Req
.io_Flags
& IOF_QUICK
)) {
330 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
337 AROS_LH1(LONG
, AbortIO
, AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
), struct VUSBHCIBase
*, VUSBHCIBase
, 6, VUSBHCI
) {
339 mybug(-1, ("[VUSBHCI] AbortIO: Entering function\n"));
341 if(ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
) {
342 if(cmdAbortIO(ioreq
)) {
351 WORD
cmdQueryDevice(struct IOUsbHWReq
*ioreq
) {
352 struct VUSBHCIUnit
*unit
= (struct VUSBHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
354 mybug_unit(-1, ("Entering function\n"));
356 struct TagItem
*taglist
= (struct TagItem
*) ioreq
->iouh_Data
;
360 while((tag
= LibNextTagItem(&taglist
)) != NULL
) {
361 switch (tag
->ti_Tag
) {
362 case UHA_Manufacturer
:
363 *((STRPTR
*) tag
->ti_Data
) = "The AROS Development Team";
367 *((ULONG
*) tag
->ti_Data
) = VERSION_NUMBER
;
371 *((ULONG
*) tag
->ti_Data
) = REVISION_NUMBER
;
375 *((STRPTR
*) tag
->ti_Data
) = "©2015-2017 The AROS Development Team";
378 case UHA_ProductName
:
379 if(unit
->roothub
.devdesc
.bcdUSB
== AROS_WORD2LE(0x0200)) {
380 *((STRPTR
*) tag
->ti_Data
) = "VUSBHCI Host Controller USB2.0";
382 *((STRPTR
*) tag
->ti_Data
) = "VUSBHCI Host Controller USB3.0";
386 case UHA_Description
:
387 *((STRPTR
*) tag
->ti_Data
) = "Hosted Host Controller Interface (libusb)";
390 case UHA_Capabilities
:
391 if(unit
->roothub
.devdesc
.bcdUSB
== AROS_WORD2LE(0x0200)) {
392 *((ULONG
*) tag
->ti_Data
) = (UHCF_USB20
|UHCF_ISO
);
394 *((ULONG
*) tag
->ti_Data
) = (UHCF_USB30
|UHCF_ISO
);
403 mybug_unit(-1, ("Done\n\n"));
405 ioreq
->iouh_Actual
= count
;
409 struct VUSBHCIUnit
*VUSBHCI_AddNewUnit200(void) {
411 struct VUSBHCIUnit
*unit
;
413 static const char name
[] = {"[VUSBHCI2.00]"};
415 unit
= AllocVec(sizeof(struct VUSBHCIUnit
), MEMF_ANY
|MEMF_CLEAR
);
418 mybug(-1, ("[VUSBHCI] VUSBHCI_AddNewUnit: Failed to create new unit structure\n"));
421 unit
->state
= UHSF_SUSPENDED
;
422 unit
->allocated
= FALSE
;
424 unit
->ctrlxfer_pending
= FALSE
;
425 unit
->intrxfer_pending
= FALSE
;
426 unit
->bulkxfer_pending
= FALSE
;
427 unit
->isocxfer_pending
= FALSE
;
429 NEWLIST(&unit
->ctrlxfer_queue
);
430 NEWLIST(&unit
->intrxfer_queue
);
431 NEWLIST(&unit
->bulkxfer_queue
);
432 NEWLIST(&unit
->isocxfer_queue
);
434 NEWLIST(&unit
->roothub
.intrxfer_queue
);
436 /* This is our root hub device descriptor */
437 unit
->roothub
.devdesc
.bLength
= sizeof(struct UsbStdDevDesc
);
438 unit
->roothub
.devdesc
.bDescriptorType
= UDT_DEVICE
;
439 unit
->roothub
.devdesc
.bcdUSB
= AROS_WORD2LE(0x0200);
440 unit
->roothub
.devdesc
.bDeviceClass
= HUB_CLASSCODE
;
441 unit
->roothub
.devdesc
.bDeviceSubClass
= 0;
442 unit
->roothub
.devdesc
.bDeviceProtocol
= 0;
443 unit
->roothub
.devdesc
.bMaxPacketSize0
= 64; // Valid values are 8, 9(SuperSpeed), 16, 32, 64
444 unit
->roothub
.devdesc
.idVendor
= AROS_WORD2LE(0x0000);
445 unit
->roothub
.devdesc
.idProduct
= AROS_WORD2LE(0x0000);
446 unit
->roothub
.devdesc
.bcdDevice
= AROS_WORD2LE(0x0200);
447 unit
->roothub
.devdesc
.iManufacturer
= 1;
448 unit
->roothub
.devdesc
.iProduct
= 2;
449 unit
->roothub
.devdesc
.iSerialNumber
= 0;
450 unit
->roothub
.devdesc
.bNumConfigurations
= 1;
452 /* This is our root hub config descriptor */
453 unit
->roothub
.config
.cfgdesc
.bLength
= sizeof(struct UsbStdCfgDesc
);
454 unit
->roothub
.config
.cfgdesc
.bLength
= sizeof(struct UsbStdCfgDesc
);
455 unit
->roothub
.config
.cfgdesc
.bDescriptorType
= UDT_CONFIGURATION
;
456 unit
->roothub
.config
.cfgdesc
.wTotalLength
= AROS_WORD2LE(sizeof(struct RHConfig
));
457 unit
->roothub
.config
.cfgdesc
.bNumInterfaces
= 1;
458 unit
->roothub
.config
.cfgdesc
.bConfigurationValue
= 1;
459 unit
->roothub
.config
.cfgdesc
.iConfiguration
= 0;
460 unit
->roothub
.config
.cfgdesc
.bmAttributes
= (USCAF_SELF_POWERED
);
461 unit
->roothub
.config
.cfgdesc
.bMaxPower
= 0;
463 unit
->roothub
.config
.ifdesc
.bLength
= sizeof(struct UsbStdIfDesc
);
464 unit
->roothub
.config
.ifdesc
.bDescriptorType
= UDT_INTERFACE
;
465 unit
->roothub
.config
.ifdesc
.bInterfaceNumber
= 0;
466 unit
->roothub
.config
.ifdesc
.bAlternateSetting
= 0;
467 unit
->roothub
.config
.ifdesc
.bNumEndpoints
= 1;
468 unit
->roothub
.config
.ifdesc
.bInterfaceClass
= HUB_CLASSCODE
;
469 unit
->roothub
.config
.ifdesc
.bInterfaceSubClass
= 0;
470 unit
->roothub
.config
.ifdesc
.bInterfaceProtocol
= 0;
471 unit
->roothub
.config
.ifdesc
.iInterface
= 0;
473 unit
->roothub
.config
.epdesc
.bLength
= sizeof(struct UsbStdEPDesc
);
474 unit
->roothub
.config
.epdesc
.bDescriptorType
= UDT_ENDPOINT
;
475 unit
->roothub
.config
.epdesc
.bEndpointAddress
= (URTF_IN
|1);
476 unit
->roothub
.config
.epdesc
.bmAttributes
= USEAF_INTERRUPT
;
477 unit
->roothub
.config
.epdesc
.wMaxPacketSize
= AROS_WORD2LE(4);
478 unit
->roothub
.config
.epdesc
.bInterval
= 12;
480 /* This is our root hub hub descriptor */
481 unit
->roothub
.hubdesc
.bLength
= sizeof(struct UsbHubDesc
);
482 unit
->roothub
.hubdesc
.bDescriptorType
= UDT_HUB
;
483 unit
->roothub
.hubdesc
.bNbrPorts
= 1;
484 unit
->roothub
.hubdesc
.wHubCharacteristics
= AROS_WORD2LE(UHCF_INDIVID_POWER
|UHCF_INDIVID_OVP
);
485 unit
->roothub
.hubdesc
.bPwrOn2PwrGood
= 1;
486 unit
->roothub
.hubdesc
.bHubContrCurrent
= 1;
487 unit
->roothub
.hubdesc
.DeviceRemovable
= 0;
488 unit
->roothub
.hubdesc
.PortPwrCtrlMask
= (1<<1);
490 //unit->roothub.portstatus.wPortStatus = 0;
491 //unit->roothub.portstatus.wPortChange = 0;
493 //unit->roothub.hubstatus->wHubStatus = 0;
494 //unit->roothub.hubstatus->wHubChange = 0;
498 InitSemaphore(&unit
->ctrlxfer_queue_lock
);
499 InitSemaphore(&unit
->intrxfer_queue_lock
);
500 InitSemaphore(&unit
->bulkxfer_queue_lock
);
501 InitSemaphore(&unit
->isocxfer_queue_lock
);
503 InitSemaphore(&unit
->roothub
.intrxfer_queue_lock
);
505 /* Create periodic handler task */
506 if (-1 == (unit
->handler_task_sig_run
= AllocSignal(-1))) {
507 mybug_unit(-1, ("No signal bits available\n\n"));
509 mybug_unit(-1, ("allocated signal number %ld\n", unit
->handler_task_sig_run
));
512 unit
->handler_task
= NewCreateTask(TASKTAG_NAME
, "libusb handler task usb 2.0",
513 TASKTAG_PC
, handler_task
,
514 TASKTAG_ARG1
, FindTask(NULL
),
519 mybug_unit(-1, ("Waiting for %s handler task\n", unit
->name
));
520 Wait( (1L<<unit
->handler_task_sig_run
) );
521 mybug_unit(-1, ("%s handler task responded\n\n", unit
->name
));
522 //FreeSignal(unit->handler_task_sig_run);
528 struct VUSBHCIUnit
*VUSBHCI_AddNewUnit300(void) {
530 struct VUSBHCIUnit
*unit
;
532 static const char name
[] = {"[VUSBHCI3.00]"};
534 unit
= AllocVec(sizeof(struct VUSBHCIUnit
), MEMF_ANY
|MEMF_CLEAR
);
537 mybug(-1, ("[VUSBHCI] VUSBHCI_AddNewUnit: Failed to create new unit structure\n"));
540 unit
->state
= UHSF_SUSPENDED
;
541 unit
->allocated
= FALSE
;
543 NEWLIST(&unit
->ctrlxfer_queue
);
544 NEWLIST(&unit
->intrxfer_queue
);
545 NEWLIST(&unit
->bulkxfer_queue
);
546 NEWLIST(&unit
->isocxfer_queue
);
548 NEWLIST(&unit
->roothub
.intrxfer_queue
);
550 /* This is our root hub device descriptor */
551 unit
->roothub
.devdesc
.bLength
= sizeof(struct UsbStdDevDesc
);
552 unit
->roothub
.devdesc
.bDescriptorType
= UDT_DEVICE
;
553 unit
->roothub
.devdesc
.bcdUSB
= AROS_WORD2LE(0x0300);
554 unit
->roothub
.devdesc
.bDeviceClass
= HUB_CLASSCODE
;
555 unit
->roothub
.devdesc
.bDeviceSubClass
= 0;
556 unit
->roothub
.devdesc
.bDeviceProtocol
= 0;
557 unit
->roothub
.devdesc
.bMaxPacketSize0
= 9; // Valid values are 8, 9(SuperSpeed), 16, 32, 64
558 unit
->roothub
.devdesc
.idVendor
= AROS_WORD2LE(0x0000);
559 unit
->roothub
.devdesc
.idProduct
= AROS_WORD2LE(0x0000);
560 unit
->roothub
.devdesc
.bcdDevice
= AROS_WORD2LE(0x0300);
561 unit
->roothub
.devdesc
.iManufacturer
= 1;
562 unit
->roothub
.devdesc
.iProduct
= 2;
563 unit
->roothub
.devdesc
.iSerialNumber
= 0;
564 unit
->roothub
.devdesc
.bNumConfigurations
= 1;
566 /* This is our root hub config descriptor */
567 unit
->roothub
.config
.cfgdesc
.bLength
= sizeof(struct UsbStdCfgDesc
);
568 unit
->roothub
.config
.cfgdesc
.bLength
= sizeof(struct UsbStdCfgDesc
);
569 unit
->roothub
.config
.cfgdesc
.bDescriptorType
= UDT_CONFIGURATION
;
570 unit
->roothub
.config
.cfgdesc
.wTotalLength
= AROS_WORD2LE(sizeof(struct RHConfig
));
571 unit
->roothub
.config
.cfgdesc
.bNumInterfaces
= 1;
572 unit
->roothub
.config
.cfgdesc
.bConfigurationValue
= 1;
573 unit
->roothub
.config
.cfgdesc
.iConfiguration
= 0;
574 unit
->roothub
.config
.cfgdesc
.bmAttributes
= (USCAF_SELF_POWERED
);
575 unit
->roothub
.config
.cfgdesc
.bMaxPower
= 0;
577 unit
->roothub
.config
.ifdesc
.bLength
= sizeof(struct UsbStdIfDesc
);
578 unit
->roothub
.config
.ifdesc
.bDescriptorType
= UDT_INTERFACE
;
579 unit
->roothub
.config
.ifdesc
.bInterfaceNumber
= 0;
580 unit
->roothub
.config
.ifdesc
.bAlternateSetting
= 0;
581 unit
->roothub
.config
.ifdesc
.bNumEndpoints
= 1;
582 unit
->roothub
.config
.ifdesc
.bInterfaceClass
= HUB_CLASSCODE
;
583 unit
->roothub
.config
.ifdesc
.bInterfaceSubClass
= 0;
584 unit
->roothub
.config
.ifdesc
.bInterfaceProtocol
= 0;
585 unit
->roothub
.config
.ifdesc
.iInterface
= 0;
587 unit
->roothub
.config
.epdesc
.bLength
= sizeof(struct UsbStdEPDesc
);
588 unit
->roothub
.config
.epdesc
.bDescriptorType
= UDT_ENDPOINT
;
589 unit
->roothub
.config
.epdesc
.bEndpointAddress
= (URTF_IN
|1);
590 unit
->roothub
.config
.epdesc
.bmAttributes
= USEAF_INTERRUPT
;
591 unit
->roothub
.config
.epdesc
.wMaxPacketSize
= AROS_WORD2LE(4);
592 unit
->roothub
.config
.epdesc
.bInterval
= 12;
594 /* This is our root hub hub descriptor */
595 unit
->roothub
.sshubdesc
.bLength
= sizeof(struct UsbSSHubDesc
);
596 unit
->roothub
.sshubdesc
.bDescriptorType
= UDT_SSHUB
;
597 unit
->roothub
.sshubdesc
.bNbrPorts
= 1;
598 unit
->roothub
.sshubdesc
.wHubCharacteristics
= AROS_WORD2LE(UHCF_INDIVID_POWER
|UHCF_INDIVID_OVP
);
599 unit
->roothub
.sshubdesc
.bPwrOn2PwrGood
= 1;
600 unit
->roothub
.sshubdesc
.bHubContrCurrent
= 1;
601 unit
->roothub
.sshubdesc
.bHubHdrDecLat
= 0;
602 unit
->roothub
.sshubdesc
.wHubDelay
= 0;
603 unit
->roothub
.sshubdesc
.DeviceRemovable
= 0;
607 InitSemaphore(&unit
->ctrlxfer_queue_lock
);
608 InitSemaphore(&unit
->intrxfer_queue_lock
);
609 InitSemaphore(&unit
->bulkxfer_queue_lock
);
610 InitSemaphore(&unit
->isocxfer_queue_lock
);
612 InitSemaphore(&unit
->roothub
.intrxfer_queue_lock
);
614 /* Create periodic handler task */
615 if (-1 == (unit
->handler_task_sig_run
= AllocSignal(-1))) {
616 mybug_unit(-1, ("No signal bits available\n\n"));
618 mybug_unit(-1, ("allocated signal number %ld\n", unit
->handler_task_sig_run
));
621 unit
->handler_task
= NewCreateTask(TASKTAG_NAME
, "libusb handler task usb 3.0",
622 TASKTAG_PC
, handler_task
,
623 TASKTAG_ARG1
, FindTask(NULL
),
628 mybug_unit(-1, ("Waiting for %s handler task\n", unit
->name
));
629 Wait( (1L<<unit
->handler_task_sig_run
) );
630 mybug_unit(-1, ("%s handler task responded\n\n", unit
->name
));
631 //FreeSignal(unit->handler_task_sig_run);