Beispiel #1
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;
}
Beispiel #2
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;
}
Beispiel #3
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) {
	    if (usb_noisy > 0)
		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) {
		/* close open pipes, cancel reqs */
		usb_destroy_all_pipes(deldev);
		/* 
		 * Try to process the done queue.  This will complete any
		 * requests that made it out of the pipes while we were
		 * doing the stuff above.
		 */
		usb_poll(deldev->ud_bus);
		/* Call detach method, clean up device softc */
		(*(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) usb_dma_free(deldev->ud_cfgdescr);
	    usb_destroy_device(deldev);
	    }
	}

    if (hub->uhub_imsg != NULL) {
	usb_dma_free(hub->uhub_imsg);
	}
    KFREE(hub);				/* remove softc */

    return 0;
}
Beispiel #4
0
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);
		}
	    }
	}
}
Beispiel #5
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;
}
Beispiel #6
0
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.  */

    portstatus = usb_dma_alloc(sizeof(usb_port_status_t));
    if (portstatus == NULL) return;

    /*
     * 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 > 1) 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 = usb_dma_alloc(len);

		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 > 1) 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) {
		    newdev->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 */

		usbhub_markdetached(newdev);		/* mark device and all subordinate 
							   devices as "removing" */

		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) {
			/* close open pipes, cancel reqs */
			usb_destroy_all_pipes(newdev);
			/* 
			 * Try to process the done queue.  This will complete any
			 * requests that made it out of the pipes while we were
			 * doing the stuff above.
			 */
			usb_poll(newdev->ud_bus);
			/* Call detach method, clean up device softc */
			(*(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) usb_dma_free(newdev->ud_cfgdescr);

		    usb_destroy_device(newdev);	
		    }

		}
	    }

	}

    usb_dma_free(portstatus);

    /*
     * Queue up a request for the interrupt pipe.  This will catch further
     * changes at this port.
     */

    usbhub_queue_intreq(dev,softc);

}