usbd_status usbd_reset_port(usbd_device_handle dev, int port, usb_port_status_t *ps) { usb_device_request_t req; usbd_status err; int n; req.bmRequestType = UT_WRITE_CLASS_OTHER; req.bRequest = UR_SET_FEATURE; USETW(req.wValue, UHF_PORT_RESET); USETW(req.wIndex, port); USETW(req.wLength, 0); err = usbd_do_request(dev, &req, 0); DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n", port, usbd_errstr(err))); if (err) return (err); n = 10; do { /* Wait for device to recover from reset. */ usbd_delay_ms(dev, USB_PORT_RESET_DELAY); err = usbd_get_port_status(dev, port, ps); if (err) { DPRINTF(("usbd_reset_port: get status failed %d\n", err)); return (err); } /* If the device disappeared, just give up. */ if (!(UGETW(ps->wPortStatus) & UPS_CURRENT_CONNECT_STATUS)) return (USBD_NORMAL_COMPLETION); } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0); if (n == 0) return (USBD_TIMEOUT); err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET); #ifdef USB_DEBUG if (err) DPRINTF(("usbd_reset_port: clear port feature failed %d\n", err)); #endif /* Wait for the device to recover from reset. */ usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY); return (err); }
void emdtv_dtv_attach(struct emdtv_softc *sc) { usb_endpoint_descriptor_t *ed; usbd_status status; int i; for (i = 0; i < EMDTV_NXFERS; i++) { sc->sc_ix[i].ix_altix = (i & 1) ? &sc->sc_ix[i - 1] : &sc->sc_ix[i + 1]; sc->sc_ix[i].ix_sc = sc; } ed = usbd_interface2endpoint_descriptor(sc->sc_iface, 3); if (ed == NULL) { aprint_error_dev(sc->sc_dev, "couldn't find endpoint 3\n"); return; } sc->sc_isoc_maxpacketsize = UGETW(ed->wMaxPacketSize); sc->sc_isoc_buflen = sc->sc_isoc_maxpacketsize * EMDTV_NFRAMES; aprint_debug_dev(sc->sc_dev, "calling usbd_open_pipe, ep 0x%02x\n", ed->bEndpointAddress); status = usbd_open_pipe(sc->sc_iface, ed->bEndpointAddress, USBD_EXCLUSIVE_USE|USBD_MPSAFE, &sc->sc_isoc_pipe); if (status != USBD_NORMAL_COMPLETION) { aprint_error_dev(sc->sc_dev, "couldn't open isoc pipe\n"); usbd_set_interface(sc->sc_iface, 0); return; } emdtv_write_1(sc, UR_GET_STATUS, 0x48, 0x00); emdtv_write_1(sc, UR_GET_STATUS, 0x12, 0x77); usbd_delay_ms(sc->sc_udev, 6); emdtv_gpio_ctl(sc, EMDTV_GPIO_ANALOG_ON, false); emdtv_gpio_ctl(sc, EMDTV_GPIO_TS1_ON, true); emdtv_gpio_ctl(sc, EMDTV_GPIO_TUNER1_ON, true); emdtv_gpio_ctl(sc, EMDTV_GPIO_DEMOD1_RESET, true); usbd_delay_ms(sc->sc_udev, 100); emdtv_dtv_rescan(sc, NULL, NULL); }
int uoak_get_cmd(struct uoak_softc *sc) { sc->sc_rcmd.dir = OAK_GET; /* check the device is ready to request */ while (uoak_check_device_ready(sc) < 0) usbd_delay_ms(sc->sc_udev, UOAK_RETRY_DELAY); /* issue request */ if (uhidev_set_report(sc->sc_hdev, UHID_FEATURE_REPORT, &sc->sc_rcmd, sc->sc_flen)) return EIO; /* wait till the device ready to return the request */ while (uoak_check_device_ready(sc) < 0) usbd_delay_ms(sc->sc_udev, UOAK_RESPONSE_DELAY); return 0; }
/* * Issue a SET_CONFIGURATION command to reset the MAC. This should be * done after the firmware is loaded into the adapter in order to * bring it into proper operation. */ void kue_reset(struct kue_softc *sc) { DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__)); if (usbd_set_config_no(sc->kue_udev, KUE_CONFIG_NO, 1) || usbd_device2interface_handle(sc->kue_udev, KUE_IFACE_IDX, &sc->kue_iface)) printf("%s: reset failed\n", sc->kue_dev.dv_xname); /* Wait a little while for the chip to get its brains in order. */ usbd_delay_ms(sc->kue_udev, 10); }
int uoak_set_cmd(struct uoak_softc *sc) { sc->sc_rcmd.dir = OAK_SET; while (uoak_check_device_ready(sc) < 0) usbd_delay_ms(sc->sc_udev, UOAK_RETRY_DELAY); if (uhidev_set_report(sc->sc_hdev, UHID_FEATURE_REPORT, &sc->sc_rcmd, sc->sc_flen)) return EIO; return 0; }
usbd_status ezload_downloads_and_reset(usbd_device_handle dev, const struct ezdata **recs) { usbd_status err; /*(void)ezload_reset(dev, 1);*/ err = ezload_reset(dev, 1); if (err) return (err); usbd_delay_ms(dev, 250); while (*recs != NULL) { err = ezload_download(dev, *recs++); if (err) return (err); } if (err) return (err); usbd_delay_ms(dev, 250); /*(void)ezload_reset(dev, 0);*/ err = ezload_reset(dev, 0); usbd_delay_ms(dev, 250); return (err); }
void ueagle_stat_thread(void *arg) { struct ueagle_softc *sc = arg; for (;;) { if (ueagle_stat(sc) != 0) break; usbd_delay_ms(sc->sc_udev, 5000); if (usbd_is_dying(sc->sc_udev)) break; } wakeup(sc->stat_thread); kthread_exit(0); }
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); }
static int auvitek_stop_xfer(struct auvitek_softc *sc) { struct auvitek_xfer *ax = &sc->sc_ax; usbd_status err; int i; if (ax->ax_pipe != NULL) { usbd_abort_pipe(ax->ax_pipe); usbd_close_pipe(ax->ax_pipe); ax->ax_pipe = NULL; } for (i = 0; i < AUVITEK_NISOC_XFERS; i++) { struct auvitek_isoc *isoc = &ax->ax_i[i]; if (isoc->i_xfer != NULL) { usbd_free_buffer(isoc->i_xfer); usbd_free_xfer(isoc->i_xfer); isoc->i_xfer = NULL; } if (isoc->i_frlengths != NULL) { kmem_free(isoc->i_frlengths, sizeof(isoc->i_frlengths[0]) * ax->ax_nframes); isoc->i_frlengths = NULL; } } usbd_delay_ms(sc->sc_udev, 1000); err = usbd_set_interface(sc->sc_isoc_iface, 0); if (err != USBD_NORMAL_COMPLETION) { aprint_error_dev(sc->sc_dev, "couldn't set zero bw interface: %s\n", usbd_errstr(err)); return EIO; } return 0; }
static int uhub_attach(device_t self) { struct uhub_softc *sc = device_get_softc(self); struct usb_attach_arg *uaa = device_get_ivars(self); usbd_device_handle dev = uaa->device; usbd_status err; struct usbd_hub *hub = NULL; usb_device_request_t req; usb_hub_descriptor_t hubdesc; int p, port, nports, nremov, pwrdly; usbd_interface_handle iface; usb_endpoint_descriptor_t *ed; struct usbd_tt *tts = NULL; DPRINTFN(1,("uhub_attach\n")); sc->sc_hub = dev; if (dev->depth > 0 && UHUB_IS_HIGH_SPEED(sc)) { device_printf(self, "%s transaction translator%s\n", UHUB_IS_SINGLE_TT(sc) ? "single" : "multiple", UHUB_IS_SINGLE_TT(sc) ? "" : "s"); } err = usbd_set_config_index(dev, 0, 1); if (err) { DPRINTF(("%s: configuration failed, error=%s\n", device_get_nameunit(self), usbd_errstr(err))); return ENXIO; } if (dev->depth > USB_HUB_MAX_DEPTH) { device_printf(self, "hub depth (%d) exceeded, hub ignored\n", USB_HUB_MAX_DEPTH); return ENXIO; } /* Get hub descriptor. */ req.bmRequestType = UT_READ_CLASS_DEVICE; req.bRequest = UR_GET_DESCRIPTOR; USETW2(req.wValue, (dev->address > 1 ? UDESC_HUB : 0), 0); USETW(req.wIndex, 0); USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE); DPRINTFN(1,("usb_init_hub: getting hub descriptor\n")); err = usbd_do_request(dev, &req, &hubdesc); nports = hubdesc.bNbrPorts; if (!err && nports > 7) { USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8); err = usbd_do_request(dev, &req, &hubdesc); } if (err) { DPRINTF(("%s: getting hub descriptor failed, error=%s\n", device_get_nameunit(self), usbd_errstr(err))); return ENXIO; } for (nremov = 0, port = 1; port <= nports; port++) if (!UHD_NOT_REMOV(&hubdesc, port)) nremov++; device_printf(self, "%d port%s with %d removable, %s powered\n", nports, nports != 1 ? "s" : "", nremov, dev->self_powered ? "self" : "bus"); if (nports == 0) { device_printf(self, "no ports, hub ignored\n"); goto bad; } hub = kmalloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port), M_USBDEV, M_WAITOK); dev->hub = hub; dev->hub->hubdev = self; hub->explore = uhub_explore; hub->hubdesc = hubdesc; DPRINTFN(1,("usbhub_init_hub: selfpowered=%d, parent=%p, " "parent->selfpowered=%d\n", dev->self_powered, dev->powersrc->parent, dev->powersrc->parent ? dev->powersrc->parent->self_powered : 0)); if (!dev->self_powered && dev->powersrc->parent != NULL && !dev->powersrc->parent->self_powered) { device_printf(self, "bus powered hub connected to bus powered hub, " "ignored\n"); goto bad; } /* Set up interrupt pipe. */ err = usbd_device2interface_handle(dev, 0, &iface); if (err) { device_printf(self, "no interface handle\n"); goto bad; } ed = usbd_interface2endpoint_descriptor(iface, 0); if (ed == NULL) { device_printf(self, "no endpoint descriptor\n"); goto bad; } if ((ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { device_printf(self, "bad interrupt endpoint\n"); goto bad; } err = usbd_open_pipe_intr(iface, ed->bEndpointAddress, USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_status, sizeof(sc->sc_status), uhub_intr, UHUB_INTR_INTERVAL); if (err) { device_printf(self, "cannot open interrupt pipe\n"); goto bad; } /* Wait with power off for a while. */ usbd_delay_ms(dev, USB_POWER_DOWN_TIME); usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, self); /* * To have the best chance of success we do things in the exact same * order as Windoze98. This should not be necessary, but some * devices do not follow the USB specs to the letter. * * These are the events on the bus when a hub is attached: * Get device and config descriptors (see attach code) * Get hub descriptor (see above) * For all ports * turn on power * wait for power to become stable * (all below happens in explore code) * For all ports * clear C_PORT_CONNECTION * For all ports * get port status * if device connected * wait 100 ms * turn on reset * wait * clear C_PORT_RESET * get port status * proceed with device attachment */ if (UHUB_IS_HIGH_SPEED(sc)) { tts = kmalloc((UHUB_IS_SINGLE_TT(sc) ? 1 : nports) * sizeof(struct usbd_tt), M_USBDEV, M_WAITOK); } /* Set up data structures */ for (p = 0; p < nports; p++) { struct usbd_port *up = &hub->ports[p]; up->device = NULL; up->parent = dev; up->portno = p+1; if (dev->self_powered) /* Self powered hub, give ports maximum current. */ up->power = USB_MAX_POWER; else up->power = USB_MIN_POWER; up->restartcnt = 0; if (UHUB_IS_HIGH_SPEED(sc)) { up->tt = &tts[UHUB_IS_SINGLE_TT(sc) ? 0 : p]; up->tt->hub = hub; } else { up->tt = NULL; } } /* XXX should check for none, individual, or ganged power? */ pwrdly = dev->hub->hubdesc.bPwrOn2PwrGood * UHD_PWRON_FACTOR + USB_EXTRA_POWER_UP_TIME; for (port = 1; port <= nports; port++) { /* Turn the power on. */ err = usbd_set_port_feature(dev, port, UHF_PORT_POWER); if (err) device_printf(self, "port %d power on failed, %s\n", port, usbd_errstr(err)); DPRINTF(("usb_init_port: turn on port %d power\n", port)); } /* Wait for stable power if we are not a root hub */ if (dev->powersrc->parent != NULL) usbd_delay_ms(dev, pwrdly); /* The usual exploration will finish the setup. */ sc->sc_running = 1; return 0; bad: if (hub) kfree(hub, M_USBDEV); dev->hub = NULL; return ENXIO; }
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); }
int uhub_port_connect(struct uhub_softc *sc, int port, int status, int change) { struct usbd_port *up = &sc->sc_hub->hub->ports[port-1]; int speed; /* We have a connect status change, handle it. */ usbd_clear_port_feature(sc->sc_hub, port, UHF_C_PORT_CONNECTION); /* * If there is already a device on the port the change status * must mean that is has disconnected. Looking at the * current connect status is not enough to figure this out * since a new unit may have been connected before we handle * the disconnect. */ if (up->device != NULL) { /* Disconnected */ usbd_detach(up->device, &sc->sc_dev); up->device = NULL; } /* Nothing connected, just ignore it. */ if ((status & UPS_CURRENT_CONNECT_STATUS) == 0) return (0); /* Connected */ if ((status & (UPS_PORT_POWER|UPS_PORT_POWER_SS)) == 0) { printf("%s: connected port %d has no power\n", DEVNAME(sc), port); return (-1); } /* Wait for maximum device power up time. */ usbd_delay_ms(sc->sc_hub, USB_PORT_POWERUP_DELAY); /* Reset port, which implies enabling it. */ if (usbd_reset_port(sc->sc_hub, port)) { printf("%s: port %d reset failed\n", DEVNAME(sc), port); return (-1); } /* Get port status again, it might have changed during reset */ if (usbd_get_port_status(sc->sc_hub, port, &up->status)) return (-1); status = UGETW(up->status.wPortStatus); change = UGETW(up->status.wPortChange); DPRINTF("%s: port %d status=0x%04x change=0x%04x\n", DEVNAME(sc), port, status, change); /* Nothing connected, just ignore it. */ if ((status & UPS_CURRENT_CONNECT_STATUS) == 0) { DPRINTF("%s: port %d, device disappeared after reset\n", DEVNAME(sc), port); return (-1); } /* * Figure out device speed. This is a bit tricky because * UPS_PORT_POWER_SS and UPS_LOW_SPEED share the same bit. */ if ((status & UPS_PORT_POWER) == 0) status &= ~UPS_PORT_POWER_SS; if (status & UPS_HIGH_SPEED) speed = USB_SPEED_HIGH; else if (status & UPS_LOW_SPEED) speed = USB_SPEED_LOW; else { /* * If there is no power bit set, it is certainly * a Super Speed device, so use the speed of its * parent hub. */ if (status & UPS_PORT_POWER) speed = USB_SPEED_FULL; else speed = sc->sc_hub->speed; } /* * Reduce the speed, otherwise we won't setup the proper * transfer methods. */ if (speed > sc->sc_hub->speed) speed = sc->sc_hub->speed; /* Get device info and set its address. */ if (usbd_new_device(&sc->sc_dev, sc->sc_hub->bus, sc->sc_hub->depth + 1, speed, port, up)) { /* * The unit refused to accept a new address, or had * some other serious problem. Since we cannot leave * at 0 we have to disable the port instead. */ printf("%s: device problem, disabling port %d\n", DEVNAME(sc), port); usbd_clear_port_feature(sc->sc_hub, port, UHF_PORT_ENABLE); return (-1); } return (0); }
void uhub_attach(struct device *parent, struct device *self, void *aux) { struct uhub_softc *sc = (struct uhub_softc *)self; struct usb_attach_arg *uaa = aux; struct usbd_device *dev = uaa->device; struct usbd_hub *hub = NULL; union { usb_hub_descriptor_t hs; usb_hub_ss_descriptor_t ss; } hd; int p, port, nports, powerdelay; struct usbd_interface *iface; usb_endpoint_descriptor_t *ed; struct usbd_tt *tts = NULL; uint8_t ttthink = 0; usbd_status err; #ifdef UHUB_DEBUG int nremov; #endif sc->sc_hub = dev; err = usbd_set_config_index(dev, 0, 1); if (err) { DPRINTF("%s: configuration failed, error=%s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); return; } if (dev->depth > USB_HUB_MAX_DEPTH) { printf("%s: hub depth (%d) exceeded, hub ignored\n", sc->sc_dev.dv_xname, USB_HUB_MAX_DEPTH); return; } /* * Super-Speed hubs need to know their depth to be able to * parse the bits of the route-string that correspond to * their downstream port number. * * This does no apply to root hubs. */ if (dev->depth != 0 && dev->speed == USB_SPEED_SUPER) { if (usbd_set_hub_depth(dev, dev->depth - 1)) { printf("%s: unable to set HUB depth\n", sc->sc_dev.dv_xname); return; } } /* Get hub descriptor. */ if (dev->speed == USB_SPEED_SUPER) { err = usbd_get_hub_ss_descriptor(dev, &hd.ss, 1); nports = hd.ss.bNbrPorts; powerdelay = (hd.ss.bPwrOn2PwrGood * UHD_PWRON_FACTOR); if (!err && nports > 7) usbd_get_hub_ss_descriptor(dev, &hd.ss, nports); } else { err = usbd_get_hub_descriptor(dev, &hd.hs, 1); nports = hd.hs.bNbrPorts; powerdelay = (hd.hs.bPwrOn2PwrGood * UHD_PWRON_FACTOR); ttthink = UGETW(hd.hs.wHubCharacteristics) & UHD_TT_THINK; if (!err && nports > 7) usbd_get_hub_descriptor(dev, &hd.hs, nports); } if (err) { DPRINTF("%s: getting hub descriptor failed, error=%s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); return; } #ifdef UHUB_DEBUG for (nremov = 0, port = 1; port <= nports; port++) { if (dev->speed == USB_SPEED_SUPER) { if (!UHD_NOT_REMOV(&hd.ss, port)) nremov++; } else { if (!UHD_NOT_REMOV(&hd.hs, port)) nremov++; } } printf("%s: %d port%s with %d removable, %s powered", sc->sc_dev.dv_xname, nports, nports != 1 ? "s" : "", nremov, dev->self_powered ? "self" : "bus"); if (dev->depth > 0 && UHUB_IS_HIGH_SPEED(sc)) { printf(", %s transaction translator%s", UHUB_IS_SINGLE_TT(sc) ? "single" : "multiple", UHUB_IS_SINGLE_TT(sc) ? "" : "s"); } printf("\n"); #endif if (nports == 0) { printf("%s: no ports, hub ignored\n", sc->sc_dev.dv_xname); goto bad; } hub = malloc(sizeof(*hub), M_USBDEV, M_NOWAIT); if (hub == NULL) return; hub->ports = mallocarray(nports, sizeof(struct usbd_port), M_USBDEV, M_NOWAIT); if (hub->ports == NULL) { free(hub, M_USBDEV, 0); return; } dev->hub = hub; dev->hub->hubsoftc = sc; hub->explore = uhub_explore; hub->nports = nports; hub->powerdelay = powerdelay; hub->ttthink = ttthink >> 5; if (!dev->self_powered && dev->powersrc->parent != NULL && !dev->powersrc->parent->self_powered) { printf("%s: bus powered hub connected to bus powered hub, " "ignored\n", sc->sc_dev.dv_xname); goto bad; } /* Set up interrupt pipe. */ err = usbd_device2interface_handle(dev, 0, &iface); if (err) { printf("%s: no interface handle\n", sc->sc_dev.dv_xname); goto bad; } ed = usbd_interface2endpoint_descriptor(iface, 0); if (ed == NULL) { printf("%s: no endpoint descriptor\n", sc->sc_dev.dv_xname); goto bad; } if ((ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { printf("%s: bad interrupt endpoint\n", sc->sc_dev.dv_xname); goto bad; } sc->sc_statuslen = (nports + 1 + 7) / 8; sc->sc_statusbuf = malloc(sc->sc_statuslen, M_USBDEV, M_NOWAIT); if (!sc->sc_statusbuf) goto bad; err = usbd_open_pipe_intr(iface, ed->bEndpointAddress, USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_statusbuf, sc->sc_statuslen, uhub_intr, UHUB_INTR_INTERVAL); if (err) { printf("%s: cannot open interrupt pipe\n", sc->sc_dev.dv_xname); goto bad; } /* Wait with power off for a while. */ usbd_delay_ms(dev, USB_POWER_DOWN_TIME); /* * To have the best chance of success we do things in the exact same * order as Windoze98. This should not be necessary, but some * devices do not follow the USB specs to the letter. * * These are the events on the bus when a hub is attached: * Get device and config descriptors (see attach code) * Get hub descriptor (see above) * For all ports * turn on power * wait for power to become stable * (all below happens in explore code) * For all ports * clear C_PORT_CONNECTION * For all ports * get port status * if device connected * wait 100 ms * turn on reset * wait * clear C_PORT_RESET * get port status * proceed with device attachment */ if (UHUB_IS_HIGH_SPEED(sc)) { tts = mallocarray((UHUB_IS_SINGLE_TT(sc) ? 1 : nports), sizeof (struct usbd_tt), M_USBDEV, M_NOWAIT); if (!tts) goto bad; } /* Set up data structures */ for (p = 0; p < nports; p++) { struct usbd_port *up = &hub->ports[p]; up->device = NULL; up->parent = dev; up->portno = p + 1; if (dev->self_powered) /* Self powered hub, give ports maximum current. */ up->power = USB_MAX_POWER; else up->power = USB_MIN_POWER; up->restartcnt = 0; up->reattach = 0; if (UHUB_IS_HIGH_SPEED(sc)) { up->tt = &tts[UHUB_IS_SINGLE_TT(sc) ? 0 : p]; up->tt->hub = hub; } else { up->tt = NULL; } } for (port = 1; port <= nports; port++) { /* Turn the power on. */ err = usbd_set_port_feature(dev, port, UHF_PORT_POWER); if (err) printf("%s: port %d power on failed, %s\n", sc->sc_dev.dv_xname, port, usbd_errstr(err)); /* Make sure we check the port status at least once. */ sc->sc_status |= (1 << port); } /* Wait for stable power. */ if (dev->powersrc->parent != NULL) usbd_delay_ms(dev, powerdelay + USB_EXTRA_POWER_UP_TIME); /* The usual exploration will finish the setup. */ sc->sc_running = 1; return; bad: if (sc->sc_statusbuf) free(sc->sc_statusbuf, M_USBDEV, 0); if (hub) { if (hub->ports) free(hub->ports, M_USBDEV, 0); free(hub, M_USBDEV, 0); } dev->hub = NULL; }
/* **************************************************************** * Função de "attach" * **************************************************************** */ int uhub_attach (struct device *dev) { struct uhub_softc *sc; struct usb_attach_arg *uaa = dev->ivars; struct usbd_device *udev = uaa->device; struct usbd_hub *hub = NULL; struct usb_device_request req; struct usb_hub_descriptor *hubdesc = NULL; struct usbd_interface *iface; struct usb_endpoint_descriptor *ed; int p, port, nports, nremov, pwrdly, err; /* * Aloca e zera a estrutura "softc" */ if ((sc = dev->softc = malloc_byte (sizeof (struct uhub_softc))) == NULL) return (-1); memclr (sc, sizeof (struct uhub_softc)); #if (0) /*******************************************************/ { char *devinfo; if ((devinfo = malloc_byte (1024)) == NULL) goto bad; memclr (devinfo, 1024); usbd_devinfo (udev, USBD_SHOW_INTERFACE_CLASS, devinfo); device_set_desc_copy (dev, devinfo); free_byte (devinfo); } #endif /*******************************************************/ sc->sc_hub = udev; sc->sc_dev = dev; if (err = usbd_set_config_index (udev, 0, 1)) { printf ("uhub_attach (%s): erro na configuração (%s)\n", dev->nameunit, usbd_errstr (err)); goto bad; } if (udev->depth > USB_HUB_MAX_DEPTH) { printf ( "uhub_attach (%s): profundidade máxima excedida (%d > %d), \"hub\" ignorado\n", dev->nameunit, udev->depth, USB_HUB_MAX_DEPTH ); goto bad; } /* Get hub descriptor */ if ((hubdesc = malloc_byte (sizeof (struct usb_hub_descriptor))) == NULL) { err = USBD_NOMEM; goto bad; } req.bmRequestType = UT_READ_CLASS_DEVICE; req.bRequest = UR_GET_DESCRIPTOR; USETW2 (req.wValue, (udev->address > 1 ? UDESC_HUB : 0), 0); USETW (req.wIndex, 0); USETW (req.wLength, USB_HUB_DESCRIPTOR_SIZE); err = usbd_do_request (udev, &req, hubdesc); nports = hubdesc->bNbrPorts; if (err == 0 && nports > 7) { USETW (req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports + 1) / 8); err = usbd_do_request (udev, &req, hubdesc); } if (err) { printf ( "uhub_attach (%s): erro ao ler descritor do hub (%s)\n", dev->nameunit, usbd_errstr (err) ); goto bad; } for (nremov = 0, port = 1; port <= nports; port++) { if (!UHD_NOT_REMOV (hubdesc, port)) nremov++; } if (nports == 0) { printf ("%s: hub sem portas ignorado\n", dev->nameunit); goto bad; } printf ( "%s: %d porta%s, %d removíve%s, %s energizadas\n", dev->nameunit, nports, nports != 1 ? "s" : "", nremov, nremov != 1 ? "is" : "l", udev->self_powered ? "auto" : "bus" ); if ((hub = malloc_byte (sizeof (*hub) + (nports - 1) * sizeof (struct usbd_port))) == NULL) goto bad; memclr (hub, (sizeof (*hub) + (nports - 1) * sizeof (struct usbd_port))); udev->hub = hub; udev->hub->hubsoftc = sc; hub->explore = uhub_explore; hub->hubdesc = *hubdesc; free_byte (hubdesc); hubdesc = NULL; #ifdef USB_MSG printf ( "uhub_attach: selfpowered=%d, parent=%p, parent->selfpowered=%d\n", dev->self_powered, dev->powersrc->parent, dev->powersrc->parent ? dev->powersrc->parent->self_powered : 0 ); #endif USB_MSG if (!udev->self_powered && udev->powersrc->parent != NULL && !udev->powersrc->parent->self_powered) { printf ( "uhub_attach (%s): bus powered hub connected to bus powered hub, ignored\n", dev->nameunit ); goto bad; } /* Set up interrupt pipe */ if (usbd_device2interface_handle (udev, 0, &iface)) { printf ("uhub_attach (%s): no interface handle\n", dev->nameunit); goto bad; } if ((ed = usbd_interface2endpoint_descriptor (iface, 0)) == NULL) { printf ("uhub_attach (%s): no endpoint descriptor\n", dev->nameunit); goto bad; } if ((ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { printf ("uhub_attach (%s): bad interrupt endpoint\n", dev->nameunit); goto bad; } if ( usbd_open_pipe_intr ( iface, ed->bEndpointAddress, USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_status, sizeof (sc->sc_status), uhub_intr, UHUB_INTR_INTERVAL ) ) { printf ("uhub_attach (%s): cannot open interrupt pipe\n", dev->nameunit); goto bad; } /* Wait with power off for a while */ usbd_delay_ms (udev, USB_POWER_DOWN_TIME); /* * To have the best chance of success we do things in the exact same * order as Windoze98. This should not be necessary, but some * devices do not follow the USB specs to the letter. * * These are the events on the bus when a hub is attached: * Get device and config descriptors (see attach code) * Get hub descriptor (see above) * For all ports * turn on power * wait for power to become stable * (all below happens in explore code) * For all ports * clear C_PORT_CONNECTION * For all ports * get port status * if device connected * wait 100 ms * turn on reset * wait * clear C_PORT_RESET * get port status * proceed with device attachment */ /* Set up data structures */ for (p = 0; p < nports; p++) { struct usbd_port *up = &hub->ports[p]; up->device = NULL; up->parent = udev; up->portno = p+1; if (udev->self_powered) /* Self powered hub, give ports maximum current */ up->power = USB_MAX_POWER; else up->power = USB_MIN_POWER; up->restartcnt = 0; } /* XXX should check for none, individual, or ganged power? */ pwrdly = udev->hub->hubdesc.bPwrOn2PwrGood * UHD_PWRON_FACTOR + USB_EXTRA_POWER_UP_TIME; for (port = 1; port <= nports; port++) { /* Turn the power on */ if (err = usbd_set_port_feature (udev, port, UHF_PORT_POWER)) { printf ( "uhub_attach (%s): port %d power on failed, %s\n", dev->nameunit, port, usbd_errstr (err) ); } #ifdef USB_MSG printf ("uhub_attach: turn on port %d power\n", port); #endif USB_MSG /* Wait for stable power */ usbd_delay_ms (udev, pwrdly); } /* The usual exploration will finish the setup */ sc->sc_running = 1; return (0); /* * Em caso de erro, ... */ bad: if (hubdesc != NULL) free_byte (hubdesc); if (hub != NULL) free_byte (hub); udev->hub = NULL; free_byte (sc); dev->softc = NULL; return (-1); } /* end uhub_attach */
/* * 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; }
usbd_status usbd_set_config_index(usbd_device_handle dev, int index, int msg) { usb_status_t ds; usb_config_descriptor_t cd, *cdp; usbd_status err; int i, ifcidx, nifc, len, selfpowered, power; DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index)); if (dev->config != USB_UNCONFIG_NO) { nifc = dev->cdesc->bNumInterface; /* Check that all interfaces are idle */ for (ifcidx = 0; ifcidx < nifc; ifcidx++) { if (LIST_EMPTY(&dev->ifaces[ifcidx].pipes)) continue; DPRINTF(("usbd_set_config_index: open pipes exist\n")); return (USBD_IN_USE); } DPRINTF(("usbd_set_config_index: free old config\n")); /* Free all configuration data structures. */ for (ifcidx = 0; ifcidx < nifc; ifcidx++) usbd_free_iface_data(dev, ifcidx); kfree(dev->ifaces, M_USB); kfree(dev->cdesc, M_USB); dev->ifaces = NULL; dev->cdesc = NULL; dev->config = USB_UNCONFIG_NO; } if (index == USB_UNCONFIG_INDEX) { /* We are unconfiguring the device, so leave unallocated. */ DPRINTF(("usbd_set_config_index: set config 0\n")); err = usbd_set_config(dev, USB_UNCONFIG_NO); if (err) DPRINTF(("usbd_set_config_index: setting config=0 " "failed, error=%s\n", usbd_errstr(err))); return (err); } /* Get the short descriptor. */ err = usbd_get_config_desc(dev, index, &cd); if (err) return (err); len = UGETW(cd.wTotalLength); cdp = kmalloc(len, M_USB, M_INTWAIT); /* Get the full descriptor. Try a few times for slow devices. */ for (i = 0; i < 3; i++) { err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp); if (!err) break; usbd_delay_ms(dev, 200); } if (err) goto bad; if (cdp->bDescriptorType != UDESC_CONFIG) { DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n", cdp->bDescriptorType)); err = USBD_INVAL; goto bad; } /* Figure out if the device is self or bus powered. */ selfpowered = 0; if (!(dev->quirks->uq_flags & UQ_BUS_POWERED) && (cdp->bmAttributes & UC_SELF_POWERED)) { /* May be self powered. */ if (cdp->bmAttributes & UC_BUS_POWERED) { /* Must ask device. */ if (dev->quirks->uq_flags & UQ_POWER_CLAIM) { /* * Hub claims to be self powered, but isn't. * It seems that the power status can be * determined by the hub characteristics. */ usb_hub_descriptor_t hd; usb_device_request_t req; req.bmRequestType = UT_READ_CLASS_DEVICE; req.bRequest = UR_GET_DESCRIPTOR; USETW(req.wValue, 0); USETW(req.wIndex, 0); USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE); err = usbd_do_request(dev, &req, &hd); if (!err && (UGETW(hd.wHubCharacteristics) & UHD_PWR_INDIVIDUAL)) selfpowered = 1; DPRINTF(("usbd_set_config_index: charac=0x%04x" ", error=%s\n", UGETW(hd.wHubCharacteristics), usbd_errstr(err))); } else { err = usbd_get_device_status(dev, &ds); if (!err && (UGETW(ds.wStatus) & UDS_SELF_POWERED)) selfpowered = 1; DPRINTF(("usbd_set_config_index: status=0x%04x" ", error=%s\n", UGETW(ds.wStatus), usbd_errstr(err))); } } else selfpowered = 1; } DPRINTF(("usbd_set_config_index: (addr %d) cno=%d attr=0x%02x, " "selfpowered=%d, power=%d\n", cdp->bConfigurationValue, dev->address, cdp->bmAttributes, selfpowered, cdp->bMaxPower * 2)); /* Check if we have enough power. */ #ifdef USB_DEBUG if (dev->powersrc == NULL) { DPRINTF(("usbd_set_config_index: No power source?\n")); return (USBD_IOERROR); } #endif power = cdp->bMaxPower * 2; if (power > dev->powersrc->power) { DPRINTF(("power exceeded %d %d\n", power,dev->powersrc->power)); /* XXX print nicer message. */ if (msg) kprintf("%s: device addr %d (config %d) exceeds power " "budget, %d mA > %d mA\n", device_get_nameunit(dev->bus->bdev), dev->address, cdp->bConfigurationValue, power, dev->powersrc->power); err = USBD_NO_POWER; goto bad; } dev->power = power; dev->self_powered = selfpowered; /* Set the actual configuration value. */ DPRINTF(("usbd_set_config_index: set config %d\n", cdp->bConfigurationValue)); err = usbd_set_config(dev, cdp->bConfigurationValue); if (err) { DPRINTF(("usbd_set_config_index: setting config=%d failed, " "error=%s\n", cdp->bConfigurationValue, usbd_errstr(err))); goto bad; } /* Allocate and fill interface data. */ nifc = cdp->bNumInterface; dev->ifaces = kmalloc(nifc * sizeof(struct usbd_interface), M_USB, M_INTWAIT); DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp)); dev->cdesc = cdp; dev->config = cdp->bConfigurationValue; for (ifcidx = 0; ifcidx < nifc; ifcidx++) { err = usbd_fill_iface_data(dev, ifcidx, 0); if (err) { while (--ifcidx >= 0) usbd_free_iface_data(dev, ifcidx); goto bad; } } return (USBD_NORMAL_COMPLETION); bad: kfree(cdp, M_USB); return (err); }
void ukbd_attach(struct device *parent, struct device *self, void *aux) { struct ukbd_softc *sc = (struct ukbd_softc *)self; struct hidkbd *kbd = &sc->sc_kbd; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; struct usb_hid_descriptor *hid; u_int32_t qflags; int dlen, repid; void *desc; kbd_t layout = (kbd_t)-1; sc->sc_hdev.sc_intr = ukbd_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_udev = uha->uaa->device; sc->sc_hdev.sc_report_id = uha->reportid; uhidev_get_report_desc(uha->parent, &desc, &dlen); repid = uha->reportid; sc->sc_hdev.sc_isize = hid_report_size(desc, dlen, hid_input, repid); sc->sc_hdev.sc_osize = hid_report_size(desc, dlen, hid_output, repid); sc->sc_hdev.sc_fsize = hid_report_size(desc, dlen, hid_feature, repid); qflags = usbd_get_quirks(sc->sc_hdev.sc_udev)->uq_flags; if (hidkbd_attach(self, kbd, 1, qflags, repid, desc, dlen) != 0) return; if (uha->uaa->vendor == USB_VENDOR_APPLE) { int iso = 0; if ((uha->uaa->product == USB_PRODUCT_APPLE_FOUNTAIN_ISO) || (uha->uaa->product == USB_PRODUCT_APPLE_GEYSER_ISO)) iso = 1; if (hid_locate(desc, dlen, HID_USAGE2(HUP_APPLE, HUG_FN_KEY), uha->reportid, hid_input, &sc->sc_apple_fn, &qflags)) { if (qflags & HIO_VARIABLE) { if (iso) sc->sc_munge = ukbd_apple_iso_munge; else sc->sc_munge = ukbd_apple_munge; } } } if (uha->uaa->vendor == USB_VENDOR_TOPRE && uha->uaa->product == USB_PRODUCT_TOPRE_HHKB) { /* ignore country code on purpose */ } else { hid = usbd_get_hid_descriptor(uha->uaa->iface); if (hid->bCountryCode <= HCC_MAX) layout = ukbd_countrylayout[hid->bCountryCode]; #ifdef DIAGNOSTIC if (hid->bCountryCode != 0) printf(", country code %d", hid->bCountryCode); #endif } if (layout == (kbd_t)-1) { #ifdef UKBD_LAYOUT layout = UKBD_LAYOUT; #else layout = KB_US | KB_DEFAULT; #endif } printf("\n"); #ifdef __loongson__ if (uha->uaa->vendor == USB_VENDOR_CYPRESS && uha->uaa->product == USB_PRODUCT_CYPRESS_LPRDK) sc->sc_munge = ukbd_gdium_munge; #endif if (kbd->sc_console_keyboard) { extern struct wskbd_mapdata ukbd_keymapdata; DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc)); ukbd_keymapdata.layout = layout; wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata); ukbd_enable(sc, 1); } /* Flash the leds; no real purpose, just shows we're alive. */ ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS | WSKBD_LED_COMPOSE); usbd_delay_ms(sc->sc_hdev.sc_udev, 400); ukbd_set_leds(sc, 0); hidkbd_attach_wskbd(kbd, layout, &ukbd_accessops); }
usbd_status uhub_explore(usbd_device_handle dev) { usb_hub_descriptor_t *hd = &dev->hub->hubdesc; device_t self = dev->hub->hubdev; struct uhub_softc *sc = device_get_softc(self); struct usbd_port *up; usbd_status err; int speed; int port; int change, status; DPRINTFN(10, ("uhub_explore dev=%p addr=%d\n", dev, dev->address)); if (!sc->sc_running) return (USBD_NOT_STARTED); /* Ignore hubs that are too deep. */ if (dev->depth > USB_HUB_MAX_DEPTH) return (USBD_TOO_DEEP); for(port = 1; port <= hd->bNbrPorts; port++) { up = &dev->hub->ports[port-1]; err = usbd_get_port_status(dev, port, &up->status); if (err) { DPRINTF(("uhub_explore: get port status failed, " "error=%s\n", usbd_errstr(err))); continue; } status = UGETW(up->status.wPortStatus); change = UGETW(up->status.wPortChange); DPRINTFN(3,("uhub_explore: %s port %d status 0x%04x 0x%04x\n", device_get_nameunit(self), port, status, change)); if (change & UPS_C_PORT_ENABLED) { DPRINTF(("uhub_explore: C_PORT_ENABLED 0x%x\n", change)); usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE); if (change & UPS_C_CONNECT_STATUS) { /* Ignore the port error if the device vanished. */ } else if (status & UPS_PORT_ENABLED) { device_printf(self, "illegal enable change, port %d\n", port); } else { /* Port error condition. */ if (up->restartcnt) /* no message first time */ device_printf(self, "port error, restarting " "port %d\n", port); if (up->restartcnt++ < USBD_RESTART_MAX) goto disco; else device_printf(self, "port error, giving up " "port %d\n", port); } } if (!(change & UPS_C_CONNECT_STATUS)) { DPRINTFN(3,("uhub_explore: port=%d !C_CONNECT_" "STATUS\n", port)); /* No status change, just do recursive explore. */ if (up->device != NULL && up->device->hub != NULL) up->device->hub->explore(up->device); #if 0 && defined(DIAGNOSTIC) if (up->device == NULL && (status & UPS_CURRENT_CONNECT_STATUS)) device_printf(self, "connected, no device\n"); #endif continue; } /* We have a connect status change, handle it. */ DPRINTF(("uhub_explore: status change hub=%d port=%d\n", dev->address, port)); usbd_clear_port_feature(dev, port, UHF_C_PORT_CONNECTION); /*usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE);*/ /* * If there is already a device on the port the change status * must mean that is has disconnected. Looking at the * current connect status is not enough to figure this out * since a new unit may have been connected before we handle * the disconnect. */ disco: if (up->device != NULL) { /* Disconnected */ DPRINTF(("uhub_explore: device addr=%d disappeared " "on port %d\n", up->device->address, port)); usb_disconnect_port(up, self); usbd_clear_port_feature(dev, port, UHF_C_PORT_CONNECTION); } if (!(status & UPS_CURRENT_CONNECT_STATUS)) { /* Nothing connected, just ignore it. */ DPRINTFN(3,("uhub_explore: port=%d !CURRENT_CONNECT" "_STATUS\n", port)); continue; } /* Connected */ if (!(status & UPS_PORT_POWER)) device_printf(self, "strange, connected port %d has no power\n", port); /* Wait for maximum device power up time. */ usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY); /* Reset port, which implies enabling it. */ if (usbd_reset_port(dev, port, &up->status)) { device_printf(self, "port %d reset failed\n", port); continue; } /* Get port status again, it might have changed during reset */ err = usbd_get_port_status(dev, port, &up->status); if (err) { DPRINTF(("uhub_explore: get port status failed, " "error=%s\n", usbd_errstr(err))); continue; } status = UGETW(up->status.wPortStatus); change = UGETW(up->status.wPortChange); if (!(status & UPS_CURRENT_CONNECT_STATUS)) { /* Nothing connected, just ignore it. */ #ifdef DIAGNOSTIC device_printf(self, "port %d, device disappeared after reset\n", port); #endif continue; } #if 0 if (UHUB_IS_HIGH_SPEED(sc) && !(status & UPS_HIGH_SPEED)) { device_printf(self, "port %d, transaction translation not " "implemented, low/full speed device ignored\n", port); continue; } #endif /* Figure out device speed */ if (status & UPS_HIGH_SPEED) speed = USB_SPEED_HIGH; else if (status & UPS_LOW_SPEED) speed = USB_SPEED_LOW; else speed = USB_SPEED_FULL; /* Get device info and set its address. */ err = usbd_new_device(self, dev->bus, dev->depth + 1, speed, port, up); /* XXX retry a few times? */ if (err) { DPRINTFN(-1,("uhub_explore: usb_new_device failed, " "error=%s\n", usbd_errstr(err))); /* Avoid addressing problems by disabling. */ /* usbd_reset_port(dev, port, &up->status); */ /* * The unit refused to accept a new address, or had * some other serious problem. Since we cannot leave * at 0 we have to disable the port instead. */ device_printf(self, "device problem (%s), disabling port %d\n", usbd_errstr(err), port); usbd_clear_port_feature(dev, port, UHF_PORT_ENABLE); } else { /* The port set up succeeded, reset error count. */ up->restartcnt = 0; if (up->device->hub) up->device->hub->explore(up->device); } } return (USBD_NORMAL_COMPLETION); }
void ukbd_attach(device_t parent, device_t self, void *aux) { struct ukbd_softc *sc = device_private(self); struct uhidev_attach_arg *uha = aux; u_int32_t qflags; const char *parseerr; #if defined(__NetBSD__) struct wskbddev_attach_args a; #else int i; #endif sc->sc_hdev.sc_dev = self; sc->sc_hdev.sc_intr = ukbd_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_report_id = uha->reportid; if (!pmf_device_register(self, NULL, NULL)) { aprint_normal("\n"); aprint_error_dev(self, "couldn't establish power handler\n"); } parseerr = ukbd_parse_desc(sc); if (parseerr != NULL) { aprint_normal("\n"); aprint_error_dev(self, "attach failed, %s\n", parseerr); USB_ATTACH_ERROR_RETURN; } #ifdef DIAGNOSTIC aprint_normal(": %d modifier keys, %d key codes", sc->sc_nmod, sc->sc_nkeycode); #endif aprint_normal("\n"); qflags = usbd_get_quirks(uha->parent->sc_udev)->uq_flags; sc->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0; /* * Remember if we're the console keyboard. * * XXX This always picks the first keyboard on the * first USB bus, but what else can we really do? */ if ((sc->sc_console_keyboard = ukbd_is_console) != 0) { /* Don't let any other keyboard have it. */ ukbd_is_console = 0; } if (sc->sc_console_keyboard) { DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc)); wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata); ukbd_enable(sc, 1); } a.console = sc->sc_console_keyboard; a.keymap = &ukbd_keymapdata; a.accessops = &ukbd_accessops; a.accesscookie = sc; #ifdef UKBD_REPEAT usb_callout_init(sc->sc_rawrepeat_ch); #endif usb_callout_init(sc->sc_delay); /* Flash the leds; no real purpose, just shows we're alive. */ ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS); usbd_delay_ms(uha->parent->sc_udev, 400); ukbd_set_leds(sc, 0); sc->sc_wskbddev = config_found(self, &a, wskbddevprint); USB_ATTACH_SUCCESS_RETURN; }
usbd_status usbd_set_config_index(struct usbd_device *dev, int index, int msg) { USBHIST_FUNC(); USBHIST_CALLED(usbdebug); usb_config_descriptor_t cd, *cdp; usb_bos_descriptor_t *bdp = NULL; usbd_status err; int i, ifcidx, nifc, len, selfpowered, power; DPRINTFN(5, "dev=%p index=%d", dev, index, 0, 0); if (index >= dev->ud_ddesc.bNumConfigurations && index != USB_UNCONFIG_INDEX) { /* panic? */ printf("usbd_set_config_index: illegal index\n"); return USBD_INVAL; } /* XXX check that all interfaces are idle */ if (dev->ud_config != USB_UNCONFIG_NO) { DPRINTF("free old config", 0, 0, 0, 0); /* Free all configuration data structures. */ nifc = dev->ud_cdesc->bNumInterface; for (ifcidx = 0; ifcidx < nifc; ifcidx++) usbd_free_iface_data(dev, ifcidx); kmem_free(dev->ud_ifaces, nifc * sizeof(struct usbd_interface)); kmem_free(dev->ud_cdesc, UGETW(dev->ud_cdesc->wTotalLength)); if (dev->ud_bdesc != NULL) kmem_free(dev->ud_bdesc, UGETW(dev->ud_bdesc->wTotalLength)); dev->ud_ifaces = NULL; dev->ud_cdesc = NULL; dev->ud_bdesc = NULL; dev->ud_config = USB_UNCONFIG_NO; } if (index == USB_UNCONFIG_INDEX) { /* We are unconfiguring the device, so leave unallocated. */ DPRINTF("set config 0", 0, 0, 0, 0); err = usbd_set_config(dev, USB_UNCONFIG_NO); if (err) { DPRINTF("setting config=0 failed, err = %d", err, 0, 0, 0); } return err; } /* Get the short descriptor. */ err = usbd_get_config_desc(dev, index, &cd); if (err) { DPRINTF("get_config_desc=%d", err, 0, 0, 0); return err; } len = UGETW(cd.wTotalLength); cdp = kmem_alloc(len, KM_SLEEP); if (cdp == NULL) return USBD_NOMEM; /* Get the full descriptor. Try a few times for slow devices. */ for (i = 0; i < 3; i++) { err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp); if (!err) break; usbd_delay_ms(dev, 200); } if (err) { DPRINTF("get_desc=%d", err, 0, 0, 0); goto bad; } if (cdp->bDescriptorType != UDESC_CONFIG) { DPRINTF("bad desc %d", cdp->bDescriptorType, 0, 0, 0); err = USBD_INVAL; goto bad; } if (USB_IS_SS(dev->ud_speed)) { usb_bos_descriptor_t bd; /* get short bos desc */ err = usbd_get_bos_desc(dev, index, &bd); if (!err) { int blen = UGETW(bd.wTotalLength); bdp = kmem_alloc(blen, KM_SLEEP); if (bdp == NULL) { err = USBD_NOMEM; goto bad; } /* Get the full desc */ for (i = 0; i < 3; i++) { err = usbd_get_desc(dev, UDESC_BOS, index, blen, bdp); if (!err) break; usbd_delay_ms(dev, 200); } if (err || bdp->bDescriptorType != UDESC_BOS) { DPRINTF("error %d or bad desc %d", err, bdp->bDescriptorType, 0, 0); kmem_free(bdp, blen); bdp = NULL; } } } dev->ud_bdesc = bdp; /* * Figure out if the device is self or bus powered. */ #if 0 /* XXX various devices don't report the power state correctly */ selfpowered = 0; err = usbd_get_device_status(dev, &ds); if (!err && (UGETW(ds.wStatus) & UDS_SELF_POWERED)) selfpowered = 1; #endif /* * Use the power state in the configuration we are going * to set. This doesn't necessarily reflect the actual * power state of the device; the driver can control this * by choosing the appropriate configuration. */ selfpowered = !!(cdp->bmAttributes & UC_SELF_POWERED); DPRINTF("addr %d cno=%d attr=0x%02x, selfpowered=%d", dev->ud_addr, cdp->bConfigurationValue, cdp->bmAttributes, selfpowered); DPRINTF("max power=%d", cdp->bMaxPower * 2, 0, 0, 0); /* Check if we have enough power. */ #if 0 /* this is a no-op, see above */ if ((cdp->bmAttributes & UC_SELF_POWERED) && !selfpowered) { if (msg) printf("%s: device addr %d (config %d): " "can't set self powered configuration\n", device_xname(dev->ud_bus->bdev), dev->ud_addr, cdp->bConfigurationValue); err = USBD_NO_POWER; goto bad; } #endif #ifdef USB_DEBUG if (dev->ud_powersrc == NULL) { DPRINTF("No power source?", 0, 0, 0, 0); err = USBD_IOERROR; goto bad; } #endif power = cdp->bMaxPower * 2; if (power > dev->ud_powersrc->up_power) { DPRINTF("power exceeded %d %d", power, dev->ud_powersrc->up_power, 0, 0); /* XXX print nicer message. */ if (msg) printf("%s: device addr %d (config %d) exceeds power " "budget, %d mA > %d mA\n", device_xname(dev->ud_bus->ub_usbctl), dev->ud_addr, cdp->bConfigurationValue, power, dev->ud_powersrc->up_power); err = USBD_NO_POWER; goto bad; } dev->ud_power = power; dev->ud_selfpowered = selfpowered; /* Set the actual configuration value. */ DPRINTF("set config %d", cdp->bConfigurationValue, 0, 0, 0); err = usbd_set_config(dev, cdp->bConfigurationValue); if (err) { DPRINTF("setting config=%d failed, error=%d", cdp->bConfigurationValue, err, 0, 0); goto bad; } /* Allocate and fill interface data. */ nifc = cdp->bNumInterface; dev->ud_ifaces = kmem_alloc(nifc * sizeof(struct usbd_interface), KM_SLEEP); if (dev->ud_ifaces == NULL) { err = USBD_NOMEM; goto bad; } DPRINTFN(5, "dev=%p cdesc=%p", dev, cdp, 0, 0); dev->ud_cdesc = cdp; dev->ud_config = cdp->bConfigurationValue; for (ifcidx = 0; ifcidx < nifc; ifcidx++) { err = usbd_fill_iface_data(dev, ifcidx, 0); if (err) { while (--ifcidx >= 0) usbd_free_iface_data(dev, ifcidx); goto bad; } } return USBD_NORMAL_COMPLETION; bad: kmem_free(cdp, len); if (bdp != NULL) { kmem_free(bdp, UGETW(bdp->wTotalLength)); dev->ud_bdesc = NULL; } return err; }
/* * 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); }
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); }
int smsc_chip_init(struct smsc_softc *sc) { int err; uint32_t reg_val; int burst_cap; /* Enter H/W config mode */ smsc_write_reg(sc, SMSC_HW_CFG, SMSC_HW_CFG_LRST); if ((err = smsc_wait_for_bits(sc, SMSC_HW_CFG, SMSC_HW_CFG_LRST)) != 0) { smsc_warn_printf(sc, "timed-out waiting for reset to " "complete\n"); goto init_failed; } /* Reset the PHY */ smsc_write_reg(sc, SMSC_PM_CTRL, SMSC_PM_CTRL_PHY_RST); if ((err = smsc_wait_for_bits(sc, SMSC_PM_CTRL, SMSC_PM_CTRL_PHY_RST) != 0)) { smsc_warn_printf(sc, "timed-out waiting for phy reset to " "complete\n"); goto init_failed; } usbd_delay_ms(sc->sc_udev, 40); /* Set the mac address */ if ((err = smsc_setmacaddress(sc, sc->sc_ac.ac_enaddr)) != 0) { smsc_warn_printf(sc, "failed to set the MAC address\n"); goto init_failed; } /* * Don't know what the HW_CFG_BIR bit is, but following the reset * sequence as used in the Linux driver. */ if ((err = smsc_read_reg(sc, SMSC_HW_CFG, ®_val)) != 0) { smsc_warn_printf(sc, "failed to read HW_CFG: %d\n", err); goto init_failed; } reg_val |= SMSC_HW_CFG_BIR; smsc_write_reg(sc, SMSC_HW_CFG, reg_val); /* * There is a so called 'turbo mode' that the linux driver supports, it * seems to allow you to jam multiple frames per Rx transaction. * By default this driver supports that and therefore allows multiple * frames per URB. * * The xfer buffer size needs to reflect this as well, therefore based * on the calculations in the Linux driver the RX bufsize is set to * 18944, * bufsz = (16 * 1024 + 5 * 512) * * Burst capability is the number of URBs that can be in a burst of * data/ethernet frames. */ #ifdef SMSC_TURBO if (sc->sc_udev->speed == USB_SPEED_HIGH) burst_cap = 37; else burst_cap = 128; #else burst_cap = 0; #endif smsc_write_reg(sc, SMSC_BURST_CAP, burst_cap); /* Set the default bulk in delay (magic value from Linux driver) */ smsc_write_reg(sc, SMSC_BULK_IN_DLY, 0x00002000); /* * Initialise the RX interface */ if ((err = smsc_read_reg(sc, SMSC_HW_CFG, ®_val)) < 0) { smsc_warn_printf(sc, "failed to read HW_CFG: (err = %d)\n", err); goto init_failed; } /* * The following setings are used for 'turbo mode', a.k.a multiple * frames per Rx transaction (again info taken form Linux driver). */ #ifdef SMSC_TURBO reg_val |= (SMSC_HW_CFG_MEF | SMSC_HW_CFG_BCE); #endif smsc_write_reg(sc, SMSC_HW_CFG, reg_val); /* Clear the status register ? */ smsc_write_reg(sc, SMSC_INTR_STATUS, 0xffffffff); /* Read and display the revision register */ if ((err = smsc_read_reg(sc, SMSC_ID_REV, &sc->sc_rev_id)) < 0) { smsc_warn_printf(sc, "failed to read ID_REV (err = %d)\n", err); goto init_failed; } /* GPIO/LED setup */ reg_val = SMSC_LED_GPIO_CFG_SPD_LED | SMSC_LED_GPIO_CFG_LNK_LED | SMSC_LED_GPIO_CFG_FDX_LED; smsc_write_reg(sc, SMSC_LED_GPIO_CFG, reg_val); /* * Initialise the TX interface */ smsc_write_reg(sc, SMSC_FLOW, 0); smsc_write_reg(sc, SMSC_AFC_CFG, AFC_CFG_DEFAULT); /* Read the current MAC configuration */ if ((err = smsc_read_reg(sc, SMSC_MAC_CSR, &sc->sc_mac_csr)) < 0) { smsc_warn_printf(sc, "failed to read MAC_CSR (err=%d)\n", err); goto init_failed; } /* Vlan */ smsc_write_reg(sc, SMSC_VLAN1, (uint32_t)ETHERTYPE_VLAN); /* * Start TX */ sc->sc_mac_csr |= SMSC_MAC_CSR_TXEN; smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr); smsc_write_reg(sc, SMSC_TX_CFG, SMSC_TX_CFG_ON); /* * Start RX */ sc->sc_mac_csr |= SMSC_MAC_CSR_RXEN; smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr); return (0); init_failed: smsc_err_printf(sc, "smsc_chip_init failed (err=%d)\n", err); return (err); }
void ukbd_attach(struct device *parent, struct device *self, void *aux) { struct ukbd_softc *sc = (struct ukbd_softc *)self; struct usb_attach_arg *uaa = aux; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; usb_hid_descriptor_t *hid; u_int32_t qflags; const char *parseerr; kbd_t layout = (kbd_t)-1; struct wskbddev_attach_args a; sc->sc_hdev.sc_intr = ukbd_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_report_id = uha->reportid; parseerr = ukbd_parse_desc(sc); if (parseerr != NULL) { printf("\n%s: attach failed, %s\n", sc->sc_hdev.sc_dev.dv_xname, parseerr); return; } hid = usbd_get_hid_descriptor(uha->uaa->iface); #ifdef DIAGNOSTIC printf(": %d modifier keys, %d key codes", sc->sc_nmod, sc->sc_nkeycode); #endif qflags = usbd_get_quirks(uha->parent->sc_udev)->uq_flags; sc->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0; /* * Remember if we're the console keyboard. * * XXX This always picks the first keyboard on the * first USB bus, but what else can we really do? */ if ((sc->sc_console_keyboard = ukbd_is_console) != 0) { /* Don't let any other keyboard have it. */ ukbd_is_console = 0; } if (uha->uaa->vendor == USB_VENDOR_TOPRE && uha->uaa->product == USB_PRODUCT_TOPRE_HHKB) { /* ignore country code on purpose */ } else { if (hid->bCountryCode <= HCC_MAX) layout = ukbd_countrylayout[hid->bCountryCode]; #ifdef DIAGNOSTIC if (hid->bCountryCode != 0) printf(", country code %d", hid->bCountryCode); #endif } if (layout == (kbd_t)-1) { #ifdef UKBD_LAYOUT layout = UKBD_LAYOUT; #else layout = KB_US; #endif } ukbd_keymapdata.layout = layout; printf("\n"); if (sc->sc_console_keyboard) { DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc)); wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata); ukbd_enable(sc, 1); } a.console = sc->sc_console_keyboard; a.keymap = &ukbd_keymapdata; a.accessops = &ukbd_accessops; a.accesscookie = sc; #ifdef WSDISPLAY_COMPAT_RAWKBD timeout_set(&sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc); #endif timeout_set(&sc->sc_delay, ukbd_delayed_decode, sc); /* Flash the leds; no real purpose, just shows we're alive. */ ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS); usbd_delay_ms(uha->parent->sc_udev, 400); ukbd_set_leds(sc, 0); sc->sc_wskbddev = config_found(self, &a, wskbddevprint); }
int ueagle_boot(struct ueagle_softc *sc) { uint16_t zero = 0; /* ;-) */ usbd_status error; #define CW(sc, address, offset, data) do { \ if ((error = ueagle_cw(sc, address, offset, data)) != 0) \ return error; \ } while (0) ueagle_request(sc, UEAGLE_SETMODE, UEAGLE_BOOTIDMA, NULL, 0); ueagle_request(sc, UEAGLE_SETMODE, UEAGLE_STARTRESET, NULL, 0); usbd_delay_ms(sc->sc_udev, 200); ueagle_request(sc, UEAGLE_SETMODE, UEAGLE_ENDRESET, NULL, 0); ueagle_request(sc, UEAGLE_SET2183DATA, UEAGLE_MPTXMAILBOX, &zero, 2); ueagle_request(sc, UEAGLE_SET2183DATA, UEAGLE_MPRXMAILBOX, &zero, 2); ueagle_request(sc, UEAGLE_SET2183DATA, UEAGLE_SWAPMAILBOX, &zero, 2); usbd_delay_ms(sc->sc_udev, 1000); sc->pageno = 0; sc->ovl = 0; ueagle_loadpage(sc); /* wait until modem reaches operational state */ error = tsleep(UEAGLE_COND_READY(sc), PZERO | PCATCH, "boot", 10 * hz); if (error != 0) { printf("%s: timeout waiting for operational state\n", sc->sc_dev.dv_xname); return error; } CW(sc, UEAGLE_CMV_CNTL, 0, 1); /* send configuration options */ CW(sc, UEAGLE_CMV_OPTN, 0, UEAGLE_OPTN0); CW(sc, UEAGLE_CMV_OPTN, 2, UEAGLE_OPTN2); CW(sc, UEAGLE_CMV_OPTN, 7, UEAGLE_OPTN7); /* continue with synchronization */ CW(sc, UEAGLE_CMV_CNTL, 0, 2); return kthread_create(ueagle_stat_thread, sc, &sc->stat_thread, sc->sc_dev.dv_xname); #undef CW }