Added a test for MUIA_Listview_SelectChange.
[AROS.git] / workbench / devs / USB / stack / usbhubclass.c
blob1c4e7f8406ae9987c0993abbb93e801c5c1b8276
1 /*
2 Copyright (C) 2006 by Michal Schulz
3 $Id$
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this program; if not, write to the
17 Free Software Foundation, Inc.,
18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * CHANGELOG:
22 * DATE NAME ENTRY
23 * ---------- ------------------ -------------------------------------------------------------------
24 * 2009-03-07 T. Wiszkowski Taught hub to re-attempt device discovery at later time
25 * if no suitable driver is present initially
26 * 2008-06-02 T. Wiszkowski Updated device detection mechanism so the stack is aware of already
27 * connected devices
30 #define DEBUG 0
32 #include <inttypes.h>
34 #include <aros/debug.h>
36 #include <exec/types.h>
37 #include <oop/oop.h>
39 #include <hidd/hidd.h>
40 #include <usb/usb.h>
41 #include <usb/usb_core.h>
43 #include <dos/dos.h>
44 #include <dos/dosextens.h>
46 #include <devices/timer.h>
48 #include <proto/oop.h>
49 #include <proto/utility.h>
50 #include <proto/dos.h>
52 #include <stdio.h>
54 #include "usb.h"
55 #include "misc.h"
57 #define STACK_SIZE 10240
59 static void hub_process();
62 * The HubInterrupt() is a tiny software interrupt routine that signals the
63 * hub process about the need of hub exploration
65 AROS_INTH1(HubInterrupt, HubData *, hub)
67 AROS_INTFUNC_INIT
69 /* Signal the HUB process about incoming interrupt */
70 if (hub->hub_task)
71 Signal(hub->hub_task, 1 << hub->sigInterrupt);
73 return FALSE;
75 AROS_INTFUNC_EXIT
79 * Initialize HUB class properly. Find out all relevant data and start the
80 * HUB process.
82 OOP_Object *METHOD(USBHub, Root, New)
84 struct Task *t;
85 struct MemList *ml;
87 D(bug("[USB] USBHub::New()\n"));
89 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
90 if (o)
92 HubData *hub = OOP_INST_DATA(cl, o);
93 char *name;
95 /* HUB devices do need a bit longer timeout than anything else */
96 HIDD_USBDevice_SetTimeout(o, NULL, 5000);
98 hub->root = GetTagData(aHidd_USBHub_IsRoot, FALSE, msg->attrList);
99 hub->enabled = FALSE;
100 hub->got_descriptor = FALSE;
102 OOP_GetAttr(o, aHidd_USBDevice_ProductName, (intptr_t *)&name);
104 hub->got_descriptor = HIDD_USBHub_GetHubDescriptor(o, &hub->descriptor);
106 if (hub->got_descriptor)
107 DumpDescriptor((usb_descriptor_t *)&hub->descriptor);
108 else
110 D(bug("[USBHub] HUB descriptor not present. I will try later...\n"));
111 hub->descriptor.bNbrPorts = GetTagData(aHidd_USBHub_NumPorts, 1, msg->attrList);
114 D(bug("[USBHub] %s hub with %d ports\n",
115 hub->root ? "Root" : "A", hub->descriptor.bNbrPorts));
117 hub->children = AllocVecPooled(SD(cl)->MemPool, hub->descriptor.bNbrPorts * sizeof(OOP_Object *));
119 D(bug("[USB] USBHub has name \"%s\"\n", name));
121 hub->sd = SD(cl);
122 hub->hub_name = name ? name : "unknown";
123 hub->proc_name = AllocVecPooled(SD(cl)->MemPool, 10 + strlen(name ? name : "unknown"));
125 sprintf(hub->proc_name, "USBHub (%s)", name ? name : "unknown");
127 HIDD_USBDevice_Configure(o, 0);
129 usb_endpoint_descriptor_t *ep = HIDD_USBDevice_GetEndpoint(o, 0, 0);
131 D(bug("[USBHub] Endpoint descriptor %p\n", ep));
133 if (ep)
135 DumpDescriptor((usb_descriptor_t *)ep);
137 if ((ep->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT)
139 bug("[USBHub] Wrong endpoint type\n");
140 HIDD_USBDevice_Configure(o, USB_UNCONFIG_INDEX);
141 // TODO: unconfigure, error, coercemethod
144 OOP_Object *drv = NULL;
145 OOP_GetAttr(o, aHidd_USBDevice_Bus, (IPTR *)&drv);
147 if (drv)
149 hub->interrupt.is_Data = hub;
150 hub->interrupt.is_Code = (VOID_FUNC)HubInterrupt;
151 hub->intr_pipe = HIDD_USBDevice_CreatePipe(o, PIPE_Interrupt, ep->bEndpointAddress, ep->bInterval, AROS_LE2WORD(ep->wMaxPacketSize), 0);
152 // HIDD_USBDrv_AddInterrupt(drv, hub->intr_pipe, &hub->status[0], AROS_LE2WORD(ep->wMaxPacketSize), &hub->interrupt);
153 HIDD_USBDrv_AddInterrupt(drv, hub->intr_pipe, &hub->status[0], 1, &hub->interrupt);
158 struct TagItem tags[] = {
159 { TASKTAG_ARG1, (IPTR)hub },
160 { TASKTAG_ARG2, (IPTR)o },
161 { TASKTAG_ARG3, (IPTR)FindTask(NULL) },
162 { TAG_DONE, 0UL },
165 t = AllocMem(sizeof(struct Task), MEMF_PUBLIC|MEMF_CLEAR);
166 ml = AllocMem(sizeof(struct MemList) + sizeof(struct MemEntry), MEMF_PUBLIC|MEMF_CLEAR);
168 if (t && ml)
170 char *sp = AllocMem(STACK_SIZE, MEMF_PUBLIC|MEMF_CLEAR);
171 t->tc_SPLower = sp;
172 t->tc_SPUpper = sp + STACK_SIZE;
173 #if AROS_STACK_GROWS_DOWNWARDS
174 t->tc_SPReg = (char *)t->tc_SPUpper - SP_OFFSET;
175 #else
176 t->tc_SPReg = (char *)t->tc_SPLower + SP_OFFSET;
177 #endif
179 ml->ml_NumEntries = 2;
180 ml->ml_ME[0].me_Addr = t;
181 ml->ml_ME[0].me_Length = sizeof(struct Task);
182 ml->ml_ME[1].me_Addr = sp;
183 ml->ml_ME[1].me_Length = STACK_SIZE;
185 NEWLIST(&t->tc_MemEntry);
186 ADDHEAD(&t->tc_MemEntry, &ml->ml_Node);
188 t->tc_Node.ln_Name = hub->proc_name;
189 t->tc_Node.ln_Type = NT_TASK;
190 t->tc_Node.ln_Pri = 0;
192 NewAddTask(t, hub_process, NULL, &tags[0]);
193 hub->hub_task = t;
196 Wait(SIGF_SINGLE);
199 D(bug("[USB] USBHub::New() = %p\n",o));
201 return o;
204 void METHOD(USBHub, Root, Dispose)
206 D(bug("[USB] USBHub::Dispose\n"));
207 HubData *hub = OOP_INST_DATA(cl, o);
208 struct usbEvent message;
210 message.ev_Message.mn_ReplyPort = CreateMsgPort();
211 message.ev_Type = evt_Cleanup;
213 PutMsg(hub->hub_port, (struct Message *)&message);
214 WaitPort(message.ev_Message.mn_ReplyPort);
215 DeleteMsgPort(message.ev_Message.mn_ReplyPort);
217 FreeVecPooled(SD(cl)->MemPool, hub->children);
218 FreeVecPooled(SD(cl)->MemPool, hub->proc_name);
220 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
223 void METHOD(USBHub, Root, Get)
225 uint32_t idx;
226 HubData *hub = OOP_INST_DATA(cl, o);
228 if (IS_USBHUB_ATTR(msg->attrID, idx))
230 switch (idx)
232 case aoHidd_USBHub_IsRoot:
233 *msg->storage = hub->root;
234 break;
235 case aoHidd_USBHub_IsCompound:
236 *msg->storage = 0;
237 break;
238 case aoHidd_USBHub_HubCurrent:
239 *msg->storage = 0;
240 break;
241 case aoHidd_USBHub_NumPorts:
242 *msg->storage = hub->descriptor.bNbrPorts;
243 break;
244 default:
245 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
248 else
249 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
252 void METHOD(USBHub, Root, Set)
254 uint32_t idx;
255 struct TagItem *tag;
256 struct TagItem *tags = msg->attrList;
258 while ((tag = NextTagItem(&tags)))
260 if (IS_USBHUB_ATTR(tag->ti_Tag, idx))
266 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
269 OOP_Object * METHOD(USBHub, Hidd_USBHub, GetChild)
271 HubData *hub = OOP_INST_DATA(cl, o);
272 if ((msg->port > 0) && (msg->port <= hub->descriptor.bNbrPorts))
273 return (hub->children[msg->port-1]);
274 else
275 return NULL;
278 BOOL METHOD(USBHub, Hidd_USBHub, OnOff)
280 HubData *hub = OOP_INST_DATA(cl, o);
281 struct usbEvent message;
283 D(bug("[USBHub] USBHub::OnOff(%d)\n", msg->on));
285 hub->enabled = msg->on;
287 message.ev_Message.mn_ReplyPort = CreateMsgPort();
288 message.ev_Type = evt_OnOff;
290 PutMsg(hub->hub_port, (struct Message *)&message);
291 WaitPort(message.ev_Message.mn_ReplyPort);
292 DeleteMsgPort(message.ev_Message.mn_ReplyPort);
294 return FALSE;
297 BOOL METHOD(USBHub, Hidd_USBHub, PortEnable)
299 D(bug("[USBHub] USBHub::PortEnable(%d, %d)\n", msg->portNummer, msg->enable));
300 return FALSE;
303 BOOL METHOD(USBHub, Hidd_USBHub, PortReset)
305 HubData *hub = OOP_INST_DATA(cl, o);
306 BOOL retval = FALSE;
307 USBDevice_Request req;
308 int n = 10;
309 usb_port_status_t ps;
311 req.bmRequestType = UT_WRITE_CLASS_OTHER;
312 req.bRequest = UR_SET_FEATURE;
313 req.wValue = AROS_WORD2LE(UHF_PORT_RESET);
314 req.wIndex = AROS_WORD2LE(msg->portNummer);
315 req.wLength = AROS_WORD2LE(0);
317 retval = HIDD_USBDevice_ControlMessage(o, NULL, &req, NULL, 0);
319 if (retval) do
321 USBDelay(hub->tr, USB_PORT_RESET_DELAY);
323 retval = HIDD_USBHub_GetPortStatus(o, msg->portNummer, &ps);
325 if (!retval)
326 break;
328 if (!(AROS_LE2WORD(ps.wPortStatus) & UPS_CURRENT_CONNECT_STATUS))
330 retval = TRUE;
331 break;
333 } while ((AROS_LE2WORD(ps.wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
335 if (n==0)
336 retval = FALSE;
337 else
339 HIDD_USBHub_ClearPortFeature(o, msg->portNummer, UHF_C_PORT_RESET);
340 USBDelay(hub->tr, USB_PORT_RESET_RECOVERY);
343 D(bug("[USBHub] USBHub::PortReset(%d) %s\n", msg->portNummer, retval ? "OK":"Error"));
345 return retval;
348 BOOL METHOD(USBHub, Hidd_USBHub, GetPortStatus)
350 D(bug("[USBHub] USBHub::GetPortStatus()\n"));
352 USBDevice_Request req;
354 req.bmRequestType = UT_READ_CLASS_OTHER;
355 req.bRequest = UR_GET_STATUS;
356 req.wValue = AROS_WORD2LE(0);
357 req.wIndex = AROS_WORD2LE(msg->port);
358 req.wLength = AROS_WORD2LE(sizeof(usb_port_status_t));
360 return HIDD_USBDevice_ControlMessage(o, NULL, &req, msg->status, sizeof(usb_port_status_t));
363 BOOL METHOD(USBHub, Hidd_USBHub, GetHubStatus)
365 D(bug("[USBHub] USBHub::GetHubStatus()\n"));
367 USBDevice_Request req;
369 req.bmRequestType = UT_READ_CLASS_DEVICE;
370 req.bRequest = UR_GET_STATUS;
371 req.wValue = AROS_WORD2LE(0);
372 req.wIndex = AROS_WORD2LE(0);
373 req.wLength = AROS_WORD2LE(sizeof(usb_hub_status_t));
375 return HIDD_USBDevice_ControlMessage(o, NULL, &req, msg->status, sizeof(usb_hub_status_t));
378 BOOL METHOD(USBHub, Hidd_USBHub, ClearHubFeature)
380 D(bug("[USBHub] USBHub::ClearHubFeature()\n"));
382 USBDevice_Request req;
384 req.bmRequestType = UT_WRITE_CLASS_DEVICE;
385 req.bRequest = UR_CLEAR_FEATURE;
386 req.wValue = AROS_WORD2LE(msg->feature);
387 req.wIndex = AROS_WORD2LE(0);
388 req.wLength = AROS_WORD2LE(0);
390 return HIDD_USBDevice_ControlMessage(o, NULL, &req, NULL, 0);
393 BOOL METHOD(USBHub, Hidd_USBHub, SetHubFeature)
395 D(bug("[USBHub] USBHub::SetHubFeature()\n"));
397 USBDevice_Request req;
399 req.bmRequestType = UT_WRITE_CLASS_DEVICE;
400 req.bRequest = UR_SET_FEATURE;
401 req.wValue = AROS_WORD2LE(msg->feature);
402 req.wIndex = AROS_WORD2LE(0);
403 req.wLength = AROS_WORD2LE(0);
405 return HIDD_USBDevice_ControlMessage(o, NULL, &req, NULL, 0);
408 BOOL METHOD(USBHub, Hidd_USBHub, ClearPortFeature)
410 D(bug("[USBHub] USBHub::ClearPortFeature(%p, %d, %d)\n", o, msg->port, msg->feature));
412 USBDevice_Request req;
414 req.bmRequestType = UT_WRITE_CLASS_OTHER;
415 req.bRequest = UR_CLEAR_FEATURE;
416 req.wValue = AROS_WORD2LE(msg->feature);
417 req.wIndex = AROS_WORD2LE(msg->port);
418 req.wLength = AROS_WORD2LE(0);
420 return HIDD_USBDevice_ControlMessage(o, NULL, &req, NULL, 0);
423 BOOL METHOD(USBHub, Hidd_USBHub, SetPortFeature)
425 D(bug("[USBHub] USBHub::SetPortFeature(%p, %d, %d)\n", o, msg->port, msg->feature));
427 USBDevice_Request req;
429 req.bmRequestType = UT_WRITE_CLASS_OTHER;
430 req.bRequest = UR_SET_FEATURE;
431 req.wValue = AROS_WORD2LE(msg->feature);
432 req.wIndex = AROS_WORD2LE(msg->port);
433 req.wLength = AROS_WORD2LE(0);
435 return HIDD_USBDevice_ControlMessage(o, NULL, &req, NULL, 0);
438 BOOL METHOD(USBHub, Hidd_USBHub, GetHubDescriptor)
440 USBDevice_Request request = {
441 bmRequestType: UT_READ_CLASS_DEVICE,
442 bRequest: UR_GET_DESCRIPTOR,
443 wValue: AROS_WORD2LE(((uint8_t)UDESC_HUB) << 8),
444 wIndex: AROS_WORD2LE(0),
445 wLength: AROS_WORD2LE(USB_HUB_DESCRIPTOR_SIZE)
448 return HIDD_USBDevice_ControlMessage(o, NULL, &request, msg->descriptor, USB_HUB_DESCRIPTOR_SIZE);
453 static void hub_enable(OOP_Class *cl, OOP_Object *o)
455 HubData *hub = OOP_INST_DATA(cl, o);
456 int pwrdly, port;
458 if (!hub->got_descriptor)
459 hub->got_descriptor = HIDD_USBHub_GetHubDescriptor(o, &hub->descriptor);
461 pwrdly = hub->descriptor.bPwrOn2PwrGood * UHD_PWRON_FACTOR + USB_EXTRA_POWER_UP_TIME;
463 for (port = 1; port <= hub->descriptor.bNbrPorts; port++)
465 if (!HIDD_USBHub_SetPortFeature(o, port, UHF_PORT_POWER))
466 bug("[USBHub] PowerOn on port %d failed\n", port);
468 USBDelay(hub->tr, pwrdly);
472 static void hub_disable(OOP_Class *cl, OOP_Object *o)
474 HubData *hub = OOP_INST_DATA(cl, o);
475 int pwrdly, port;
477 if (!hub->got_descriptor)
478 hub->got_descriptor = HIDD_USBHub_GetHubDescriptor(o, &hub->descriptor);
480 pwrdly = hub->descriptor.bPwrOn2PwrGood * UHD_PWRON_FACTOR + USB_EXTRA_POWER_UP_TIME;
482 for (port = 1; port <= hub->descriptor.bNbrPorts; port++)
484 if (!HIDD_USBHub_ClearPortFeature(o, port, UHF_PORT_POWER))
485 bug("[USBHub] PowerOff on port %d failed\n", port);
487 USBDelay(hub->tr, pwrdly);
491 static BOOL hub_explore(OOP_Class *cl, OOP_Object *o)
493 HubData *hub = OOP_INST_DATA(cl, o);
494 BOOL more = FALSE;
495 int port;
497 D(bug("[USBHub Process] hub_explore()\n"));
499 if (!hub->got_descriptor)
500 hub->got_descriptor = HIDD_USBHub_GetHubDescriptor(o, &hub->descriptor);
502 for (port=1; port <= hub->descriptor.bNbrPorts; port++)
504 usb_port_status_t port_status;
505 uint16_t status, change;
507 if (!HIDD_USBHub_GetPortStatus(o, port, &port_status))
509 D(bug("[USBHub Process] HIDD_USBHub_GetPortStatus(%p, %d, %p) failed\n",
510 o, port, &status));
511 continue;
514 status = AROS_LE2WORD(port_status.wPortStatus);
515 change = AROS_LE2WORD(port_status.wPortChange);
517 D(bug("[USBHub Process] Port %d, status %04x, change %04x\n", port, status, change));
519 if (change & UPS_C_PORT_ENABLED)
521 D(bug("[USBHub Process] C_PORT_ENABLED\n"));
522 HIDD_USBHub_ClearPortFeature(o, port, UHF_C_PORT_ENABLE);
523 // TODO: Extend
526 if (change & UPS_C_CONNECT_STATUS)
528 D(bug("[USBHub Process] C_CONNECT_STATUS\n"));
529 HIDD_USBHub_ClearPortFeature(o, port, UHF_C_PORT_CONNECTION);
533 * if connection status has not changed and device is still disconnected skip port.
534 * the original method did not analyse ports after reset.
536 if ((0 == (status & UPS_CURRENT_CONNECT_STATUS)) == (0 == hub->children[port-1]))
538 // D(bug("[USBHub Process] !C_CONNECT_STATUS\n"));
539 D(bug("[USBHub Process] UPS_CURRENT_CONNECT_STATUS reflects actual mapping\n"));
540 continue;
543 if (hub->children[port-1])
545 OOP_DisposeObject(hub->children[port-1]);
546 hub->children[port-1] = NULL;
549 if (!(status & UPS_CURRENT_CONNECT_STATUS))
551 D(bug("[USBHub Process] !CURRENT_CONNECT_STATUS\n"));
552 continue;
555 if (!(status & UPS_PORT_POWER))
556 D(bug("[USBHub Process] Port %d without power???\n", port));
559 * i am not sure we want to keep restarting USB ports
560 * in case where we have no driver to utilize the device
561 * however i will leave it here for now
563 USBDelay(hub->tr, USB_PORT_POWERUP_DELAY);
565 D(bug("[USBHub Process]\tRestarting device in port %d\n", port));
566 if (!HIDD_USBHub_PortReset(o, port))
568 D(bug("[USBHub Process] Port %d reset failed\n", port));
569 continue;
572 if (!HIDD_USBHub_GetPortStatus(o, port, &port_status))
574 D(bug("[USBHub Process] HIDD_USBHub_GetPortStatus(%p, %d, %p) failed\n",
575 o, port, &status));
576 continue;
578 status = AROS_LE2WORD(port_status.wPortStatus);
579 change = AROS_LE2WORD(port_status.wPortChange);
581 D(bug("[USBHub Process] Port %d, status %04x, change %04x\n", port, status, change));
583 if (!(status & UPS_CURRENT_CONNECT_STATUS))
585 D(bug("[USBHub Process] Device on port %d disappeared after reset???\n", port));
586 continue;
589 hub->children[port-1] = HIDD_USB_NewDevice(SD(cl)->usb, o, !(status & UPS_LOW_SPEED));
590 if (NULL == hub->children[port-1])
592 D(bug("[USBHub Process]\tNo known handler for selected drive. Restoring connection flag.\n"));
593 more = TRUE;
594 //HIDD_USBHub_SetPortFeature(o, port, UHF_C_PORT_CONNECTION);
598 return more;
601 static void hub_process(HubData *hub, OOP_Object *o, struct Task *parent)
603 struct Task *hub_task = FindTask(NULL);
604 struct usb_staticdata *sd = hub->sd;
605 OOP_Object *drv = NULL;
606 OOP_Class *cl = sd->hubClass;
607 struct usbEvent *ev = NULL;
608 struct timerequest *rescan;
609 uint32_t sigset = 0;
610 uint32_t sigmask = 0;
612 hub->tr = USBCreateTimer();
613 hub->hub_port = CreateMsgPort();
615 rescan = USBCreateTimer();
617 OOP_GetAttr(o, aHidd_USBDevice_Bus, (IPTR *)&drv);
618 SetTaskPri(hub_task, 10);
620 D(bug("[USBHub Process] HUB process (%p)\n", FindTask(NULL)));
622 Signal(parent, SIGF_SINGLE);
624 for (;;)
626 D(bug("[USBHub Process] YAWN...\n"));
628 sigset = Wait( (1 << hub->hub_port->mp_SigBit) |
629 (sigmask) |
630 (1 << hub->sigInterrupt)
632 D(bug("[USBHub Process] signals rcvd: %p\n", sigset));
634 /* handle messages */
635 while ((ev = (struct usbEvent *)GetMsg(hub->hub_port)) != NULL)
637 BOOL reply = TRUE;
639 switch (ev->ev_Type)
641 case evt_Startup:
642 D(bug("[USBHub Process] Startup MSG\n"));
643 break;
645 case evt_Method:
646 D(bug("[USBHub Process] Sync method call\n"));
647 ev->ev_RetVal = OOP_DoMethod(ev->ev_Target, (OOP_Msg)&ev->ev_Event);
648 break;
650 case evt_AsyncMethod:
651 D(bug("[USBHub Process] Async method call\n"));
652 OOP_DoMethod(ev->ev_Target, (OOP_Msg)&ev->ev_Event);
653 FreeVecPooled(sd->MemPool, ev);
654 reply = FALSE;
655 break;
657 case evt_Cleanup:
658 D(bug("[USBHub Process] Cleanup MSG\n"));
659 USBDeleteTimer(hub->tr);
660 ReplyMsg(&ev->ev_Message);
661 return;
663 case evt_OnOff:
664 D(bug("[USBHub Process] Hub %s\n", hub->enabled ? "on" : "off"));
665 D(bug("----->MARKER 1<-----\n"));
666 if (hub->enabled)
667 hub_enable(cl, o);
668 else
669 hub_disable(cl, o);
670 D(bug("----->MARKER 2<-----\n"));
671 break;
673 default:
674 break;
676 D(bug("----->MARKER 3<-----\n"));
677 if (reply)
678 ReplyMsg(&ev->ev_Message);
681 D(bug("----->MARKER 4<-----\n"));
683 /* handle signals */
684 if ((sigset & (1 << hub->sigInterrupt)) ||
685 (sigset & sigmask))
687 struct usb_driver *d = NULL, *d2 = NULL;
689 if (sigset & sigmask)
690 USBTimerDone(rescan);
692 D(bug("[USBHub Process] Interrupt signalled\n"));
694 ObtainSemaphore(&sd->driverListLock);
695 ForeachNode(&sd->driverList, d)
697 if (d->d_Driver == drv)
699 d2 = d;
700 break;
703 ReleaseSemaphore(&sd->driverListLock);
705 if (d2)
707 ObtainSemaphore(&d2->d_Lock);
710 * check if some devices failed to be created
711 * if so, attempt to re-detect in 10 seconds,
712 * maybe we will have adequate drivers available
714 if (hub_explore(cl, o))
716 /* wake up in 10 secs and check again */
717 sigmask = USBTimer(rescan, 10000);
719 ReleaseSemaphore(&d2->d_Lock);
722 else
724 sigset = 0;