RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / usb / usbhub.c
blob523da00e33bc69d11d6b9bd39c638f4af839c124
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * USB Hub and device discovery code File: usbhub.c
5 *
6 * This module deals with hubs and device discovery.
7 *
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
9 *
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
48 #ifndef _CFE_
49 #include <stdio.h>
50 #include <time.h>
51 #include <memory.h>
52 #include <stdint.h>
53 #include "usbhack.h"
54 #else
55 #include "lib_types.h"
56 #include "lib_string.h"
57 #include "lib_printf.h"
58 #include "cfe_console.h"
59 #endif
61 #include "lib_malloc.h"
62 #include "lib_queue.h"
63 #include "usbchap9.h"
64 #include "usbd.h"
66 /* *********************************************************************
67 * Macros for common hub requests
68 ********************************************************************* */
70 #define usbhub_set_port_feature(dev,port,feature) \
71 usb_simple_request(dev,0x23,USB_HUBREQ_SET_FEATURE,feature,port)
73 #define usbhub_set_hub_feature(dev,feature) \
74 usb_simple_request(dev,0x20,USB_HUBREQ_SET_FEATURE,feature,0)
76 #define usbhub_clear_port_feature(dev,port,feature) \
77 usb_simple_request(dev,0x23,USB_HUBREQ_CLEAR_FEATURE,feature,port)
79 #define usbhub_clear_hub_feature(dev,feature) \
80 usb_simple_request(dev,0x20,USB_HUBREQ_CLEAR_FEATURE,feature,0)
83 /* *********************************************************************
84 * Externs
85 ********************************************************************* */
87 extern int usb_noisy;
89 /* *********************************************************************
90 * Forward declarations
91 ********************************************************************* */
93 static int usbhub_attach(usbdev_t *dev,usb_driver_t *drv);
94 static int usbhub_detach(usbdev_t *dev);
96 /* *********************************************************************
97 * Hub-specific data structures
98 ********************************************************************* */
100 #define UHUB_MAX_DEVICES 8
102 #define UHUB_FLG_NEEDSCAN 1
104 typedef struct usbhub_softc_s {
105 usb_hub_descr_t uhub_descr;
106 usb_hub_status_t uhub_status;
107 int uhub_ipipe;
108 int uhub_ipipemps;
109 int uhub_nports;
110 unsigned int uhub_flags;
111 uint8_t uhub_imsg[8];
112 usbdev_t *uhub_devices[UHUB_MAX_DEVICES];
113 } usbhub_softc_t;
115 usb_driver_t usbhub_driver = {
116 "USB Hub",
117 usbhub_attach,
118 usbhub_detach
122 /* *********************************************************************
123 * usbhub_ireq_callback(ur)
125 * this routine is called when the transfer we queued to the
126 * interrupt endpoint on the hub completes. It means that
127 * *some* port on the hub needs attention. The data indicates
128 * which port, but for our purposes we don't really care - if
129 * we get this callback, we'll set a flag and re-probe the bus.
131 * Input parameters:
132 * ur - usbreq that completed
134 * Return value:
136 ********************************************************************* */
138 static int usbhub_ireq_callback(usbreq_t *ur)
140 int idx;
141 usbhub_softc_t *uhub = (ur->ur_dev->ud_private);
144 * Check to see if the request was cancelled by someone
145 * deleting our endpoint.
148 if (ur->ur_status == 0xFF) {
149 usb_free_request(ur);
150 return 0;
154 * Check to see if any of our ports need attention
157 for (idx = 1; idx <= uhub->uhub_nports; idx++) {
158 if (ur->ur_buffer[0] & (1<<idx)) {
161 * Mark the hub as needing a scan, and mark the bus as well
162 * so the top-level polling will notice.
165 uhub->uhub_flags |= UHUB_FLG_NEEDSCAN;
166 ur->ur_dev->ud_bus->ub_flags |= UB_FLG_NEEDSCAN;
172 * Do NOT requeue the request here. We will do this
173 * during exploration.
176 usb_free_request(ur);
178 return 0;
182 /* *********************************************************************
183 * usbhub_get_hub_descriptor(dev,dscr,idx,maxlen)
185 * Obtain the hub descriptor (special for hubs) from the
186 * device.
188 * Input parameters:
189 * dev - usb device
190 * dscr - place to put hub descriptor
191 * idx - which hub descriptor to get (usually zero)
192 * maxlen - max # of bytes to return
194 * Return value:
195 * # of bytes returned
196 ********************************************************************* */
198 static int usbhub_get_hub_descriptor(usbdev_t *dev,usb_hub_descr_t *dscr,int idx,int maxlen)
200 return usb_std_request(dev,0xA0,
201 USB_HUBREQ_GET_DESCRIPTOR,
202 0,0,
203 (uint8_t *) dscr,
204 maxlen);
208 /* *********************************************************************
209 * usbhub_get_hub_status(dev,status)
211 * Obtain the hub status (special for hubs) from the
212 * device.
214 * Input parameters:
215 * dev - usb device
216 * status - where to put hub status structure
218 * Return value:
219 * # of bytes returned
220 ********************************************************************* */
224 /* *********************************************************************
225 * usbhub_get_port_status(dev,port,status)
227 * Obtain the port status for a particular port from
228 * device.
230 * Input parameters:
231 * dev - usb device
232 * port - 1-based port number
233 * status - where to put port status structure
235 * Return value:
236 * # of bytes returned
237 ********************************************************************* */
239 static int usbhub_get_port_status(usbdev_t *dev,int port,usb_port_status_t *status)
241 return usb_std_request(dev,
242 0xA3,
245 port,
246 (uint8_t *) status,
247 sizeof(usb_port_status_t));
251 /* *********************************************************************
252 * usbhub_queue_intreq(dev,softc)
254 * Queue the transfer to the interrupt pipe that will catch
255 * the hub's port status changes
257 * Input parameters:
258 * dev - usb device
259 * softc - hub-specific data
261 * Return value:
262 * nothing
263 ********************************************************************* */
265 static void usbhub_queue_intreq(usbdev_t *dev,usbhub_softc_t *softc)
267 usbreq_t *ur;
269 ur = usb_make_request(dev,
270 softc->uhub_ipipe,
271 softc->uhub_imsg,softc->uhub_ipipemps,
272 UR_FLAG_IN | UR_FLAG_SHORTOK);
274 ur->ur_callback = usbhub_ireq_callback;
276 usb_queue_request(ur);
280 /* *********************************************************************
281 * usbhub_attach(dev,drv)
283 * This routine is called when the hub attaches to the system.
284 * We complete initialization for the hub and set things up so
285 * that an explore will happen soon.
287 * Input parameters:
288 * dev - usb device
289 * drv - driver structure
291 * Return value:
293 ********************************************************************* */
295 static int usbhub_attach(usbdev_t *dev,usb_driver_t *drv)
297 usb_device_status_t devstatus;
298 usb_config_descr_t *cfgdscr;
299 usb_interface_descr_t *ifdscr;
300 usb_endpoint_descr_t *epdscr;
301 usbhub_softc_t *softc;
304 * Remember the driver dispatch.
307 dev->ud_drv = drv;
309 softc = KMALLOC(sizeof(usbhub_softc_t),0);
310 memset(softc,0,sizeof(usbhub_softc_t));
311 dev->ud_private = softc;
314 * Dig out the data from the configuration descriptor
315 * (we got this from the device before attach time)
318 cfgdscr = dev->ud_cfgdescr;
319 epdscr = usb_find_cfg_descr(dev,USB_ENDPOINT_DESCRIPTOR_TYPE,0);
320 ifdscr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0);
323 * Get device status (is this really necessary?)
326 usb_get_device_status(dev,&devstatus);
329 * Set us to configuration index 0
332 usb_set_configuration(dev,cfgdscr->bConfigurationValue);
335 * Get the hub descriptor. Get the first 8 bytes first, then get the rest
336 * if there is more.
339 if (usbhub_get_hub_descriptor(dev,&(softc->uhub_descr),0,USB_HUB_DESCR_SIZE) > USB_HUB_DESCR_SIZE) {
340 usbhub_get_hub_descriptor(dev,&(softc->uhub_descr),0,softc->uhub_descr.bDescriptorLength);
344 * remember stuff from the hub descriptor
347 softc->uhub_nports = softc->uhub_descr.bNumberOfPorts;
350 * Open the interrupt pipe
353 softc->uhub_ipipe = usb_open_pipe(dev,epdscr);
354 softc->uhub_ipipemps = GETUSBFIELD(epdscr,wMaxPacketSize);
357 * Mark the bus and the hub as needing service.
360 softc->uhub_flags |= UHUB_FLG_NEEDSCAN;
361 dev->ud_bus->ub_flags |= UB_FLG_NEEDSCAN;
364 * Okay, that's it. The top-level USB daemon will notice
365 * that the bus needs service and will invoke the exploration code.
366 * This may in turn require additional explores until
367 * everything settles down.
370 return 0;
374 /* *********************************************************************
375 * usbhub_detach(dev)
377 * Called when a hub is removed from the system - we remove
378 * all subordinate devicees.
380 * Input parameters:
381 * dev - device (hub) that was removed
383 * Return value:
385 ********************************************************************* */
387 static int usbhub_detach(usbdev_t *dev)
389 usbhub_softc_t *hub;
390 usbdev_t *deldev;
391 int idx;
393 if (!IS_HUB(dev)) return 0; /* should not happen */
395 hub = dev->ud_private;
396 for (idx = 0; idx < UHUB_MAX_DEVICES; idx++) {
397 deldev = hub->uhub_devices[idx];
398 if (deldev) {
399 console_log("USB: Removing device attached to bus %d hub %d port %d",
400 dev->ud_bus->ub_num,
401 dev->ud_address,idx+1);
402 if (deldev->ud_drv) {
403 (*(deldev->ud_drv->udrv_detach))(deldev);
405 else {
406 if (usb_noisy > 0) {
407 console_log("USB: Detached device on bus %d hub %d port %d "
408 "has no methods",
409 dev->ud_bus->ub_num,
410 dev->ud_address,idx+1);
413 if (deldev->ud_cfgdescr) KFREE(deldev->ud_cfgdescr);
414 usb_destroy_device(deldev);
418 KFREE(hub); /* remove softc */
420 return 0;
425 /* *********************************************************************
426 * usbhub_map_tree1(dev,level,func,arg)
428 * This routine is used in recursive device tree exploration.
429 * We call 'func' for each device at this tree, and descend
430 * when we run into hubs
432 * Input parameters:
433 * dev - current device pointer
434 * level - current nesting level
435 * func - function to call
436 * arg - argument to pass to function
438 * Return value:
439 * nothing
440 ********************************************************************* */
442 static void usbhub_map_tree1(usbdev_t *dev,int level,
443 int (*func)(usbdev_t *dev,void *arg),void *arg)
445 usbhub_softc_t *hub;
446 int idx;
448 (*func)(dev,arg);
450 if (IS_HUB(dev)) {
451 hub = dev->ud_private;
452 for (idx = 0; idx < UHUB_MAX_DEVICES; idx++) {
453 if (hub->uhub_devices[idx]) {
454 usbhub_map_tree1(hub->uhub_devices[idx],level+1,func,arg);
460 /* *********************************************************************
461 * usbhub_map_tree(bus,func,arg)
463 * Call a function for each device in the tree
465 * Input parameters:
466 * bus - bus to scan
467 * func - function to call
468 * arg - argument to pass to function
470 * Return value:
471 * nothing
472 ********************************************************************* */
474 void usbhub_map_tree(usbbus_t *bus,int (*func)(usbdev_t *dev,void *arg),void *arg)
476 usbhub_map_tree1(bus->ub_roothub,0,func,arg);
480 /* *********************************************************************
481 * usbhub_dumpbus1(dev,arg)
483 * map function to dump devices in the device tree
485 * Input parameters:
486 * dev - device we're working on
487 * arg - argument from map_tree call
489 * Return value:
491 ********************************************************************* */
493 static int usbhub_dumpbus1(usbdev_t *dev,void *arg)
495 uint32_t *verbose = (uint32_t *) arg;
497 if ((*verbose & 0x00FF) && (dev->ud_address != (*verbose & 0x00FF))) return 0;
499 if (*verbose & 0x100) {
500 printf("============================================================================\n");
503 printf("Bus %d Device %d Class %d Vendor %04X Product %04X ",
504 dev->ud_bus->ub_num,
505 dev->ud_address,
506 dev->ud_devdescr.bDeviceClass,
507 GETUSBFIELD(&(dev->ud_devdescr),idVendor),
508 GETUSBFIELD(&(dev->ud_devdescr),idProduct));
511 if (IS_HUB(dev)) {
512 printf("[HUB]\n");
514 else {
515 printf("[DEVICE]\n");
518 if (*verbose & 0x100) {
519 usb_dbg_dumpdescriptors(dev,(uint8_t *) &(dev->ud_devdescr),dev->ud_devdescr.bLength);
520 usb_dbg_dumpcfgdescr(dev);
523 return 0;
527 /* *********************************************************************
528 * usbhub_dumpbus(bus,verbose)
530 * Dump information about devices on the USB bus.
532 * Input parameters:
533 * bus - bus to dump
534 * verbose - nonzero to display more info, like descriptors
536 * Return value:
537 * nothing
538 ********************************************************************* */
540 void usbhub_dumpbus(usbbus_t *bus,uint32_t verbose)
542 usbhub_map_tree(bus,usbhub_dumpbus1,&verbose);
547 /* *********************************************************************
548 * usbhub_reset_devicee(dev,port,status)
550 * Reset a device on a hub port. This routine does a
551 * USB_PORT_FEATURE_RESET on the specified port, waits for the
552 * bit to clear, and returns. It is used to get a device into the
553 * DEFAULT state according to the spec.
555 * Input parameters:
556 * dev - hub device
557 * port - port number(1-based)
558 * status - place to return port_status structure after
559 * reset completes
561 * Return value:
562 * nothing
563 ********************************************************************* */
565 static void usbhub_reset_device(usbdev_t *dev,int port,usb_port_status_t *portstatus)
567 console_log("USB: Resetting device on bus %d port %d",dev->ud_bus->ub_num,port);
568 #ifndef _CFE_
569 fflush(stdout);
570 #endif
572 usbhub_set_port_feature(dev,port,USB_PORT_FEATURE_RESET);
574 usbhub_get_port_status(dev,port,portstatus);
576 for (;;) {
577 usbhub_get_port_status(dev,port,portstatus);
578 if ((GETUSBFIELD((portstatus),wPortStatus) & USB_PORT_STATUS_RESET) == 0) break;
579 usb_delay_ms(dev->ud_bus,250);
581 usb_delay_ms(dev->ud_bus,250);
583 usbhub_clear_port_feature(dev,port,USB_PORT_FEATURE_C_PORT_RESET);
588 /* *********************************************************************
589 * usbhub_scan_ports(dev,arg)
591 * Scan the ports on this hub for new or removed devices.
593 * Input parameters:
594 * dev - hub device
595 * arg - passed from bus scan main routines
597 * Return value:
598 * nothing
599 ********************************************************************* */
601 static void usbhub_scan_ports(usbdev_t *dev,void *arg)
603 uint16_t current;
604 uint16_t changed;
605 usbhub_softc_t *softc;
606 int idx;
607 int res;
608 int len;
609 uint8_t *buf;
610 usbdev_t *newdev;
611 usb_driver_t *newdrv;
612 int addr;
613 usb_port_status_t portstatus;
614 usb_config_descr_t cfgdescr;
615 unsigned int powerondelay;
617 if (!IS_HUB(dev)) return; /* should not happen. */
620 * We know this is a hub. Get the softc back.
623 softc = (usbhub_softc_t *) dev->ud_private;
625 powerondelay = ((unsigned int) softc->uhub_descr.bPowerOnToPowerGood)*2 + 20;
628 * Turn on the power to the ports whose power is not yet on.
631 for (idx = 0; idx < softc->uhub_nports; idx++) {
633 usbhub_get_port_status(dev,idx+1,&portstatus);
635 current = GETUSBFIELD((&portstatus),wPortStatus);
636 changed = GETUSBFIELD((&portstatus),wPortChange);
637 if (usb_noisy > 1) {
638 printf("BeforePowerup: port %d status %04X changed %04X\n",idx+1,current,changed);
641 if (!(current & USB_PORT_STATUS_POWER)) {
642 if (usb_noisy > 1) console_log("USB: Powering up bus %d port %d",
643 dev->ud_bus->ub_num,idx+1);
644 usbhub_set_port_feature(dev,idx+1,USB_PORT_FEATURE_POWER);
645 usb_delay_ms(dev->ud_bus,powerondelay);
650 * Begin exploration at this level.
653 for (idx = 0; idx < softc->uhub_nports; idx++) {
655 usbhub_get_port_status(dev,idx+1,&portstatus);
657 current = GETUSBFIELD((&portstatus),wPortStatus);
658 changed = GETUSBFIELD((&portstatus),wPortChange);
660 if (usb_noisy > 0) {
661 printf("USB: Explore: Bus %d Hub %d port %d status %04X changed %04X\n",
662 dev->ud_bus->ub_num,
663 dev->ud_address,idx+1,current,changed);
664 usb_dbg_dumpportstatus(idx+1,&portstatus,1);
668 // if (changed & USB_PORT_STATUS_RESET) {
669 // usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_RESET);
670 // }
672 if (changed & USB_PORT_STATUS_ENABLED) {
673 usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_ENABLE);
676 if (changed & USB_PORT_STATUS_CONNECT) {
678 * A device was either connected or disconnected.
679 * Clear the status change first.
682 usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_CONNECTION);
684 if (current & USB_PORT_STATUS_CONNECT) {
687 * The device has been CONNECTED.
690 console_log("USB: New device connected to bus %d hub %d port %d",
691 dev->ud_bus->ub_num,
692 dev->ud_address,idx+1);
695 * Reset the device. Reuse our old port status structure
696 * so we get the latest status. Some devices do not report
697 * lowspeed until they are reset.
700 usbhub_reset_device(dev,idx+1,&portstatus);
701 current = GETUSBFIELD((&portstatus),wPortStatus);
702 changed = GETUSBFIELD((&portstatus),wPortChange);
705 * Create a device for this port.
708 newdev = usb_create_device(dev->ud_bus,(current & USB_PORT_STATUS_LOWSPD) ? 1 : 0);
711 * Get the device descriptor.
714 res = usb_get_device_descriptor(newdev,&(newdev->ud_devdescr),TRUE);
716 if (usb_noisy > 0) usb_dbg_dumpdescriptors(newdev,(uint8_t *) &(newdev->ud_devdescr),8);
719 * Set up the max packet size for the control endpoint,
720 * then get the rest of the descriptor.
723 usb_set_ep0mps(newdev,newdev->ud_devdescr.bMaxPacketSize0);
724 res = usb_get_device_descriptor(newdev,&(newdev->ud_devdescr),FALSE);
727 * Obtain a new address and set the address of the
728 * root hub to this address.
731 addr = usb_new_address(newdev->ud_bus);
732 res = usb_set_address(newdev,addr);
735 * Get the configuration descriptor and all the
736 * associated interface and endpoint descriptors.
739 res = usb_get_config_descriptor(newdev,&cfgdescr,0,
740 sizeof(usb_config_descr_t));
741 if (res != sizeof(usb_config_descr_t)) {
742 printf("[a]usb_get_config_descriptor returns %d\n",res);
745 len = GETUSBFIELD(&cfgdescr,wTotalLength);
746 buf = KMALLOC(len,0);
748 res = usb_get_config_descriptor(newdev,(usb_config_descr_t *)buf,0,len);
749 if (res != len) {
750 printf("[b]usb_get_config_descriptor returns %d\n",res);
753 newdev->ud_cfgdescr = (usb_config_descr_t *) buf;
755 if (usb_noisy > 0) usb_dbg_dumpdescriptors(newdev,buf,len);
758 * Point the hub at the devices it owns
761 softc->uhub_devices[idx] = newdev;
764 * Find the driver for this. It had better be the hub
765 * driver.
768 newdrv = usb_find_driver(newdev);
771 * Call the attach method.
774 if (newdrv) {
775 dev->ud_drv = newdrv; /* remember driver dispatch in device */
776 (*(newdrv->udrv_attach))(newdev,newdrv);
780 else {
783 * The device has been DISCONNECTED.
786 console_log("USB: Device disconnected from bus %d hub %d port %d",
787 dev->ud_bus->ub_num,
788 dev->ud_address,idx+1);
791 * Recover pointer to device below hub and clear
792 * this pointer.
795 newdev = softc->uhub_devices[idx]; /* Get device pointer */
796 softc->uhub_devices[idx] = NULL; /* remove device from hub */
799 * Deassign the USB device's address and then
800 * call detach method to free resources. Devices that
801 * do not have drivers will not have any methods.
804 if (newdev) {
805 if (newdev->ud_drv) {
806 (*(newdev->ud_drv->udrv_detach))(newdev);
808 else {
809 if (usb_noisy > 0) {
810 console_log("USB: Detached device on bus %d hub %d port %d "
811 "has no methods",
812 dev->ud_bus->ub_num,
813 dev->ud_address,idx+1);
817 if (newdev->ud_cfgdescr) KFREE(newdev->ud_cfgdescr);
819 usb_destroy_device(newdev);
829 * Queue up a request for the interrupt pipe. This will catch further
830 * changes at this port.
833 usbhub_queue_intreq(dev,softc);
837 /* *********************************************************************
838 * usbhub_scan1(dev,arg)
840 * Scan one device at this level, or descend if we run into a hub
841 * This is part of the device discovery code.
843 * Input parameters:
844 * dev - current device, maybe a hub
845 * arg - passed from main scan routine
847 * Return value:
849 ********************************************************************* */
852 static int usbhub_scan1(usbdev_t *dev,void *arg)
854 usbhub_softc_t *hub;
857 * If the device is not a hub, we've reached the leaves of the
858 * tree.
861 if (!IS_HUB(dev)) return 0;
864 * Otherwise, scan the ports on this hub.
867 hub = dev->ud_private;
869 if (hub->uhub_flags & UHUB_FLG_NEEDSCAN) {
870 hub->uhub_flags &= ~UHUB_FLG_NEEDSCAN;
871 usbhub_scan_ports(dev,arg);
874 return 0;
877 /* *********************************************************************
878 * usb_scan(bus)
880 * Scan the bus looking for new or removed devices
882 * Input parameters:
883 * bus - bus to scan
885 * Return value:
886 * nothing
887 ********************************************************************* */
889 void usb_scan(usbbus_t *bus)
892 * Call our tree walker with the scan function.
895 usbhub_map_tree(bus,usbhub_scan1,NULL);