diff options
Diffstat (limited to 'cfe/cfe/usb/usbhub.c')
-rw-r--r-- | cfe/cfe/usb/usbhub.c | 912 |
1 files changed, 912 insertions, 0 deletions
diff --git a/cfe/cfe/usb/usbhub.c b/cfe/cfe/usb/usbhub.c new file mode 100644 index 0000000..1e571ed --- /dev/null +++ b/cfe/cfe/usb/usbhub.c @@ -0,0 +1,912 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * USB Hub and device discovery code File: usbhub.c + * + * This module deals with hubs and device discovery. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#ifndef _CFE_ +#include <stdio.h> +#include <time.h> +#include <memory.h> +#include <stdint.h> +#include "usbhack.h" +#else +#include "lib_types.h" +#include "lib_string.h" +#include "lib_printf.h" +#include "cfe_console.h" +#endif + +#include "lib_malloc.h" +#include "lib_queue.h" +#include "usbchap9.h" +#include "usbd.h" + +/* ********************************************************************* + * Macros for common hub requests + ********************************************************************* */ + +#define usbhub_set_port_feature(dev,port,feature) \ + usb_simple_request(dev,0x23,USB_HUBREQ_SET_FEATURE,feature,port) + +#define usbhub_set_hub_feature(dev,feature) \ + usb_simple_request(dev,0x20,USB_HUBREQ_SET_FEATURE,feature,0) + +#define usbhub_clear_port_feature(dev,port,feature) \ + usb_simple_request(dev,0x23,USB_HUBREQ_CLEAR_FEATURE,feature,port) + +#define usbhub_clear_hub_feature(dev,feature) \ + usb_simple_request(dev,0x20,USB_HUBREQ_CLEAR_FEATURE,feature,0) + + +/* ********************************************************************* + * Externs + ********************************************************************* */ + +extern int usb_noisy; + +/* ********************************************************************* + * Forward declarations + ********************************************************************* */ + +static int usbhub_attach(usbdev_t *dev,usb_driver_t *drv); +static int usbhub_detach(usbdev_t *dev); + +/* ********************************************************************* + * Hub-specific data structures + ********************************************************************* */ + +#define UHUB_MAX_DEVICES 8 + +#define UHUB_FLG_NEEDSCAN 1 + +typedef struct usbhub_softc_s { + usb_hub_descr_t uhub_descr; + usb_hub_status_t uhub_status; + int uhub_ipipe; + int uhub_ipipemps; + int uhub_nports; + unsigned int uhub_flags; + uint8_t uhub_imsg[8]; + usbdev_t *uhub_devices[UHUB_MAX_DEVICES]; +} usbhub_softc_t; + +usb_driver_t usbhub_driver = { + "USB Hub", + usbhub_attach, + usbhub_detach +}; + + +/* ********************************************************************* + * usbhub_ireq_callback(ur) + * + * this routine is called when the transfer we queued to the + * interrupt endpoint on the hub completes. It means that + * *some* port on the hub needs attention. The data indicates + * which port, but for our purposes we don't really care - if + * we get this callback, we'll set a flag and re-probe the bus. + * + * Input parameters: + * ur - usbreq that completed + * + * Return value: + * 0 + ********************************************************************* */ + +static int usbhub_ireq_callback(usbreq_t *ur) +{ + int idx; + usbhub_softc_t *uhub = (ur->ur_dev->ud_private); + + /* + * Check to see if the request was cancelled by someone + * deleting our endpoint. + */ + + if (ur->ur_status == 0xFF) { + usb_free_request(ur); + return 0; + } + + /* + * Check to see if any of our ports need attention + */ + + for (idx = 1; idx <= uhub->uhub_nports; idx++) { + if (ur->ur_buffer[0] & (1<<idx)) { + + /* + * Mark the hub as needing a scan, and mark the bus as well + * so the top-level polling will notice. + */ + + uhub->uhub_flags |= UHUB_FLG_NEEDSCAN; + ur->ur_dev->ud_bus->ub_flags |= UB_FLG_NEEDSCAN; + } + } + + + /* + * Do NOT requeue the request here. We will do this + * during exploration. + */ + + usb_free_request(ur); + + return 0; +} + + +/* ********************************************************************* + * usbhub_get_hub_descriptor(dev,dscr,idx,maxlen) + * + * Obtain the hub descriptor (special for hubs) from the + * device. + * + * Input parameters: + * dev - usb device + * dscr - place to put hub descriptor + * idx - which hub descriptor to get (usually zero) + * maxlen - max # of bytes to return + * + * Return value: + * # of bytes returned + ********************************************************************* */ + +static int usbhub_get_hub_descriptor(usbdev_t *dev,usb_hub_descr_t *dscr,int idx,int maxlen) +{ + return usb_std_request(dev,0xA0, + USB_HUBREQ_GET_DESCRIPTOR, + 0,0, + (uint8_t *) dscr, + maxlen); +} + + +/* ********************************************************************* + * usbhub_get_hub_status(dev,status) + * + * Obtain the hub status (special for hubs) from the + * device. + * + * Input parameters: + * dev - usb device + * status - where to put hub status structure + * + * Return value: + * # of bytes returned + ********************************************************************* */ + +#if 0 +static int usbhub_get_hub_status(usbdev_t *dev,usb_hub_status_t *status) +{ + return usb_std_request(dev, + 0xA0, + 0x00, + 0, + 0, + (uint8_t *) status, + sizeof(usbhub_status_t)); +} +#endif + + +/* ********************************************************************* + * usbhub_get_port_status(dev,port,status) + * + * Obtain the port status for a particular port from + * device. + * + * Input parameters: + * dev - usb device + * port - 1-based port number + * status - where to put port status structure + * + * Return value: + * # of bytes returned + ********************************************************************* */ + +static int usbhub_get_port_status(usbdev_t *dev,int port,usb_port_status_t *status) +{ + return usb_std_request(dev, + 0xA3, + 0, + 0, + port, + (uint8_t *) status, + sizeof(usb_port_status_t)); +} + + +/* ********************************************************************* + * usbhub_queue_intreq(dev,softc) + * + * Queue the transfer to the interrupt pipe that will catch + * the hub's port status changes + * + * Input parameters: + * dev - usb device + * softc - hub-specific data + * + * Return value: + * nothing + ********************************************************************* */ + +static void usbhub_queue_intreq(usbdev_t *dev,usbhub_softc_t *softc) +{ + usbreq_t *ur; + + ur = usb_make_request(dev, + softc->uhub_ipipe, + softc->uhub_imsg,softc->uhub_ipipemps, + UR_FLAG_IN | UR_FLAG_SHORTOK); + + ur->ur_callback = usbhub_ireq_callback; + + usb_queue_request(ur); +} + + +/* ********************************************************************* + * usbhub_attach(dev,drv) + * + * This routine is called when the hub attaches to the system. + * We complete initialization for the hub and set things up so + * that an explore will happen soon. + * + * Input parameters: + * dev - usb device + * drv - driver structure + * + * Return value: + * 0 + ********************************************************************* */ + +static int usbhub_attach(usbdev_t *dev,usb_driver_t *drv) +{ + usb_device_status_t devstatus; + usb_config_descr_t *cfgdscr; + usb_interface_descr_t *ifdscr; + usb_endpoint_descr_t *epdscr; + usbhub_softc_t *softc; + + /* + * Remember the driver dispatch. + */ + + dev->ud_drv = drv; + + softc = KMALLOC(sizeof(usbhub_softc_t),0); + memset(softc,0,sizeof(usbhub_softc_t)); + dev->ud_private = softc; + + /* + * Dig out the data from the configuration descriptor + * (we got this from the device before attach time) + */ + + cfgdscr = dev->ud_cfgdescr; + epdscr = usb_find_cfg_descr(dev,USB_ENDPOINT_DESCRIPTOR_TYPE,0); + ifdscr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0); + + /* + * Get device status (is this really necessary?) + */ + + usb_get_device_status(dev,&devstatus); + + /* + * Set us to configuration index 0 + */ + + usb_set_configuration(dev,cfgdscr->bConfigurationValue); + + /* + * Get the hub descriptor. Get the first 8 bytes first, then get the rest + * if there is more. + */ + + if (usbhub_get_hub_descriptor(dev,&(softc->uhub_descr),0,USB_HUB_DESCR_SIZE) > USB_HUB_DESCR_SIZE) { + usbhub_get_hub_descriptor(dev,&(softc->uhub_descr),0,softc->uhub_descr.bDescriptorLength); + } + + /* + * remember stuff from the hub descriptor + */ + + softc->uhub_nports = softc->uhub_descr.bNumberOfPorts; + + /* + * Open the interrupt pipe + */ + + softc->uhub_ipipe = usb_open_pipe(dev,epdscr); + softc->uhub_ipipemps = GETUSBFIELD(epdscr,wMaxPacketSize); + + /* + * Mark the bus and the hub as needing service. + */ + + softc->uhub_flags |= UHUB_FLG_NEEDSCAN; + dev->ud_bus->ub_flags |= UB_FLG_NEEDSCAN; + + /* + * Okay, that's it. The top-level USB daemon will notice + * that the bus needs service and will invoke the exploration code. + * This may in turn require additional explores until + * everything settles down. + */ + + return 0; +} + + +/* ********************************************************************* + * usbhub_detach(dev) + * + * Called when a hub is removed from the system - we remove + * all subordinate devicees. + * + * Input parameters: + * dev - device (hub) that was removed + * + * Return value: + * 0 + ********************************************************************* */ + +static int usbhub_detach(usbdev_t *dev) +{ + usbhub_softc_t *hub; + usbdev_t *deldev; + int idx; + + if (!IS_HUB(dev)) return 0; /* should not happen */ + + hub = dev->ud_private; + for (idx = 0; idx < UHUB_MAX_DEVICES; idx++) { + deldev = hub->uhub_devices[idx]; + if (deldev) { + console_log("USB: Removing device attached to bus %d hub %d port %d", + dev->ud_bus->ub_num, + dev->ud_address,idx+1); + if (deldev->ud_drv) { + (*(deldev->ud_drv->udrv_detach))(deldev); + } + else { + if (usb_noisy > 0) { + console_log("USB: Detached device on bus %d hub %d port %d " + "has no methods", + dev->ud_bus->ub_num, + dev->ud_address,idx+1); + } + } + if (deldev->ud_cfgdescr) KFREE(deldev->ud_cfgdescr); + usb_destroy_device(deldev); + } + } + + KFREE(hub); /* remove softc */ + + return 0; +} + + + +/* ********************************************************************* + * usbhub_map_tree1(dev,level,func,arg) + * + * This routine is used in recursive device tree exploration. + * We call 'func' for each device at this tree, and descend + * when we run into hubs + * + * Input parameters: + * dev - current device pointer + * level - current nesting level + * func - function to call + * arg - argument to pass to function + * + * Return value: + * nothing + ********************************************************************* */ + +static void usbhub_map_tree1(usbdev_t *dev,int level, + int (*func)(usbdev_t *dev,void *arg),void *arg) +{ + usbhub_softc_t *hub; + int idx; + + (*func)(dev,arg); + + if (IS_HUB(dev)) { + hub = dev->ud_private; + for (idx = 0; idx < UHUB_MAX_DEVICES; idx++) { + if (hub->uhub_devices[idx]) { + usbhub_map_tree1(hub->uhub_devices[idx],level+1,func,arg); + } + } + } +} + +/* ********************************************************************* + * usbhub_map_tree(bus,func,arg) + * + * Call a function for each device in the tree + * + * Input parameters: + * bus - bus to scan + * func - function to call + * arg - argument to pass to function + * + * Return value: + * nothing + ********************************************************************* */ + +void usbhub_map_tree(usbbus_t *bus,int (*func)(usbdev_t *dev,void *arg),void *arg) +{ + usbhub_map_tree1(bus->ub_roothub,0,func,arg); +} + + +/* ********************************************************************* + * usbhub_dumpbus1(dev,arg) + * + * map function to dump devices in the device tree + * + * Input parameters: + * dev - device we're working on + * arg - argument from map_tree call + * + * Return value: + * 0 + ********************************************************************* */ + +static int usbhub_dumpbus1(usbdev_t *dev,void *arg) +{ + uint32_t *verbose = (uint32_t *) arg; + + if ((*verbose & 0x00FF) && (dev->ud_address != (*verbose & 0x00FF))) return 0; + + if (*verbose & 0x100) { + printf("============================================================================\n"); + } + + printf("Bus %d Device %d Class %d Vendor %04X Product %04X ", + dev->ud_bus->ub_num, + dev->ud_address, + dev->ud_devdescr.bDeviceClass, + GETUSBFIELD(&(dev->ud_devdescr),idVendor), + GETUSBFIELD(&(dev->ud_devdescr),idProduct)); + + + if (IS_HUB(dev)) { + printf("[HUB]\n"); + } + else { + printf("[DEVICE]\n"); + } + + if (*verbose & 0x100) { + usb_dbg_dumpdescriptors(dev,(uint8_t *) &(dev->ud_devdescr),dev->ud_devdescr.bLength); + usb_dbg_dumpcfgdescr(dev); + } + + return 0; +} + + +/* ********************************************************************* + * usbhub_dumpbus(bus,verbose) + * + * Dump information about devices on the USB bus. + * + * Input parameters: + * bus - bus to dump + * verbose - nonzero to display more info, like descriptors + * + * Return value: + * nothing + ********************************************************************* */ + +void usbhub_dumpbus(usbbus_t *bus,uint32_t verbose) +{ + usbhub_map_tree(bus,usbhub_dumpbus1,&verbose); +} + + + +/* ********************************************************************* + * usbhub_reset_devicee(dev,port,status) + * + * Reset a device on a hub port. This routine does a + * USB_PORT_FEATURE_RESET on the specified port, waits for the + * bit to clear, and returns. It is used to get a device into the + * DEFAULT state according to the spec. + * + * Input parameters: + * dev - hub device + * port - port number(1-based) + * status - place to return port_status structure after + * reset completes + * + * Return value: + * nothing + ********************************************************************* */ + +static void usbhub_reset_device(usbdev_t *dev,int port,usb_port_status_t *portstatus) +{ + console_log("USB: Resetting device on bus %d port %d",dev->ud_bus->ub_num,port); +#ifndef _CFE_ + fflush(stdout); +#endif + + usbhub_set_port_feature(dev,port,USB_PORT_FEATURE_RESET); + + usbhub_get_port_status(dev,port,portstatus); + + for (;;) { + usbhub_get_port_status(dev,port,portstatus); + if ((GETUSBFIELD((portstatus),wPortStatus) & USB_PORT_STATUS_RESET) == 0) break; + usb_delay_ms(dev->ud_bus,250); + } + usb_delay_ms(dev->ud_bus,250); + + usbhub_clear_port_feature(dev,port,USB_PORT_FEATURE_C_PORT_RESET); +} + + + +/* ********************************************************************* + * usbhub_scan_ports(dev,arg) + * + * Scan the ports on this hub for new or removed devices. + * + * Input parameters: + * dev - hub device + * arg - passed from bus scan main routines + * + * Return value: + * nothing + ********************************************************************* */ + +static void usbhub_scan_ports(usbdev_t *dev,void *arg) +{ + uint16_t current; + uint16_t changed; + usbhub_softc_t *softc; + int idx; + int res; + int len; + uint8_t *buf; + usbdev_t *newdev; + usb_driver_t *newdrv; + int addr; + usb_port_status_t portstatus; + usb_config_descr_t cfgdescr; + unsigned int powerondelay; + + if (!IS_HUB(dev)) return; /* should not happen. */ + + /* + * We know this is a hub. Get the softc back. + */ + + softc = (usbhub_softc_t *) dev->ud_private; + + powerondelay = ((unsigned int) softc->uhub_descr.bPowerOnToPowerGood)*2 + 20; + + /* + * Turn on the power to the ports whose power is not yet on. + */ + + for (idx = 0; idx < softc->uhub_nports; idx++) { + + usbhub_get_port_status(dev,idx+1,&portstatus); + + current = GETUSBFIELD((&portstatus),wPortStatus); + changed = GETUSBFIELD((&portstatus),wPortChange); + if (usb_noisy > 1) { + printf("BeforePowerup: port %d status %04X changed %04X\n",idx+1,current,changed); + } + + if (!(current & USB_PORT_STATUS_POWER)) { + if (usb_noisy > 1) console_log("USB: Powering up bus %d port %d", + dev->ud_bus->ub_num,idx+1); + usbhub_set_port_feature(dev,idx+1,USB_PORT_FEATURE_POWER); + usb_delay_ms(dev->ud_bus,powerondelay); + } + } + + /* + * Begin exploration at this level. + */ + + for (idx = 0; idx < softc->uhub_nports; idx++) { + + usbhub_get_port_status(dev,idx+1,&portstatus); + + current = GETUSBFIELD((&portstatus),wPortStatus); + changed = GETUSBFIELD((&portstatus),wPortChange); + + if (usb_noisy > 0) { + printf("USB: Explore: Bus %d Hub %d port %d status %04X changed %04X\n", + dev->ud_bus->ub_num, + dev->ud_address,idx+1,current,changed); + usb_dbg_dumpportstatus(idx+1,&portstatus,1); + } + + +// if (changed & USB_PORT_STATUS_RESET) { +// usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_RESET); +// } + + if (changed & USB_PORT_STATUS_ENABLED) { + usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_ENABLE); + } + + if (changed & USB_PORT_STATUS_CONNECT) { + /* + * A device was either connected or disconnected. + * Clear the status change first. + */ + + usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_CONNECTION); + + if (current & USB_PORT_STATUS_CONNECT) { + + /* + * The device has been CONNECTED. + */ + + console_log("USB: New device connected to bus %d hub %d port %d", + dev->ud_bus->ub_num, + dev->ud_address,idx+1); + + /* + * Reset the device. Reuse our old port status structure + * so we get the latest status. Some devices do not report + * lowspeed until they are reset. + */ + + usbhub_reset_device(dev,idx+1,&portstatus); + current = GETUSBFIELD((&portstatus),wPortStatus); + changed = GETUSBFIELD((&portstatus),wPortChange); + + /* + * Create a device for this port. + */ + + newdev = usb_create_device(dev->ud_bus,(current & USB_PORT_STATUS_LOWSPD) ? 1 : 0); + + /* + * Get the device descriptor. + */ + + res = usb_get_device_descriptor(newdev,&(newdev->ud_devdescr),TRUE); + + if (usb_noisy > 0) usb_dbg_dumpdescriptors(newdev,(uint8_t *) &(newdev->ud_devdescr),8); + + /* + * Set up the max packet size for the control endpoint, + * then get the rest of the descriptor. + */ + + usb_set_ep0mps(newdev,newdev->ud_devdescr.bMaxPacketSize0); + res = usb_get_device_descriptor(newdev,&(newdev->ud_devdescr),FALSE); + + /* + * Obtain a new address and set the address of the + * root hub to this address. + */ + + addr = usb_new_address(newdev->ud_bus); + res = usb_set_address(newdev,addr); + + /* + * Get the configuration descriptor and all the + * associated interface and endpoint descriptors. + */ + + res = usb_get_config_descriptor(newdev,&cfgdescr,0, + sizeof(usb_config_descr_t)); + if (res != sizeof(usb_config_descr_t)) { + printf("[a]usb_get_config_descriptor returns %d\n",res); + } + + len = GETUSBFIELD(&cfgdescr,wTotalLength); + buf = KMALLOC(len,0); + + res = usb_get_config_descriptor(newdev,(usb_config_descr_t *)buf,0,len); + if (res != len) { + printf("[b]usb_get_config_descriptor returns %d\n",res); + } + + newdev->ud_cfgdescr = (usb_config_descr_t *) buf; + + if (usb_noisy > 0) usb_dbg_dumpdescriptors(newdev,buf,len); + + /* + * Point the hub at the devices it owns + */ + + softc->uhub_devices[idx] = newdev; + + /* + * Find the driver for this. It had better be the hub + * driver. + */ + + newdrv = usb_find_driver(newdev); + + /* + * Call the attach method. + */ + + if (newdrv) { + dev->ud_drv = newdrv; /* remember driver dispatch in device */ + (*(newdrv->udrv_attach))(newdev,newdrv); + } + } + + else { + + /* + * The device has been DISCONNECTED. + */ + + console_log("USB: Device disconnected from bus %d hub %d port %d", + dev->ud_bus->ub_num, + dev->ud_address,idx+1); + + /* + * Recover pointer to device below hub and clear + * this pointer. + */ + + newdev = softc->uhub_devices[idx]; /* Get device pointer */ + softc->uhub_devices[idx] = NULL; /* remove device from hub */ + + /* + * Deassign the USB device's address and then + * call detach method to free resources. Devices that + * do not have drivers will not have any methods. + */ + + if (newdev) { + if (newdev->ud_drv) { + (*(newdev->ud_drv->udrv_detach))(newdev); + } + else { + if (usb_noisy > 0) { + console_log("USB: Detached device on bus %d hub %d port %d " + "has no methods", + dev->ud_bus->ub_num, + dev->ud_address,idx+1); + } + } + + if (newdev->ud_cfgdescr) KFREE(newdev->ud_cfgdescr); + + usb_destroy_device(newdev); + } + + } + } + + } + + + /* + * Queue up a request for the interrupt pipe. This will catch further + * changes at this port. + */ + + usbhub_queue_intreq(dev,softc); + +} + +/* ********************************************************************* + * usbhub_scan1(dev,arg) + * + * Scan one device at this level, or descend if we run into a hub + * This is part of the device discovery code. + * + * Input parameters: + * dev - current device, maybe a hub + * arg - passed from main scan routine + * + * Return value: + * 0 + ********************************************************************* */ + + +static int usbhub_scan1(usbdev_t *dev,void *arg) +{ + usbhub_softc_t *hub; + + /* + * If the device is not a hub, we've reached the leaves of the + * tree. + */ + + if (!IS_HUB(dev)) return 0; + + /* + * Otherwise, scan the ports on this hub. + */ + + hub = dev->ud_private; + + if (hub->uhub_flags & UHUB_FLG_NEEDSCAN) { + hub->uhub_flags &= ~UHUB_FLG_NEEDSCAN; + usbhub_scan_ports(dev,arg); + } + + return 0; +} + +/* ********************************************************************* + * usb_scan(bus) + * + * Scan the bus looking for new or removed devices + * + * Input parameters: + * bus - bus to scan + * + * Return value: + * nothing + ********************************************************************* */ + +void usb_scan(usbbus_t *bus) +{ + /* + * Call our tree walker with the scan function. + */ + + usbhub_map_tree(bus,usbhub_scan1,NULL); +} + + + + |