revert between 56095 -> 55830 in arch
[AROS.git] / rom / usb / vusbhc / vusbhci_device.c
blob92f3847c4836fa9e0e95e6ee5011176999128189
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);
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();
45 if (unit->mp) {
46 unit->tr = (struct timerequest *)CreateIORequest(unit->mp, sizeof(struct timerequest));
47 if (unit->tr) {
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 */
57 while(1) {
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);
106 //Forbid();
107 if((check_handler==0)|(unit->ctrlxfer_pending|unit->intrxfer_pending|unit->bulkxfer_pending|unit->isocxfer_pending)) {
108 check_handler = 10;
109 call_libusb_event_handler();
111 //Permit();
113 /* Wait */
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) {
119 check_handler--;
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)) {
139 return FALSE;
142 VUSBHCIBase->usbunit200 = VUSBHCI_AddNewUnit200();
143 if(VUSBHCIBase->usbunit200 == NULL) {
144 mybug(-1, ("[VUSBHCI] Init: Failed to create new USB2.0 unit!\n"));
145 return FALSE;
149 VUSBHCIBase->usbunit300 = VUSBHCI_AddNewUnit300();
150 if(VUSBHCIBase->usbunit300 == NULL) {
151 mybug(-1, ("[VUSBHCI] Init: Failed to create new USB3.0 unit!\n"));
152 return FALSE;
155 return TRUE;
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;
168 if(unitnum == 0) {
169 unit = VUSBHCIBase->usbunit200;
171 } else if(unitnum == 1) {
172 unit = VUSBHCIBase->usbunit300;
174 } else {
175 return FALSE;
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"));
189 return FALSE;
190 } else {
191 unit->allocated = TRUE;
192 ioreq->iouh_Req.io_Unit = (struct Unit *) unit;
194 /* Opened ok! */
195 ioreq->iouh_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
196 ioreq->iouh_Req.io_Error = 0;
197 return TRUE;
200 return FALSE;
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));
210 if(unit) {
211 unit->allocated = FALSE;
213 ioreq->iouh_Req.io_Unit = (APTR) -1;
214 ioreq->iouh_Req.io_Device = (APTR) -1;
216 return TRUE;
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"));
224 return FALSE;
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) {
232 AROS_LIBFUNC_INIT
234 WORD ret = RC_OK;
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"));
243 if(unit != NULL) {
245 switch (ioreq->iouh_Req.io_Command) {
246 case CMD_RESET:
247 mybug_unit(-1, ("CMD_RESET\n"));
248 break;
249 case CMD_FLUSH:
250 mybug_unit(-1, ("CMD_FLUSH\n"));
251 ret = cmdFlush(ioreq);
252 break;
253 case UHCMD_QUERYDEVICE:
254 mybug_unit(-1, ("UHCMD_QUERYDEVICE\n"));
255 ret = cmdQueryDevice(ioreq);
256 break;
257 case UHCMD_USBRESET:
258 mybug_unit(0, ("UHCMD_USBRESET\n"));
259 ret = cmdUsbReset(ioreq);
260 break;
261 case UHCMD_USBRESUME:
262 mybug_unit(-1, ("UHCMD_USBRESUME\n"));
263 break;
264 case UHCMD_USBSUSPEND:
265 mybug_unit(-1, ("UHCMD_USBSUSPEND\n"));
266 break;
267 case UHCMD_USBOPER:
268 mybug_unit(-1, ("UHCMD_USBOPER\n"));
269 //ret = cmdUsbOper(ioreq);
270 break;
271 case UHCMD_CONTROLXFER:
272 ret = cmdControlXFer(ioreq);
273 break;
274 case UHCMD_INTXFER:
275 ret = cmdIntXFer(ioreq);
276 break;
277 case UHCMD_BULKXFER:
278 ret = cmdBulkXFer(ioreq);
279 break;
280 case UHCMD_ISOXFER:
281 ret = cmdISOXFer(ioreq);
282 break;
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,
290 UHCMD_QUERYDEVICE,
291 UHCMD_USBRESET,
292 UHCMD_USBRESUME,
293 UHCMD_USBSUSPEND,
294 UHCMD_USBOPER,
295 UHCMD_CONTROLXFER ,
296 UHCMD_ISOXFER,
297 UHCMD_INTXFER,
298 UHCMD_BULKXFER,
299 NSCMD_DEVICEQUERY,
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;
309 ret = RC_OK;
310 break;
311 default:
312 mybug_unit(-1, ("IOERR_NOCMD\n"));
313 ret = IOERR_NOCMD;
314 break;
316 } else {
317 /* We have aborted the request as unit is invalid */
318 ret = IOERR_ABORTED;
321 if(ret != RC_DONTREPLY) {
322 /* Set error codes */
323 if (ret != RC_OK) {
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);
334 AROS_LIBFUNC_EXIT
337 AROS_LH1(LONG, AbortIO, AROS_LHA(struct IOUsbHWReq *, ioreq, A1), struct VUSBHCIBase *, VUSBHCIBase, 6, VUSBHCI) {
338 AROS_LIBFUNC_INIT
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)) {
343 return(0);
347 return(-1);
348 AROS_LIBFUNC_EXIT
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;
357 struct TagItem *tag;
358 ULONG count = 0;
360 while((tag = LibNextTagItem(&taglist)) != NULL) {
361 switch (tag->ti_Tag) {
362 case UHA_Manufacturer:
363 *((STRPTR *) tag->ti_Data) = "The AROS Development Team";
364 count++;
365 break;
366 case UHA_Version:
367 *((ULONG *) tag->ti_Data) = VERSION_NUMBER;
368 count++;
369 break;
370 case UHA_Revision:
371 *((ULONG *) tag->ti_Data) = REVISION_NUMBER;
372 count++;
373 break;
374 case UHA_Copyright:
375 *((STRPTR *) tag->ti_Data) = "©2015-2017 The AROS Development Team";
376 count++;
377 break;
378 case UHA_ProductName:
379 if(unit->roothub.devdesc.bcdUSB == AROS_WORD2LE(0x0200)) {
380 *((STRPTR *) tag->ti_Data) = "VUSBHCI Host Controller USB2.0";
381 } else {
382 *((STRPTR *) tag->ti_Data) = "VUSBHCI Host Controller USB3.0";
384 count++;
385 break;
386 case UHA_Description:
387 *((STRPTR *) tag->ti_Data) = "Hosted Host Controller Interface (libusb)";
388 count++;
389 break;
390 case UHA_Capabilities:
391 if(unit->roothub.devdesc.bcdUSB == AROS_WORD2LE(0x0200)) {
392 *((ULONG *) tag->ti_Data) = (UHCF_USB20|UHCF_ISO);
393 } else {
394 *((ULONG *) tag->ti_Data) = (UHCF_USB30|UHCF_ISO);
396 count++;
397 break;
398 default:
399 break;
403 mybug_unit(-1, ("Done\n\n"));
405 ioreq->iouh_Actual = count;
406 return RC_OK;
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);
417 if(unit == NULL) {
418 mybug(-1, ("[VUSBHCI] VUSBHCI_AddNewUnit: Failed to create new unit structure\n"));
419 return NULL;
420 } else {
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;
496 unit->name = name;
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"));
508 } else {
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),
515 TASKTAG_ARG2, unit,
516 TASKTAG_PRI, 5,
517 TAG_END);
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);
524 return unit;
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);
536 if(unit == NULL) {
537 mybug(-1, ("[VUSBHCI] VUSBHCI_AddNewUnit: Failed to create new unit structure\n"));
538 return NULL;
539 } else {
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;
605 unit->name = name;
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"));
617 } else {
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),
624 TASKTAG_ARG2, unit,
625 TASKTAG_PRI, 5,
626 TAG_END);
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);
633 return unit;