int kue_load_fw(struct kue_softc *sc) { usb_device_descriptor_t dd; usbd_status err; struct kue_firmware *fw; u_char *buf; size_t buflen; DPRINTFN(1,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__)); /* * First, check if we even need to load the firmware. * If the device was still attached when the system was * rebooted, it may already have firmware loaded in it. * If this is the case, we don't need to do it again. * And in fact, if we try to load it again, we'll hang, * so we have to avoid this condition if we don't want * to look stupid. * * We can test this quickly by checking the bcdRevision * code. The NIC will return a different revision code if * it's probed while the firmware is still loaded and * running. */ if (usbd_get_device_desc(sc->kue_udev, &dd)) return (EIO); if (UGETW(dd.bcdDevice) >= KUE_WARM_REV) { printf("%s: warm boot, no firmware download\n", sc->kue_dev.dv_xname); return (0); } err = loadfirmware("kue", &buf, &buflen); if (err) { printf("%s: failed loadfirmware of file %s: errno %d\n", sc->kue_dev.dv_xname, "kue", err); return (err); } fw = (struct kue_firmware *)buf; printf("%s: cold boot, downloading firmware\n", sc->kue_dev.dv_xname); /* Load code segment */ DPRINTFN(1,("%s: kue_load_fw: download code_seg\n", sc->kue_dev.dv_xname)); err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, (void *)&fw->data[0], ntohl(fw->codeseglen)); if (err) { printf("%s: failed to load code segment: %s\n", sc->kue_dev.dv_xname, usbd_errstr(err)); free(buf, M_DEVBUF); return (EIO); } /* Load fixup segment */ DPRINTFN(1,("%s: kue_load_fw: download fix_seg\n", sc->kue_dev.dv_xname)); err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, (void *)&fw->data[ntohl(fw->codeseglen)], ntohl(fw->fixseglen)); if (err) { printf("%s: failed to load fixup segment: %s\n", sc->kue_dev.dv_xname, usbd_errstr(err)); free(buf, M_DEVBUF); return (EIO); } /* Send trigger command. */ DPRINTFN(1,("%s: kue_load_fw: download trig_seg\n", sc->kue_dev.dv_xname)); err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, (void *)&fw->data[ntohl(fw->codeseglen) + ntohl(fw->fixseglen)], ntohl(fw->trigseglen)); if (err) { printf("%s: failed to load trigger segment: %s\n", sc->kue_dev.dv_xname, usbd_errstr(err)); free(buf, M_DEVBUF); return (EIO); } free(buf, M_DEVBUF); usbd_delay_ms(sc->kue_udev, 10); /* * Reload device descriptor. * Why? The chip without the firmware loaded returns * one revision code. The chip with the firmware * loaded and running returns a *different* revision * code. This confuses the quirk mechanism, which is * dependent on the revision data. */ (void)usbd_reload_device_desc(sc->kue_udev); DPRINTFN(1,("%s: %s: done\n", sc->kue_dev.dv_xname, __func__)); /* Reset the adapter. */ kue_reset(sc); return (0); }
void uticom_attach_hook(void *arg) { struct uticom_softc *sc = arg; usb_config_descriptor_t *cdesc; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usbd_status err; int status, i; usb_device_descriptor_t *dd; struct ucom_attach_args uca; /* Initialize endpoints. */ uca.bulkin = uca.bulkout = -1; sc->sc_intr_number = -1; sc->sc_intr_pipe = NULL; dd = usbd_get_device_descriptor(sc->sc_udev); DPRINTF(("%s: uticom_attach: num of configurations %d\n", sc->sc_dev.dv_xname, dd->bNumConfigurations)); /* The device without firmware has single configuration with single * bulk out interface. */ if (dd->bNumConfigurations > 1) goto fwload_done; /* Loading firmware. */ DPRINTF(("%s: uticom_attach: starting loading firmware\n", sc->sc_dev.dv_xname)); err = usbd_set_config_index(sc->sc_udev, UTICOM_CONFIG_INDEX, 1); if (err) { printf("%s: failed to set configuration: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); usbd_deactivate(sc->sc_udev); return; } /* Get the config descriptor. */ cdesc = usbd_get_config_descriptor(sc->sc_udev); if (cdesc == NULL) { printf("%s: failed to get configuration descriptor\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } err = usbd_device2interface_handle(sc->sc_udev, UTICOM_IFACE_INDEX, &sc->sc_iface); if (err) { printf("%s: failed to get interface: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); usbd_deactivate(sc->sc_udev); return; } /* Find the bulk out interface used to upload firmware. */ id = usbd_get_interface_descriptor(sc->sc_iface); sc->sc_iface_number = id->bInterfaceNumber; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (ed == NULL) { printf("%s: no endpoint descriptor for %d\n", sc->sc_dev.dv_xname, i); usbd_deactivate(sc->sc_udev); return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { uca.bulkout = ed->bEndpointAddress; DPRINTF(("%s: uticom_attach: data bulk out num: %d\n", sc->sc_dev.dv_xname, ed->bEndpointAddress)); } if (uca.bulkout == -1) { printf("%s: could not find data bulk out\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } } status = uticom_download_fw(sc, uca.bulkout, sc->sc_udev); if (status) { printf("%s: firmware download failed\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } else { DPRINTF(("%s: firmware download succeeded\n", sc->sc_dev.dv_xname)); } status = usbd_reload_device_desc(sc->sc_udev); if (status) { printf("%s: error reloading device descriptor\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } fwload_done: dd = usbd_get_device_descriptor(sc->sc_udev); DPRINTF(("%s: uticom_attach: num of configurations %d\n", sc->sc_dev.dv_xname, dd->bNumConfigurations)); err = usbd_set_config_index(sc->sc_udev, UTICOM_ACTIVE_INDEX, 1); if (err) { printf("%s: failed to set configuration: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); usbd_deactivate(sc->sc_udev); return; } /* Get the config descriptor. */ cdesc = usbd_get_config_descriptor(sc->sc_udev); if (cdesc == NULL) { printf("%s: failed to get configuration descriptor\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } /* Get the interface (XXX: multiport chips are not supported yet). */ err = usbd_device2interface_handle(sc->sc_udev, UTICOM_IFACE_INDEX, &sc->sc_iface); if (err) { printf("%s: failed to get interface: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); usbd_deactivate(sc->sc_udev); return; } /* Find the interrupt endpoints. */ id = usbd_get_interface_descriptor(sc->sc_iface); sc->sc_iface_number = id->bInterfaceNumber; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (ed == NULL) { printf("%s: no endpoint descriptor for %d\n", sc->sc_dev.dv_xname, i); usbd_deactivate(sc->sc_udev); return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { sc->sc_intr_number = ed->bEndpointAddress; sc->sc_isize = UGETW(ed->wMaxPacketSize); } } if (sc->sc_intr_number == -1) { printf("%s: could not find interrupt in\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } /* Keep interface for interrupt. */ sc->sc_intr_iface = sc->sc_iface; /* Find the bulk{in,out} endpoints. */ id = usbd_get_interface_descriptor(sc->sc_iface); sc->sc_iface_number = id->bInterfaceNumber; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (ed == NULL) { printf("%s: no endpoint descriptor for %d\n", sc->sc_dev.dv_xname, i); usbd_deactivate(sc->sc_udev); return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { uca.bulkin = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { uca.bulkout = ed->bEndpointAddress; } } if (uca.bulkin == -1) { printf("%s: could not find data bulk in\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } if (uca.bulkout == -1) { printf("%s: could not find data bulk out\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } sc->sc_dtr = sc->sc_rts = -1; uca.portno = UCOM_UNK_PORTNO; uca.ibufsize = UTICOM_IBUFSZ; uca.obufsize = UTICOM_OBUFSZ; uca.ibufsizepad = UTICOM_IBUFSZ; uca.device = sc->sc_udev; uca.iface = sc->sc_iface; uca.opkthdrlen = 0; uca.methods = &uticom_methods; uca.arg = sc; uca.info = NULL; err = uticom_reset(sc); if (err) { printf("%s: reset failed: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); usbd_deactivate(sc->sc_udev); return; } DPRINTF(("%s: uticom_attach: in = 0x%x, out = 0x%x, intr = 0x%x\n", sc->sc_dev.dv_xname, uca.bulkin, uca.bulkout, sc->sc_intr_number)); sc->sc_subdev = config_found_sm((struct device *)sc, &uca, ucomprint, ucomsubmatch); }
/* * Called when a new device has been put in the powered state, * but not yet in the addressed state. * Get initial descriptor, set the address, get full descriptor, * and attach a driver. */ usbd_status usbd_new_device(device_t parent, struct usbd_bus* bus, int depth, int speed, int port, struct usbd_port *up) { USBHIST_FUNC(); USBHIST_CALLED(usbdebug); struct usbd_device *dev, *adev; struct usbd_device *hub; usb_device_descriptor_t *dd; usb_port_status_t ps; usbd_status err; int addr; int i; int p; DPRINTF("bus=%p port=%d depth=%d speed=%d", bus, port, depth, speed); if (bus->ub_methods->ubm_newdev != NULL) return (bus->ub_methods->ubm_newdev)(parent, bus, depth, speed, port, up); addr = usbd_getnewaddr(bus); if (addr < 0) { printf("%s: No free USB addresses, new device ignored.\n", device_xname(bus->ub_usbctl)); return USBD_NO_ADDR; } dev = kmem_zalloc(sizeof(*dev), KM_SLEEP); if (dev == NULL) return USBD_NOMEM; dev->ud_bus = bus; /* Set up default endpoint handle. */ dev->ud_ep0.ue_edesc = &dev->ud_ep0desc; /* Set up default endpoint descriptor. */ dev->ud_ep0desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE; dev->ud_ep0desc.bDescriptorType = UDESC_ENDPOINT; dev->ud_ep0desc.bEndpointAddress = USB_CONTROL_ENDPOINT; dev->ud_ep0desc.bmAttributes = UE_CONTROL; /* * temporary, will be fixed after first descriptor fetch * (which uses 64 bytes so it shouldn't be less), * highspeed devices must support 64 byte packets anyway */ if (speed == USB_SPEED_HIGH || speed == USB_SPEED_FULL) USETW(dev->ud_ep0desc.wMaxPacketSize, 64); else USETW(dev->ud_ep0desc.wMaxPacketSize, USB_MAX_IPACKET); dev->ud_ep0desc.bInterval = 0; /* doesn't matter, just don't leave it uninitialized */ dev->ud_ep0.ue_toggle = 0; dev->ud_quirks = &usbd_no_quirk; dev->ud_addr = USB_START_ADDR; dev->ud_ddesc.bMaxPacketSize = 0; dev->ud_depth = depth; dev->ud_powersrc = up; dev->ud_myhub = up->up_parent; up->up_dev = dev; /* Locate port on upstream high speed hub */ for (adev = dev, hub = up->up_parent; hub != NULL && hub->ud_speed != USB_SPEED_HIGH; adev = hub, hub = hub->ud_myhub) ; if (hub) { for (p = 0; p < hub->ud_hub->uh_hubdesc.bNbrPorts; p++) { if (hub->ud_hub->uh_ports[p].up_dev == adev) { dev->ud_myhsport = &hub->ud_hub->uh_ports[p]; goto found; } } panic("usbd_new_device: cannot find HS port"); found: DPRINTFN(1, "high speed port %d", p, 0, 0, 0); } else { dev->ud_myhsport = NULL; } dev->ud_speed = speed; dev->ud_langid = USBD_NOLANG; dev->ud_cookie.cookie = ++usb_cookie_no; /* Establish the default pipe. */ err = usbd_setup_pipe_flags(dev, 0, &dev->ud_ep0, USBD_DEFAULT_INTERVAL, &dev->ud_pipe0, USBD_MPSAFE); if (err) { usbd_remove_device(dev, up); return err; } dd = &dev->ud_ddesc; /* Try a few times in case the device is slow (i.e. outside specs.) */ for (i = 0; i < 10; i++) { /* Get the first 8 bytes of the device descriptor. */ err = usbd_get_initial_ddesc(dev, dd); if (!err) break; usbd_delay_ms(dev, 200); if ((i & 3) == 3) usbd_reset_port(up->up_parent, port, &ps); } if (err) { DPRINTF("addr=%d, getting first desc failed: %d", addr, err, 0, 0); usbd_remove_device(dev, up); return err; } /* Windows resets the port here, do likewise */ if (up->up_parent) usbd_reset_port(up->up_parent, port, &ps); if (speed == USB_SPEED_HIGH) { /* Max packet size must be 64 (sec 5.5.3). */ if (dd->bMaxPacketSize != USB_2_MAX_CTRL_PACKET) { #ifdef DIAGNOSTIC printf("usbd_new_device: addr=%d bad max packet " "size=%d. adjusting to %d.\n", addr, dd->bMaxPacketSize, USB_2_MAX_CTRL_PACKET); #endif dd->bMaxPacketSize = USB_2_MAX_CTRL_PACKET; } } DPRINTF("adding unit addr=%d, rev=%02x, class=%d, subclass=%d", addr, UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass); DPRINTF("protocol=%d, maxpacket=%d, len=%d, speed=%d", dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength, dev->ud_speed); if (dd->bDescriptorType != UDESC_DEVICE) { /* Illegal device descriptor */ DPRINTF("illegal descriptor %d", dd->bDescriptorType, 0, 0, 0); usbd_remove_device(dev, up); return USBD_INVAL; } if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) { DPRINTF("bad length %d", dd->bLength, 0, 0, 0); usbd_remove_device(dev, up); return USBD_INVAL; } USETW(dev->ud_ep0desc.wMaxPacketSize, dd->bMaxPacketSize); /* Re-establish the default pipe with the new MPS. */ usbd_kill_pipe(dev->ud_pipe0); err = usbd_setup_pipe_flags(dev, 0, &dev->ud_ep0, USBD_DEFAULT_INTERVAL, &dev->ud_pipe0, USBD_MPSAFE); if (err) { DPRINTF("setup default pipe failed err %d", err, 0, 0, 0); usbd_remove_device(dev, up); return err; } /* Set the address */ DPRINTFN(5, "setting device address=%d", addr, 0, 0, 0); err = usbd_set_address(dev, addr); if (err) { DPRINTF("set address %d failed, err = %d", addr, err, 0, 0); err = USBD_SET_ADDR_FAILED; usbd_remove_device(dev, up); return err; } /* Allow device time to set new address */ usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE); dev->ud_addr = addr; /* new device address now */ bus->ub_devices[addr] = dev; /* Re-establish the default pipe with the new address. */ usbd_kill_pipe(dev->ud_pipe0); err = usbd_setup_pipe_flags(dev, 0, &dev->ud_ep0, USBD_DEFAULT_INTERVAL, &dev->ud_pipe0, USBD_MPSAFE); if (err) { DPRINTF("setup default pipe failed, err = %d", err, 0, 0, 0); usbd_remove_device(dev, up); return err; } err = usbd_reload_device_desc(dev); if (err) { DPRINTF("addr=%d, getting full desc failed, err = %d", addr, err, 0, 0); usbd_remove_device(dev, up); return err; } /* Assume 100mA bus powered for now. Changed when configured. */ dev->ud_power = USB_MIN_POWER; dev->ud_selfpowered = 0; DPRINTF("new dev (addr %d), dev=%p, parent=%p", addr, dev, parent, 0); usbd_get_device_strings(dev); usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev); if (port == 0) { /* root hub */ KASSERT(addr == 1); usbd_attach_roothub(parent, dev); return USBD_NORMAL_COMPLETION; } err = usbd_probe_and_attach(parent, dev, port, addr); if (err) { usbd_remove_device(dev, up); return err; } return USBD_NORMAL_COMPLETION; }
Static int kue_load_fw(struct kue_softc *sc) { usb_device_descriptor_t dd; usbd_status err; DPRINTFN(1,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev), __func__)); /* * First, check if we even need to load the firmware. * If the device was still attached when the system was * rebooted, it may already have firmware loaded in it. * If this is the case, we don't need to do it again. * And in fact, if we try to load it again, we'll hang, * so we have to avoid this condition if we don't want * to look stupid. * * We can test this quickly by checking the bcdRevision * code. The NIC will return a different revision code if * it's probed while the firmware is still loaded and * running. */ if (usbd_get_device_desc(sc->kue_udev, &dd)) return (EIO); if (UGETW(dd.bcdDevice) == KUE_WARM_REV) { printf("%s: warm boot, no firmware download\n", USBDEVNAME(sc->kue_dev)); return (0); } printf("%s: cold boot, downloading firmware\n", USBDEVNAME(sc->kue_dev)); /* Load code segment */ DPRINTFN(1,("%s: kue_load_fw: download code_seg\n", USBDEVNAME(sc->kue_dev))); /*XXXUNCONST*/ err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, __UNCONST(kue_code_seg), sizeof(kue_code_seg)); if (err) { printf("%s: failed to load code segment: %s\n", USBDEVNAME(sc->kue_dev), usbd_errstr(err)); return (EIO); } /* Load fixup segment */ DPRINTFN(1,("%s: kue_load_fw: download fix_seg\n", USBDEVNAME(sc->kue_dev))); /*XXXUNCONST*/ err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, __UNCONST(kue_fix_seg), sizeof(kue_fix_seg)); if (err) { printf("%s: failed to load fixup segment: %s\n", USBDEVNAME(sc->kue_dev), usbd_errstr(err)); return (EIO); } /* Send trigger command. */ DPRINTFN(1,("%s: kue_load_fw: download trig_seg\n", USBDEVNAME(sc->kue_dev))); /*XXXUNCONST*/ err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, __UNCONST(kue_trig_seg), sizeof(kue_trig_seg)); if (err) { printf("%s: failed to load trigger segment: %s\n", USBDEVNAME(sc->kue_dev), usbd_errstr(err)); return (EIO); } usbd_delay_ms(sc->kue_udev, 10); /* * Reload device descriptor. * Why? The chip without the firmware loaded returns * one revision code. The chip with the firmware * loaded and running returns a *different* revision * code. This confuses the quirk mechanism, which is * dependent on the revision data. */ (void)usbd_reload_device_desc(sc->kue_udev); DPRINTFN(1,("%s: %s: done\n", USBDEVNAME(sc->kue_dev), __func__)); /* Reset the adapter. */ kue_reset(sc); return (0); }
/* * Called when a new device has been put in the powered state, * but not yet in the addressed state. * Get initial descriptor, set the address, get full descriptor, * and attach a driver. */ usbd_status usbd_new_device(device_t parent, usbd_bus_handle bus, int depth, int speed, int port, struct usbd_port *up) { usbd_device_handle dev, adev; struct usbd_device *hub; usb_device_descriptor_t *dd; usb_port_status_t ps; usbd_status err; int addr; int i; int p; DPRINTF(("usbd_new_device bus=%p port=%d depth=%d speed=%d\n", bus, port, depth, speed)); addr = usbd_getnewaddr(bus); if (addr < 0) { kprintf("%s: No free USB addresses, new device ignored.\n", device_get_nameunit(bus->bdev)); return (USBD_NO_ADDR); } dev = kmalloc(sizeof *dev, M_USB, M_INTWAIT | M_ZERO); dev->bus = bus; /* Set up default endpoint handle. */ dev->def_ep.edesc = &dev->def_ep_desc; /* Set up default endpoint descriptor. */ dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE; dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT; dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT; dev->def_ep_desc.bmAttributes = UE_CONTROL; USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET); dev->def_ep_desc.bInterval = 0; dev->quirks = &usbd_no_quirk; dev->address = USB_START_ADDR; dev->ddesc.bMaxPacketSize = 0; dev->depth = depth; dev->powersrc = up; dev->myhub = up->parent; up->device = dev; /* Locate port on upstream high speed hub */ for (adev = dev, hub = up->parent; hub != NULL && hub->speed != USB_SPEED_HIGH; adev = hub, hub = hub->myhub) ; if (hub) { for (p = 0; p < hub->hub->hubdesc.bNbrPorts; p++) { if (hub->hub->ports[p].device == adev) { dev->myhsport = &hub->hub->ports[p]; goto found; } } panic("usbd_new_device: cannot find HS port\n"); found: DPRINTFN(1,("usbd_new_device: high speed port %d\n", p)); } else { dev->myhsport = NULL; } dev->speed = speed; dev->langid = USBD_NOLANG; dev->cookie.cookie = ++usb_cookie_no; /* Establish the default pipe. */ err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL, &dev->default_pipe); if (err) { usbd_remove_device(dev, up); return (err); } /* Set the address. Do this early; some devices need that. */ /* Try a few times in case the device is slow (i.e. outside specs.) */ DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr)); for (i = 0; i < 5; i++) { err = usbd_set_address(dev, addr); if (!err) break; usbd_delay_ms(dev, 200); if ((i & 3) == 3) { DPRINTFN(-1,("usb_new_device: set address %d " "failed - trying a port reset\n", addr)); usbd_reset_port(up->parent, port, &ps); } } if (err) { DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr)); err = USBD_SET_ADDR_FAILED; usbd_remove_device(dev, up); return (err); } /* Allow device time to set new address */ usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE); /* Kill the pipe */ usbd_kill_pipe(dev->default_pipe); dev->default_pipe = NULL; dev->address = addr; /* New device address now */ bus->devices[addr] = dev; /* Re-establish the default pipe. */ err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL, &dev->default_pipe); if (err) { usbd_remove_device(dev, up); return (err); } usbd_delay_ms(dev, 200); dd = &dev->ddesc; /* Get the first 8 bytes of the device descriptor. */ err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd); if (err) { DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc " "failed\n", addr)); usbd_remove_device(dev, up); return (err); } if (speed == USB_SPEED_HIGH) { /* Max packet size must be 64 (sec 5.5.3). */ if (dd->bMaxPacketSize != USB_2_MAX_CTRL_PACKET) { #ifdef DIAGNOSTIC kprintf("usbd_new_device: addr=%d bad max packet size\n", addr); #endif dd->bMaxPacketSize = USB_2_MAX_CTRL_PACKET; } } DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, " "subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n", addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass, dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength, dev->speed)); if (dd->bDescriptorType != UDESC_DEVICE) { /* Illegal device descriptor */ DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n", dd->bDescriptorType)); usbd_remove_device(dev, up); return (USBD_INVAL); } if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) { DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength)); usbd_remove_device(dev, up); return (USBD_INVAL); } USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize); err = usbd_reload_device_desc(dev); if (err) { DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc " "failed\n", addr)); usbd_remove_device(dev, up); return (err); } /* Assume 100mA bus powered for now. Changed when configured. */ dev->power = USB_MIN_POWER; dev->self_powered = 0; DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n", addr, dev, parent)); err = usbd_probe_and_attach(parent, dev, port, addr); if (err) { usbd_remove_device(dev, up); return (err); } usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev); return (USBD_NORMAL_COMPLETION); }