Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / bus / usb / usbhub.c
blob34a7ff1b5f848cb2a7d5d9efefa5e83d928422b4
1 /* usb.c - USB Hub Support. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/dl.h>
21 #include <grub/mm.h>
22 #include <grub/usb.h>
23 #include <grub/misc.h>
24 #include <grub/time.h>
26 #define GRUB_USBHUB_MAX_DEVICES 128
28 /* USB Supports 127 devices, with device 0 as special case. */
29 static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES];
31 static int rescan = 0;
32 static int npending = 0;
34 struct grub_usb_hub
36 struct grub_usb_hub *next;
37 grub_usb_controller_t controller;
38 int nports;
39 struct grub_usb_device **devices;
40 struct grub_usb_hub_port *ports;
41 grub_usb_device_t dev;
44 static struct grub_usb_hub *hubs;
45 static grub_usb_controller_dev_t grub_usb_list;
47 /* Add a device that currently has device number 0 and resides on
48 CONTROLLER, the Hub reported that the device speed is SPEED. */
49 static grub_usb_device_t
50 grub_usb_hub_add_dev (grub_usb_controller_t controller,
51 grub_usb_speed_t speed,
52 int split_hubport, int split_hubaddr)
54 grub_usb_device_t dev;
55 int i;
56 grub_usb_err_t err;
58 grub_boot_time ("Attaching USB device");
60 dev = grub_zalloc (sizeof (struct grub_usb_device));
61 if (! dev)
62 return NULL;
64 dev->controller = *controller;
65 dev->speed = speed;
66 dev->split_hubport = split_hubport;
67 dev->split_hubaddr = split_hubaddr;
69 err = grub_usb_device_initialize (dev);
70 if (err)
72 grub_free (dev);
73 return NULL;
76 /* Assign a new address to the device. */
77 for (i = 1; i < GRUB_USBHUB_MAX_DEVICES; i++)
79 if (! grub_usb_devs[i])
80 break;
82 if (i == GRUB_USBHUB_MAX_DEVICES)
84 grub_error (GRUB_ERR_IO, "can't assign address to USB device");
85 for (i = 0; i < 8; i++)
86 grub_free (dev->config[i].descconf);
87 grub_free (dev);
88 return NULL;
91 err = grub_usb_control_msg (dev,
92 (GRUB_USB_REQTYPE_OUT
93 | GRUB_USB_REQTYPE_STANDARD
94 | GRUB_USB_REQTYPE_TARGET_DEV),
95 GRUB_USB_REQ_SET_ADDRESS,
96 i, 0, 0, NULL);
97 if (err)
99 for (i = 0; i < 8; i++)
100 grub_free (dev->config[i].descconf);
101 grub_free (dev);
102 return NULL;
105 dev->addr = i;
106 dev->initialized = 1;
107 grub_usb_devs[i] = dev;
109 grub_dprintf ("usb", "Added new usb device: %p, addr=%d\n",
110 dev, i);
111 grub_dprintf ("usb", "speed=%d, split_hubport=%d, split_hubaddr=%d\n",
112 speed, split_hubport, split_hubaddr);
114 /* Wait "recovery interval", spec. says 2ms */
115 grub_millisleep (2);
117 grub_boot_time ("Probing USB device driver");
119 grub_usb_device_attach (dev);
121 grub_boot_time ("Attached USB device");
123 return dev;
127 static grub_usb_err_t
128 grub_usb_add_hub (grub_usb_device_t dev)
130 struct grub_usb_usb_hubdesc hubdesc;
131 grub_usb_err_t err;
132 int i;
134 err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
135 | GRUB_USB_REQTYPE_CLASS
136 | GRUB_USB_REQTYPE_TARGET_DEV),
137 GRUB_USB_REQ_GET_DESCRIPTOR,
138 (GRUB_USB_DESCRIPTOR_HUB << 8) | 0,
139 0, sizeof (hubdesc), (char *) &hubdesc);
140 if (err)
141 return err;
142 grub_dprintf ("usb", "Hub descriptor:\n\t\t len:%d, typ:0x%02x, cnt:%d, char:0x%02x, pwg:%d, curr:%d\n",
143 hubdesc.length, hubdesc.type, hubdesc.portcnt,
144 hubdesc.characteristics, hubdesc.pwdgood,
145 hubdesc.current);
147 /* Activate the first configuration. Hubs should have only one conf. */
148 grub_dprintf ("usb", "Hub set configuration\n");
149 grub_usb_set_configuration (dev, 1);
151 dev->nports = hubdesc.portcnt;
152 dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0]));
153 dev->ports = grub_zalloc (dev->nports * sizeof (dev->ports[0]));
154 if (!dev->children || !dev->ports)
156 grub_free (dev->children);
157 grub_free (dev->ports);
158 return GRUB_USB_ERR_INTERNAL;
161 /* Power on all Hub ports. */
162 for (i = 1; i <= hubdesc.portcnt; i++)
164 grub_dprintf ("usb", "Power on - port %d\n", i);
165 /* Power on the port and wait for possible device connect */
166 grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
167 | GRUB_USB_REQTYPE_CLASS
168 | GRUB_USB_REQTYPE_TARGET_OTHER),
169 GRUB_USB_REQ_SET_FEATURE,
170 GRUB_USB_HUB_FEATURE_PORT_POWER,
171 i, 0, NULL);
174 /* Rest will be done on next usb poll. */
175 for (i = 0; i < dev->config[0].interf[0].descif->endpointcnt;
176 i++)
178 struct grub_usb_desc_endp *endp = NULL;
179 endp = &dev->config[0].interf[0].descendp[i];
181 if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp)
182 == GRUB_USB_EP_INTERRUPT)
184 grub_size_t len;
185 dev->hub_endpoint = endp;
186 len = endp->maxpacket;
187 if (len > sizeof (dev->statuschange))
188 len = sizeof (dev->statuschange);
189 dev->hub_transfer
190 = grub_usb_bulk_read_background (dev, endp, len,
191 (char *) &dev->statuschange);
192 break;
196 rescan = 1;
198 return GRUB_USB_ERR_NONE;
201 static void
202 attach_root_port (struct grub_usb_hub *hub, int portno,
203 grub_usb_speed_t speed)
205 grub_usb_device_t dev;
206 grub_usb_err_t err;
208 grub_boot_time ("After detect_dev");
210 /* Enable the port. */
211 err = hub->controller->dev->portstatus (hub->controller, portno, 1);
212 if (err)
213 return;
214 hub->controller->dev->pending_reset = grub_get_time_ms () + 5000;
215 npending++;
217 grub_millisleep (10);
219 grub_boot_time ("Port enabled");
221 /* Enable the port and create a device. */
222 /* High speed device needs not transaction translation
223 and full/low speed device cannot be connected to EHCI root hub
224 and full/low speed device connected to OHCI/UHCI needs not
225 transaction translation - e.g. hubport and hubaddr should be
226 always none (zero) for any device connected to any root hub. */
227 dev = grub_usb_hub_add_dev (hub->controller, speed, 0, 0);
228 hub->controller->dev->pending_reset = 0;
229 npending--;
230 if (! dev)
231 return;
233 hub->devices[portno] = dev;
235 /* If the device is a Hub, scan it for more devices. */
236 if (dev->descdev.class == 0x09)
237 grub_usb_add_hub (dev);
239 grub_boot_time ("Attached root port");
242 /* Iterate over all controllers found by the driver. */
243 static int
244 grub_usb_controller_dev_register_iter (grub_usb_controller_t controller, void *data)
246 grub_usb_controller_dev_t usb = data;
247 struct grub_usb_hub *hub;
249 controller->dev = usb;
251 grub_boot_time ("Registering USB root hub");
253 hub = grub_malloc (sizeof (*hub));
254 if (!hub)
255 return GRUB_USB_ERR_INTERNAL;
257 hub->next = hubs;
258 hubs = hub;
259 hub->controller = grub_malloc (sizeof (*controller));
260 if (!hub->controller)
262 grub_free (hub);
263 return GRUB_USB_ERR_INTERNAL;
266 grub_memcpy (hub->controller, controller, sizeof (*controller));
267 hub->dev = 0;
269 /* Query the number of ports the root Hub has. */
270 hub->nports = controller->dev->hubports (controller);
271 hub->devices = grub_zalloc (sizeof (hub->devices[0]) * hub->nports);
272 hub->ports = grub_zalloc (sizeof (hub->ports[0]) * hub->nports);
273 if (!hub->devices || !hub->ports)
275 grub_free (hub->devices);
276 grub_free (hub->ports);
277 grub_free (hub->controller);
278 grub_free (hub);
279 grub_print_error ();
280 return 0;
283 return 0;
286 void
287 grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb)
289 grub_usb_controller_dev_t *p, q;
291 for (p = &grub_usb_list, q = *p; q; p = &(q->next), q = q->next)
292 if (q == usb)
294 *p = q->next;
295 break;
299 void
300 grub_usb_controller_dev_register (grub_usb_controller_dev_t usb)
302 int portno;
303 int continue_waiting = 0;
304 struct grub_usb_hub *hub;
306 usb->next = grub_usb_list;
307 grub_usb_list = usb;
309 if (usb->iterate)
310 usb->iterate (grub_usb_controller_dev_register_iter, usb);
312 grub_boot_time ("waiting for stable power on USB root\n");
314 while (1)
316 for (hub = hubs; hub; hub = hub->next)
317 if (hub->controller->dev == usb)
319 /* Wait for completion of insertion and stable power (USB spec.)
320 * Should be at least 100ms, some devices requires more...
321 * There is also another thing - some devices have worse contacts
322 * and connected signal is unstable for some time - we should handle
323 * it - but prevent deadlock in case when device is too faulty... */
324 for (portno = 0; portno < hub->nports; portno++)
326 grub_usb_speed_t speed;
327 int changed = 0;
329 speed = hub->controller->dev->detect_dev (hub->controller, portno,
330 &changed);
332 if (hub->ports[portno].state == PORT_STATE_NORMAL
333 && speed != GRUB_USB_SPEED_NONE)
335 hub->ports[portno].soft_limit_time = grub_get_time_ms () + 250;
336 hub->ports[portno].hard_limit_time = hub->ports[portno].soft_limit_time + 1750;
337 hub->ports[portno].state = PORT_STATE_WAITING_FOR_STABLE_POWER;
338 grub_boot_time ("Scheduling stable power wait for port %p:%d",
339 usb, portno);
340 continue_waiting++;
341 continue;
344 if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER
345 && speed == GRUB_USB_SPEED_NONE)
347 hub->ports[portno].soft_limit_time = grub_get_time_ms () + 250;
348 continue;
350 if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER
351 && grub_get_time_ms () > hub->ports[portno].soft_limit_time)
353 hub->ports[portno].state = PORT_STATE_STABLE_POWER;
354 grub_boot_time ("Got stable power wait for port %p:%d",
355 usb, portno);
356 continue_waiting--;
357 continue;
359 if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER
360 && grub_get_time_ms () > hub->ports[portno].hard_limit_time)
362 hub->ports[portno].state = PORT_STATE_FAILED_DEVICE;
363 continue_waiting--;
364 continue;
368 if (!continue_waiting)
369 break;
370 grub_millisleep (1);
373 grub_boot_time ("After the stable power wait on USB root");
375 for (hub = hubs; hub; hub = hub->next)
376 if (hub->controller->dev == usb)
377 for (portno = 0; portno < hub->nports; portno++)
378 if (hub->ports[portno].state == PORT_STATE_STABLE_POWER)
380 grub_usb_speed_t speed;
381 int changed = 0;
382 hub->ports[portno].state = PORT_STATE_NORMAL;
383 speed = hub->controller->dev->detect_dev (hub->controller, portno, &changed);
384 attach_root_port (hub, portno, speed);
387 grub_boot_time ("USB root hub registered");
390 static void detach_device (grub_usb_device_t dev);
392 static void
393 detach_device (grub_usb_device_t dev)
395 unsigned i;
396 int k;
397 if (!dev)
398 return;
399 if (dev->descdev.class == GRUB_USB_CLASS_HUB)
401 if (dev->hub_transfer)
402 grub_usb_cancel_transfer (dev->hub_transfer);
404 for (i = 0; i < dev->nports; i++)
405 detach_device (dev->children[i]);
406 grub_free (dev->children);
408 for (i = 0; i < ARRAY_SIZE (dev->config); i++)
409 if (dev->config[i].descconf)
410 for (k = 0; k < dev->config[i].descconf->numif; k++)
412 struct grub_usb_interface *inter = &dev->config[i].interf[k];
413 if (inter && inter->detach_hook)
414 inter->detach_hook (dev, i, k);
416 grub_usb_devs[dev->addr] = 0;
419 static int
420 wait_power_nonroot_hub (grub_usb_device_t dev)
422 grub_usb_err_t err;
423 int continue_waiting = 0;
424 unsigned i;
426 for (i = 1; i <= dev->nports; i++)
427 if (dev->ports[i - 1].state == PORT_STATE_WAITING_FOR_STABLE_POWER)
429 grub_uint64_t tm;
430 grub_uint32_t current_status = 0;
432 /* Get the port status. */
433 err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
434 | GRUB_USB_REQTYPE_CLASS
435 | GRUB_USB_REQTYPE_TARGET_OTHER),
436 GRUB_USB_REQ_GET_STATUS,
437 0, i,
438 sizeof (current_status),
439 (char *) &current_status);
440 if (err)
442 dev->ports[i - 1].state = PORT_STATE_FAILED_DEVICE;
443 continue;
445 tm = grub_get_time_ms ();
446 if (!(current_status & GRUB_USB_HUB_STATUS_PORT_CONNECTED))
447 dev->ports[i - 1].soft_limit_time = tm + 250;
448 if (tm >= dev->ports[i - 1].soft_limit_time)
450 if (dev->controller.dev->pending_reset)
451 continue;
452 /* Now do reset of port. */
453 grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
454 | GRUB_USB_REQTYPE_CLASS
455 | GRUB_USB_REQTYPE_TARGET_OTHER),
456 GRUB_USB_REQ_SET_FEATURE,
457 GRUB_USB_HUB_FEATURE_PORT_RESET,
458 i, 0, 0);
459 dev->ports[i - 1].state = PORT_STATE_NORMAL;
460 grub_boot_time ("Resetting port %p:%d", dev, i - 1);
462 rescan = 1;
463 /* We cannot reset more than one device at the same time !
464 * Resetting more devices together results in very bad
465 * situation: more than one device has default address 0
466 * at the same time !!!
467 * Additionaly, we cannot perform another reset
468 * anywhere on the same OHCI controller until
469 * we will finish addressing of reseted device ! */
470 dev->controller.dev->pending_reset = grub_get_time_ms () + 5000;
471 npending++;
472 continue;
474 if (tm >= dev->ports[i - 1].hard_limit_time)
476 dev->ports[i - 1].state = PORT_STATE_FAILED_DEVICE;
477 continue;
479 continue_waiting = 1;
481 return continue_waiting && dev->controller.dev->pending_reset == 0;
484 static void
485 poll_nonroot_hub (grub_usb_device_t dev)
487 grub_usb_err_t err;
488 unsigned i;
489 grub_uint32_t changed;
490 grub_size_t actual, len;
492 if (!dev->hub_transfer)
493 return;
495 err = grub_usb_check_transfer (dev->hub_transfer, &actual);
497 if (err == GRUB_USB_ERR_WAIT)
498 return;
500 changed = dev->statuschange;
502 len = dev->hub_endpoint->maxpacket;
503 if (len > sizeof (dev->statuschange))
504 len = sizeof (dev->statuschange);
505 dev->hub_transfer
506 = grub_usb_bulk_read_background (dev, dev->hub_endpoint, len,
507 (char *) &dev->statuschange);
509 if (err || actual == 0 || changed == 0)
510 return;
512 /* Iterate over the Hub ports. */
513 for (i = 1; i <= dev->nports; i++)
515 grub_uint32_t status;
517 if (!(changed & (1 << i))
518 || dev->ports[i - 1].state == PORT_STATE_WAITING_FOR_STABLE_POWER)
519 continue;
521 /* Get the port status. */
522 err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
523 | GRUB_USB_REQTYPE_CLASS
524 | GRUB_USB_REQTYPE_TARGET_OTHER),
525 GRUB_USB_REQ_GET_STATUS,
526 0, i, sizeof (status), (char *) &status);
528 grub_dprintf ("usb", "dev = %p, i = %d, status = %08x\n",
529 dev, i, status);
531 if (err)
532 continue;
534 /* FIXME: properly handle these conditions. */
535 if (status & GRUB_USB_HUB_STATUS_C_PORT_ENABLED)
536 grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
537 | GRUB_USB_REQTYPE_CLASS
538 | GRUB_USB_REQTYPE_TARGET_OTHER),
539 GRUB_USB_REQ_CLEAR_FEATURE,
540 GRUB_USB_HUB_FEATURE_C_PORT_ENABLED, i, 0, 0);
542 if (status & GRUB_USB_HUB_STATUS_C_PORT_SUSPEND)
543 grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
544 | GRUB_USB_REQTYPE_CLASS
545 | GRUB_USB_REQTYPE_TARGET_OTHER),
546 GRUB_USB_REQ_CLEAR_FEATURE,
547 GRUB_USB_HUB_FEATURE_C_PORT_SUSPEND, i, 0, 0);
549 if (status & GRUB_USB_HUB_STATUS_C_PORT_OVERCURRENT)
550 grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
551 | GRUB_USB_REQTYPE_CLASS
552 | GRUB_USB_REQTYPE_TARGET_OTHER),
553 GRUB_USB_REQ_CLEAR_FEATURE,
554 GRUB_USB_HUB_FEATURE_C_PORT_OVERCURRENT, i, 0, 0);
556 if (!dev->controller.dev->pending_reset &&
557 (status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED))
559 grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
560 | GRUB_USB_REQTYPE_CLASS
561 | GRUB_USB_REQTYPE_TARGET_OTHER),
562 GRUB_USB_REQ_CLEAR_FEATURE,
563 GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED, i, 0, 0);
565 detach_device (dev->children[i - 1]);
566 dev->children[i - 1] = NULL;
568 /* Connected and status of connection changed ? */
569 if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)
571 grub_boot_time ("Before the stable power wait portno=%d", i);
572 /* A device is actually connected to this port. */
573 /* Wait for completion of insertion and stable power (USB spec.)
574 * Should be at least 100ms, some devices requires more...
575 * There is also another thing - some devices have worse contacts
576 * and connected signal is unstable for some time - we should handle
577 * it - but prevent deadlock in case when device is too faulty... */
578 dev->ports[i - 1].soft_limit_time = grub_get_time_ms () + 250;
579 dev->ports[i - 1].hard_limit_time = dev->ports[i - 1].soft_limit_time + 1750;
580 dev->ports[i - 1].state = PORT_STATE_WAITING_FOR_STABLE_POWER;
581 grub_boot_time ("Scheduling stable power wait for port %p:%d",
582 dev, i - 1);
583 continue;
587 if (status & GRUB_USB_HUB_STATUS_C_PORT_RESET)
589 grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
590 | GRUB_USB_REQTYPE_CLASS
591 | GRUB_USB_REQTYPE_TARGET_OTHER),
592 GRUB_USB_REQ_CLEAR_FEATURE,
593 GRUB_USB_HUB_FEATURE_C_PORT_RESET, i, 0, 0);
595 grub_boot_time ("Port %d reset", i);
597 if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)
599 grub_usb_speed_t speed;
600 grub_usb_device_t next_dev;
601 int split_hubport = 0;
602 int split_hubaddr = 0;
604 /* Determine the device speed. */
605 if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED)
606 speed = GRUB_USB_SPEED_LOW;
607 else
609 if (status & GRUB_USB_HUB_STATUS_PORT_HIGHSPEED)
610 speed = GRUB_USB_SPEED_HIGH;
611 else
612 speed = GRUB_USB_SPEED_FULL;
615 /* Wait a recovery time after reset, spec. says 10ms */
616 grub_millisleep (10);
618 /* Find correct values for SPLIT hubport and hubaddr */
619 if (speed == GRUB_USB_SPEED_HIGH)
621 /* HIGH speed device needs not transaction translation */
622 split_hubport = 0;
623 split_hubaddr = 0;
625 else
626 /* FULL/LOW device needs hub port and hub address
627 for transaction translation (if connected to EHCI) */
628 if (dev->speed == GRUB_USB_SPEED_HIGH)
630 /* This port is the first FULL/LOW speed port
631 in the chain from root hub. Attached device
632 should use its port number and hub address */
633 split_hubport = i;
634 split_hubaddr = dev->addr;
636 else
638 /* This port is NOT the first FULL/LOW speed port
639 in the chain from root hub. Attached device
640 should use values inherited from some parent
641 HIGH speed hub - if any. */
642 split_hubport = dev->split_hubport;
643 split_hubaddr = dev->split_hubaddr;
646 /* Add the device and assign a device address to it. */
647 next_dev = grub_usb_hub_add_dev (&dev->controller, speed,
648 split_hubport, split_hubaddr);
649 if (dev->controller.dev->pending_reset)
651 dev->controller.dev->pending_reset = 0;
652 npending--;
654 if (! next_dev)
655 continue;
657 dev->children[i - 1] = next_dev;
659 /* If the device is a Hub, scan it for more devices. */
660 if (next_dev->descdev.class == 0x09)
661 grub_usb_add_hub (next_dev);
667 void
668 grub_usb_poll_devices (int wait_for_completion)
670 struct grub_usb_hub *hub;
671 int i;
673 for (hub = hubs; hub; hub = hub->next)
675 /* Do we have to recheck number of ports? */
676 /* No, it should be never changed, it should be constant. */
677 for (i = 0; i < hub->nports; i++)
679 grub_usb_speed_t speed = GRUB_USB_SPEED_NONE;
680 int changed = 0;
682 if (hub->controller->dev->pending_reset)
684 /* Check for possible timeout */
685 if (grub_get_time_ms () > hub->controller->dev->pending_reset)
687 /* Something went wrong, reset device was not
688 * addressed properly, timeout happened */
689 hub->controller->dev->pending_reset = 0;
690 npending--;
693 if (!hub->controller->dev->pending_reset)
694 speed = hub->controller->dev->detect_dev (hub->controller,
695 i, &changed);
697 if (changed)
699 detach_device (hub->devices[i]);
700 hub->devices[i] = NULL;
701 if (speed != GRUB_USB_SPEED_NONE)
702 attach_root_port (hub, i, speed);
707 while (1)
709 rescan = 0;
711 /* We should check changes of non-root hubs too. */
712 for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++)
714 grub_usb_device_t dev = grub_usb_devs[i];
716 if (dev && dev->descdev.class == 0x09)
717 poll_nonroot_hub (dev);
720 while (1)
722 int continue_waiting = 0;
723 for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++)
725 grub_usb_device_t dev = grub_usb_devs[i];
727 if (dev && dev->descdev.class == 0x09)
728 continue_waiting = continue_waiting || wait_power_nonroot_hub (dev);
730 if (!continue_waiting)
731 break;
732 grub_millisleep (1);
735 if (!(rescan || (npending && wait_for_completion)))
736 break;
737 grub_millisleep (25);
742 grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data)
744 int i;
746 for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++)
748 if (grub_usb_devs[i])
750 if (hook (grub_usb_devs[i], hook_data))
751 return 1;
755 return 0;