usbd_status usbd_reload_device_desc(struct usbd_device *dev) { USBHIST_FUNC(); USBHIST_CALLED(usbdebug); usb_device_descriptor_t *udd = &dev->ud_ddesc; usbd_status err; /* Get the full device descriptor. */ err = usbd_get_device_desc(dev, udd); if (err) return err; DPRINTFN(15, "bLength %5u", udd->bLength, 0, 0, 0); DPRINTFN(15, "bDescriptorType %5u", udd->bDescriptorType, 0, 0, 0); DPRINTFN(15, "bcdUSB %2x.%02x", udd->bcdUSB[1], udd->bcdUSB[0], 0, 0); DPRINTFN(15, "bDeviceClass %5u", udd->bDeviceClass, 0, 0, 0); DPRINTFN(15, "bDeviceSubClass %5u", udd->bDeviceSubClass, 0, 0, 0); DPRINTFN(15, "bDeviceProtocol %5u", udd->bDeviceProtocol, 0, 0, 0); DPRINTFN(15, "bMaxPacketSize0 %5u", udd->bMaxPacketSize, 0, 0, 0); DPRINTFN(15, "idVendor 0x%04x", udd->idVendor, 0, 0, 0); DPRINTFN(15, "idProduct 0x%04x", udd->idProduct, 0, 0, 0); DPRINTFN(15, "bcdDevice %2x.%02x", udd->bcdDevice[1], udd->bcdDevice[0], 0, 0); DPRINTFN(15, "iManufacturer %5u", udd->iManufacturer, 0, 0, 0); DPRINTFN(15, "iProduct %5u", udd->iProduct, 0, 0, 0); DPRINTFN(15, "iSerial %5u", udd->iSerialNumber, 0, 0, 0); DPRINTFN(15, "bNumConfigurations %5u", udd->bNumConfigurations, 0, 0, 0); /* Figure out what's wrong with this device. */ dev->ud_quirks = usbd_find_quirk(udd); return USBD_NORMAL_COMPLETION; }
static int u3g_huawei_reinit(usbd_device_handle dev) { /* * The Huawei device presents itself as a umass device with Windows * drivers on it. After installation of the driver, it reinits into a * 3G serial device. */ usb_device_request_t req; usb_config_descriptor_t *cdesc; /* Get the config descriptor */ cdesc = usbd_get_config_descriptor(dev); if (cdesc == NULL) { usb_device_descriptor_t dd; if (usbd_get_device_desc(dev, &dd) != 0) return (UMATCH_NONE); if (dd.bNumConfigurations != 1) return (UMATCH_NONE); if (usbd_set_config_index(dev, 0, 1) != 0) return (UMATCH_NONE); cdesc = usbd_get_config_descriptor(dev); if (cdesc == NULL) return (UMATCH_NONE); } /* * One iface means umass mode, more than 1 (4 usually) means 3G mode. * * XXX: We should check the first interface's device class just to be * sure. If it's a mass storage device, then we can be fairly certain * it needs a mode-switch. */ if (cdesc->bNumInterface > 1) return (UMATCH_NONE); req.bmRequestType = UT_WRITE_DEVICE; req.bRequest = UR_SET_FEATURE; USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); USETW(req.wIndex, UHF_PORT_SUSPEND); USETW(req.wLength, 0); (void) usbd_do_request(dev, &req, 0); return (UMATCH_HIGHEST); /* Prevent umass from attaching */ }
usbd_status usbd_reload_device_desc(usbd_device_handle dev) { usbd_status err; int i; /* Get the full device descriptor. */ for (i = 0; i < 3; ++i) { err = usbd_get_device_desc(dev, &dev->ddesc); if (!err) break; usbd_delay_ms(dev, 200); } if (err) return (err); /* Figure out what's wrong with this device. */ dev->quirks = usbd_find_quirk(&dev->ddesc); return (USBD_NORMAL_COMPLETION); }
int stuirda_fwload(struct uirda_softc *sc) { int rc; firmware_handle_t fh; off_t fwsize; usb_device_descriptor_t usbddsc; usbd_xfer_handle fwxfer; usbd_pipe_handle fwpipe; usbd_status status; usb_device_request_t req; char *buffer; char *p; char fwname[12]; int n; u_int8_t *usbbuf; /* size_t bsize; */ printf("%s: needing to download firmware\n", device_xname(sc->sc_dev)); status = usbd_get_device_desc(sc->sc_udev, &usbddsc); if (status) { printf("%s: can't get device descriptor, status %d\n", device_xname(sc->sc_dev), status); return status; } rc = usbd_get_class_desc(sc->sc_udev, UDESC_IRDA, 0, USB_IRDA_DESCRIPTOR_SIZE, &sc->sc_irdadesc); printf("error %d reading class desc\n", rc); snprintf(fwname, sizeof(fwname), "4210%02x%02x.sb", usbddsc.bcdDevice[1], usbddsc.bcdDevice[0]); printf("%s: Attempting to load firmware %s\n", device_xname(sc->sc_dev), fwname); rc = firmware_open("stuirda", fwname, &fh); if (rc) { printf("%s: Cannot load firmware\n", device_xname(sc->sc_dev)); return rc; } fwsize = firmware_get_size(fh); printf("%s: Firmware size %lld\n", device_xname(sc->sc_dev), (long long)fwsize); buffer = firmware_malloc(fwsize); if (buffer == NULL) { printf("%s: Cannot load firmware: out of memory\n", device_xname(sc->sc_dev)); goto giveup2; } rc = firmware_read(fh, 0, buffer, (size_t)fwsize); if (rc) { printf("%s: Cannot read firmware\n", device_xname(sc->sc_dev)); goto giveup3; } for (p = buffer + sizeof("Product Version:"); p < buffer + fwsize - 5; p++) { if (0x1A == *p) break; } if (0x1a != *p || memcmp(p+1, "STMP", 4) != 0) { /* firmware bad */ printf("%s: Bad firmware\n", device_xname(sc->sc_dev)); goto giveup3; } p += 5; req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = 2 /* XXX magic */; USETW(req.wValue, 0); USETW(req.wIndex, 0); USETW(req.wLength, 0); rc = usbd_do_request(sc->sc_udev, &req, 0); if (rc) { printf("%s: Cannot switch to f/w d/l mode, error %d\n", device_xname(sc->sc_dev), rc); goto giveup3; } delay(100000); rc = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &fwpipe); if (rc) { printf("%s: Cannot open pipe, rc=%d\n", device_xname(sc->sc_dev), rc); goto giveup3; } fwxfer = usbd_alloc_xfer(sc->sc_udev); if (fwxfer == NULL) { printf("%s: Cannot alloc xfer\n", device_xname(sc->sc_dev)); goto giveup4; } usbbuf = usbd_alloc_buffer(fwxfer, 1024); if (usbbuf == NULL) { printf("%s: Cannot alloc usb buf\n", device_xname(sc->sc_dev)); goto giveup5; } n = (buffer + fwsize - p); while (n > 0) { if (n > 1023) n = 1023; memcpy(usbbuf, p, n); rc = usbd_bulk_transfer(fwxfer, fwpipe, USBD_SYNCHRONOUS|USBD_FORCE_SHORT_XFER, 5000, usbbuf, &n, "uirda-fw-wr"); printf("%s: write: rc=%d, %d left\n", device_xname(sc->sc_dev), rc, n); if (rc) { printf("%s: write: rc=%d, %d bytes written\n", device_xname(sc->sc_dev), rc, n); goto giveup4; } printf("%s: written %d\n", device_xname(sc->sc_dev), n); p += n; n = (buffer + fwsize - p); } delay(100000); /* TODO: more code here */ rc = 0; usbd_free_buffer(fwxfer); giveup5: usbd_free_xfer(fwxfer); giveup4: usbd_close_pipe(fwpipe); giveup3: firmware_free(buffer, fwsize); giveup2: firmware_close(fh); return rc; }
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); }
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); }