Try and get a lock on the semaphore, if not then just move on as some housekeeping...
[AROS.git] / rom / usb / vusbhc / vusbhci_device.c
blob4fec18c78cb0823ad7ccba8a23c9e23e76e703bd
1 /*
2 Copyright © 2015-2018, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Virtual 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>
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();
43 if (unit->mp) {
44 unit->tr = (struct timerequest *)CreateIORequest(unit->mp, sizeof(struct timerequest));
45 if (unit->tr) {
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 */
55 while(1) {
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);
104 //Forbid();
105 if((check_handler==0)|(unit->ctrlxfer_pending|unit->intrxfer_pending|unit->bulkxfer_pending|unit->isocxfer_pending)) {
106 check_handler = 10;
107 call_libusb_event_handler();
109 //Permit();
111 /* Wait */
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) {
117 check_handler--;
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)) {
137 return FALSE;
140 VUSBHCIBase->usbunit200 = VUSBHCI_AddNewUnit200();
141 if(VUSBHCIBase->usbunit200 == NULL) {
142 mybug(-1, ("[VUSBHCI] Init: Failed to create new USB2.0 unit!\n"));
143 return FALSE;
146 VUSBHCIBase->usbunit300 = VUSBHCI_AddNewUnit300();
147 if(VUSBHCIBase->usbunit300 == NULL) {
148 mybug(-1, ("[VUSBHCI] Init: Failed to create new USB3.0 unit!\n"));
149 return FALSE;
152 return TRUE;
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;
165 if(unitnum == 0) {
166 unit = VUSBHCIBase->usbunit200;
167 } else if(unitnum == 1) {
168 unit = VUSBHCIBase->usbunit300;
169 } else {
170 return FALSE;
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"));
184 return FALSE;
185 } else {
186 unit->allocated = TRUE;
187 ioreq->iouh_Req.io_Unit = (struct Unit *) unit;
189 /* Opened ok! */
190 ioreq->iouh_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
191 ioreq->iouh_Req.io_Error = 0;
192 return TRUE;
195 return FALSE;
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));
205 if(unit) {
206 unit->allocated = FALSE;
208 ioreq->iouh_Req.io_Unit = (APTR) -1;
209 ioreq->iouh_Req.io_Device = (APTR) -1;
211 return TRUE;
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"));
219 return FALSE;
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) {
227 AROS_LIBFUNC_INIT
229 WORD ret = RC_OK;
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"));
238 if(unit != NULL) {
240 switch (ioreq->iouh_Req.io_Command) {
241 case CMD_RESET:
242 mybug_unit(-1, ("CMD_RESET\n"));
243 break;
244 case CMD_FLUSH:
245 mybug_unit(-1, ("CMD_FLUSH\n"));
246 break;
247 case UHCMD_QUERYDEVICE:
248 mybug_unit(-1, ("UHCMD_QUERYDEVICE\n"));
249 ret = cmdQueryDevice(ioreq);
250 break;
251 case UHCMD_USBRESET:
252 mybug_unit(0, ("UHCMD_USBRESET\n"));
253 ret = cmdUsbReset(ioreq);
254 break;
255 case UHCMD_USBRESUME:
256 mybug_unit(-1, ("UHCMD_USBRESUME\n"));
257 break;
258 case UHCMD_USBSUSPEND:
259 mybug_unit(-1, ("UHCMD_USBSUSPEND\n"));
260 break;
261 case UHCMD_USBOPER:
262 mybug_unit(-1, ("UHCMD_USBOPER\n"));
263 //ret = cmdUsbOper(ioreq);
264 break;
265 case UHCMD_CONTROLXFER:
266 ret = cmdControlXFer(ioreq);
267 break;
268 case UHCMD_INTXFER:
269 ret = cmdIntXFer(ioreq);
270 break;
271 case UHCMD_BULKXFER:
272 ret = cmdBulkXFer(ioreq);
273 break;
274 case UHCMD_ISOXFER:
275 ret = cmdISOXFer(ioreq);
276 break;
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,
284 UHCMD_QUERYDEVICE,
285 UHCMD_USBRESET,
286 UHCMD_USBRESUME,
287 UHCMD_USBSUSPEND,
288 UHCMD_USBOPER,
289 UHCMD_CONTROLXFER ,
290 UHCMD_ISOXFER,
291 UHCMD_INTXFER,
292 UHCMD_BULKXFER,
293 NSCMD_DEVICEQUERY,
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;
303 ret = RC_OK;
304 break;
305 default:
306 mybug_unit(-1, ("IOERR_NOCMD\n"));
307 ret = IOERR_NOCMD;
308 break;
310 } else {
311 /* We have aborted the request as unit is invalid */
312 ret = IOERR_ABORTED;
315 if(ret != RC_DONTREPLY) {
316 /* Set error codes */
317 if (ret != RC_OK) {
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);
328 AROS_LIBFUNC_EXIT
331 AROS_LH1(LONG, AbortIO, AROS_LHA(struct IOUsbHWReq *, ioreq, A1), struct VUSBHCIBase *, VUSBHCIBase, 6, VUSBHCI) {
332 AROS_LIBFUNC_INIT
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)) {
337 return(0);
341 return(-1);
342 AROS_LIBFUNC_EXIT
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;
351 struct TagItem *tag;
352 ULONG count = 0;
354 while((tag = LibNextTagItem(&taglist)) != NULL) {
355 switch (tag->ti_Tag) {
356 case UHA_Manufacturer:
357 *((STRPTR *) tag->ti_Data) = "The AROS Development Team";
358 count++;
359 break;
360 case UHA_Version:
361 *((ULONG *) tag->ti_Data) = VERSION_NUMBER;
362 count++;
363 break;
364 case UHA_Revision:
365 *((ULONG *) tag->ti_Data) = REVISION_NUMBER;
366 count++;
367 break;
368 case UHA_Copyright:
369 *((STRPTR *) tag->ti_Data) = "©2015-2017 The AROS Development Team";
370 count++;
371 break;
372 case UHA_ProductName:
373 if(unit->roothub.devdesc.bcdUSB == AROS_WORD2LE(0x0200)) {
374 *((STRPTR *) tag->ti_Data) = "VUSBHCI Host Controller USB2.0";
375 } else {
376 *((STRPTR *) tag->ti_Data) = "VUSBHCI Host Controller USB3.0";
378 count++;
379 break;
380 case UHA_Description:
381 *((STRPTR *) tag->ti_Data) = "Hosted Host Controller Interface (libusb)";
382 count++;
383 break;
384 case UHA_Capabilities:
385 if(unit->roothub.devdesc.bcdUSB == AROS_WORD2LE(0x0200)) {
386 *((ULONG *) tag->ti_Data) = (UHCF_USB20|UHCF_ISO);
387 } else {
388 *((ULONG *) tag->ti_Data) = (UHCF_USB30|UHCF_ISO);
390 count++;
391 break;
392 default:
393 break;
397 mybug_unit(-1, ("Done\n\n"));
399 ioreq->iouh_Actual = count;
400 return RC_OK;
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);
411 if(unit == NULL) {
412 mybug(-1, ("[VUSBHCI] VUSBHCI_AddNewUnit: Failed to create new unit structure\n"));
413 return NULL;
414 } else {
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;
490 unit->name = name;
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"));
502 } else {
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),
509 TASKTAG_ARG2, unit,
510 TASKTAG_PRI, 5,
511 TAG_END);
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);
518 return unit;
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);
530 if(unit == NULL) {
531 mybug(-1, ("[VUSBHCI] VUSBHCI_AddNewUnit: Failed to create new unit structure\n"));
532 return NULL;
533 } else {
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;
599 unit->name = name;
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"));
611 } else {
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),
618 TASKTAG_ARG2, unit,
619 TASKTAG_PRI, 5,
620 TAG_END);
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);
627 return unit;