int uriowrite(dev_t dev, struct uio *uio, int flag) { struct urio_softc *sc; usbd_xfer_handle xfer; usbd_status err; void *bufp; u_int32_t n; int error = 0; sc = device_lookup_private(&urio_cd, URIOUNIT(dev)); DPRINTFN(5, ("uriowrite: unit=%d, len=%ld\n", URIOUNIT(dev), (long)uio->uio_resid)); if (sc->sc_dying) return (EIO); xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == NULL) return (ENOMEM); bufp = usbd_alloc_buffer(xfer, URIO_BSIZE); if (bufp == NULL) { usbd_free_xfer(xfer); return (ENOMEM); } sc->sc_refcnt++; while ((n = min(URIO_BSIZE, uio->uio_resid)) != 0) { error = uiomove(bufp, n, uio); if (error) break; DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n)); err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, USBD_NO_COPY, URIO_RW_TIMEOUT, bufp, &n, "uriowr"); DPRINTFN(2, ("uriowrite: err=%d\n", err)); if (err) { if (err == USBD_INTERRUPTED) error = EINTR; else if (err == USBD_TIMEOUT) error = ETIMEDOUT; else error = EIO; break; } } usbd_free_xfer(xfer); if (--sc->sc_refcnt < 0) usb_detach_wakeupold(sc->sc_dev); DPRINTFN(5, ("uriowrite: done unit=%d, error=%d\n", URIOUNIT(dev), error)); return (error); }
Static int kue_rx_list_init(struct kue_softc *sc) { struct kue_cdata *cd; struct kue_chain *c; int i; DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev), __func__)); cd = &sc->kue_cdata; for (i = 0; i < KUE_RX_LIST_CNT; i++) { c = &cd->kue_rx_chain[i]; c->kue_sc = sc; c->kue_idx = i; if (kue_newbuf(sc, c, NULL) == ENOBUFS) return (ENOBUFS); if (c->kue_xfer == NULL) { c->kue_xfer = usbd_alloc_xfer(sc->kue_udev); if (c->kue_xfer == NULL) return (ENOBUFS); c->kue_buf = usbd_alloc_buffer(c->kue_xfer, KUE_BUFSZ); if (c->kue_buf == NULL) return (ENOBUFS); /* XXX free xfer */ } } return (0); }
Static int url_tx_list_init(struct url_softc *sc) { struct url_cdata *cd; struct url_chain *c; int i; DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__)); cd = &sc->sc_cdata; for (i = 0; i < URL_TX_LIST_CNT; i++) { c = &cd->url_tx_chain[i]; c->url_sc = sc; c->url_idx = i; c->url_mbuf = NULL; if (c->url_xfer == NULL) { c->url_xfer = usbd_alloc_xfer(sc->sc_udev); if (c->url_xfer == NULL) return (ENOBUFS); c->url_buf = usbd_alloc_buffer(c->url_xfer, URL_BUFSZ); if (c->url_buf == NULL) { usbd_free_xfer(c->url_xfer); return (ENOBUFS); } } } return (0); }
int ugl_rx_list_init(struct ugl_softc *sc) { struct ugl_cdata *cd; struct ugl_chain *c; int i; DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); cd = &sc->sc_cdata; for (i = 0; i < UGL_RX_LIST_CNT; i++) { c = &cd->ugl_rx_chain[i]; c->ugl_sc = sc; c->ugl_idx = i; if (ugl_newbuf(sc, c, NULL) == ENOBUFS) return (ENOBUFS); if (c->ugl_xfer == NULL) { c->ugl_xfer = usbd_alloc_xfer(sc->sc_udev); if (c->ugl_xfer == NULL) return (ENOBUFS); c->ugl_buf = usbd_alloc_buffer(c->ugl_xfer, UGL_BUFSZ); if (c->ugl_buf == NULL) { usbd_free_xfer(c->ugl_xfer); return (ENOBUFS); } } } return (0); }
int wi_usb_tx_list_init(struct wi_usb_softc *sc) { struct wi_usb_chain *c; int i; DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); for (i = 0; i < WI_USB_TX_LIST_CNT; i++) { c = &sc->wi_usb_tx_chain[i]; c->wi_usb_sc = sc; c->wi_usb_idx = i; c->wi_usb_mbuf = NULL; if (c->wi_usb_xfer != NULL) { printf("UGH TX\n"); } if (c->wi_usb_xfer == NULL) { c->wi_usb_xfer = usbd_alloc_xfer(sc->wi_usb_udev); if (c->wi_usb_xfer == NULL) return (ENOBUFS); c->wi_usb_buf = usbd_alloc_buffer(c->wi_usb_xfer, WI_USB_BUFSZ); if (c->wi_usb_buf == NULL) return (ENOBUFS); } } return (0); }
int kue_tx_list_init(struct kue_softc *sc) { struct kue_cdata *cd; struct kue_chain *c; int i; DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__)); cd = &sc->kue_cdata; for (i = 0; i < KUE_TX_LIST_CNT; i++) { c = &cd->kue_tx_chain[i]; c->kue_sc = sc; c->kue_idx = i; c->kue_mbuf = NULL; if (c->kue_xfer == NULL) { c->kue_xfer = usbd_alloc_xfer(sc->kue_udev); if (c->kue_xfer == NULL) return (ENOBUFS); c->kue_buf = usbd_alloc_buffer(c->kue_xfer, KUE_BUFSZ); if (c->kue_buf == NULL) return (ENOBUFS); } } return (0); }
int uriowrite(dev_t dev, struct uio *uio, int flag) { struct urio_softc *sc; struct usbd_xfer *xfer; usbd_status err; void *bufp; u_int32_t n; int error = 0; sc = urio_cd.cd_devs[URIOUNIT(dev)]; DPRINTFN(5, ("uriowrite: unit=%d, len=%ld\n", URIOUNIT(dev), (long)uio->uio_resid)); if (usbd_is_dying(sc->sc_udev)) return (EIO); xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == NULL) return (ENOMEM); bufp = usbd_alloc_buffer(xfer, URIO_BSIZE); if (bufp == NULL) { usbd_free_xfer(xfer); return (ENOMEM); } sc->sc_refcnt++; while ((n = min(URIO_BSIZE, uio->uio_resid)) != 0) { error = uiomove(bufp, n, uio); if (error) break; DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n)); usbd_setup_xfer(xfer, sc->sc_out_pipe, 0, bufp, n, USBD_NO_COPY | USBD_SYNCHRONOUS, URIO_RW_TIMEOUT, NULL); err = usbd_transfer(xfer); DPRINTFN(2, ("uriowrite: err=%d\n", err)); if (err) { usbd_clear_endpoint_stall(sc->sc_out_pipe); if (err == USBD_TIMEOUT) error = ETIMEDOUT; else error = EIO; break; } } usbd_free_xfer(xfer); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); DPRINTFN(5, ("uriowrite: done unit=%d, error=%d\n", URIOUNIT(dev), error)); return (error); }
/* alloc/free pipe */ static usbd_status alloc_pipe(struct umidi_endpoint *ep) { struct umidi_softc *sc = ep->sc; usbd_status err; DPRINTF(("%s: alloc_pipe %p\n", sc->sc_dev.dv_xname, ep)); SIMPLEQ_INIT(&ep->intrq); ep->pending = 0; ep->busy = 0; ep->used = 0; ep->xfer = usbd_alloc_xfer(sc->sc_udev); if (ep->xfer == NULL) return USBD_NOMEM; ep->buffer = usbd_alloc_buffer(ep->xfer, ep->packetsize); if (ep->buffer == NULL) { usbd_free_xfer(ep->xfer); return USBD_NOMEM; } err = usbd_open_pipe(sc->sc_iface, ep->addr, 0, &ep->pipe); if (err != USBD_NORMAL_COMPLETION) { usbd_free_xfer(ep->xfer); return err; } return USBD_NORMAL_COMPLETION; }
static int auvitek_start_xfer(struct auvitek_softc *sc) { struct auvitek_xfer *ax = &sc->sc_ax; uint32_t vframe_len, uframe_len, nframes; usbd_status err; int i; err = usbd_set_interface(sc->sc_isoc_iface, AUVITEK_XFER_ALTNO); if (err != USBD_NORMAL_COMPLETION) { aprint_error_dev(sc->sc_dev, "couldn't set altno %d: %s\n", AUVITEK_XFER_ALTNO, usbd_errstr(err)); return EIO; } vframe_len = 720 * 480 * 2; uframe_len = ax->ax_maxpktlen; nframes = (vframe_len + uframe_len - 1) / uframe_len; nframes = (nframes + 7) & ~7; ax->ax_nframes = nframes; ax->ax_uframe_len = uframe_len; for (i = 0; i < AUVITEK_NISOC_XFERS; i++) { struct auvitek_isoc *isoc = &ax->ax_i[i]; isoc->i_ax = ax; isoc->i_frlengths = kmem_alloc(sizeof(isoc->i_frlengths[0]) * nframes, KM_SLEEP); } err = usbd_open_pipe(sc->sc_isoc_iface, ax->ax_endpt, USBD_EXCLUSIVE_USE, &ax->ax_pipe); if (err != USBD_NORMAL_COMPLETION) { aprint_error_dev(sc->sc_dev, "couldn't open pipe: %s\n", usbd_errstr(err)); return EIO; } for (i = 0; i < AUVITEK_NISOC_XFERS; i++) { struct auvitek_isoc *isoc = &ax->ax_i[i]; isoc->i_xfer = usbd_alloc_xfer(sc->sc_udev); if (isoc->i_xfer == NULL) { aprint_error_dev(sc->sc_dev, "couldn't allocate usb xfer\n"); return ENOMEM; } isoc->i_buf = usbd_alloc_buffer(isoc->i_xfer, nframes * uframe_len); if (isoc->i_buf == NULL) { aprint_error_dev(sc->sc_dev, "couldn't allocate usb xfer buffer\n"); return ENOMEM; } } return auvitek_isoc_start(sc); }
int urioread(dev_t dev, struct uio *uio, int flag) { struct urio_softc *sc; usbd_xfer_handle xfer; usbd_status err; void *bufp; u_int32_t n, tn; int error = 0; sc = device_lookup_private(&urio_cd, URIOUNIT(dev)); DPRINTFN(5, ("urioread: %d\n", URIOUNIT(dev))); if (sc->sc_dying) return (EIO); xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == NULL) return (ENOMEM); bufp = usbd_alloc_buffer(xfer, URIO_BSIZE); if (bufp == NULL) { usbd_free_xfer(xfer); return (ENOMEM); } sc->sc_refcnt++; while ((n = min(URIO_BSIZE, uio->uio_resid)) != 0) { DPRINTFN(1, ("urioread: start transfer %d bytes\n", n)); tn = n; err = usbd_bulk_transfer(xfer, sc->sc_in_pipe, USBD_NO_COPY, URIO_RW_TIMEOUT, bufp, &tn, "uriors"); if (err) { if (err == USBD_INTERRUPTED) error = EINTR; else if (err == USBD_TIMEOUT) error = ETIMEDOUT; else error = EIO; break; } DPRINTFN(1, ("urioread: got %d bytes\n", tn)); error = uiomove(bufp, tn, uio); if (error || tn < n) break; } usbd_free_xfer(xfer); if (--sc->sc_refcnt < 0) usb_detach_wakeupold(sc->sc_dev); return (error); }
/* alloc/free pipe */ static usbd_status alloc_pipe(struct umidi_endpoint *ep) { struct umidi_softc *sc = ep->sc; usbd_status err; usb_endpoint_descriptor_t *epd; epd = usbd_get_endpoint_descriptor(sc->sc_iface, ep->addr); /* * For output, an improvement would be to have a buffer bigger than * wMaxPacketSize by num_jacks-1 additional packet slots; that would * allow out_solicit to fill the buffer to the full packet size in * all cases. But to use usbd_alloc_buffer to get a slightly larger * buffer would not be a good way to do that, because if the addition * would make the buffer exceed USB_MEM_SMALL then a substantially * larger block may be wastefully allocated. Some flavor of double * buffering could serve the same purpose, but would increase the * code complexity, so for now I will live with the current slight * penalty of reducing max transfer size by (num_open-num_scheduled) * packet slots. */ ep->buffer_size = UGETW(epd->wMaxPacketSize); ep->buffer_size -= ep->buffer_size % UMIDI_PACKET_SIZE; DPRINTF(("%s: alloc_pipe %p, buffer size %u\n", USBDEVNAME(sc->sc_dev), ep, ep->buffer_size)); ep->num_scheduled = 0; ep->this_schedule = 0; ep->next_schedule = 0; ep->soliciting = 0; ep->armed = 0; ep->xfer = usbd_alloc_xfer(sc->sc_udev); if (ep->xfer == NULL) { err = USBD_NOMEM; goto quit; } ep->buffer = usbd_alloc_buffer(ep->xfer, ep->buffer_size); if (ep->buffer == NULL) { usbd_free_xfer(ep->xfer); err = USBD_NOMEM; goto quit; } ep->next_slot = ep->buffer; err = usbd_open_pipe(sc->sc_iface, ep->addr, 0, &ep->pipe); if (err) usbd_free_xfer(ep->xfer); ep->solicit_cookie = softint_establish(SOFTINT_CLOCK, out_solicit, ep); quit: return err; }
int uhidev_get_report_async(struct uhidev_softc *sc, int type, int id, void *data, int len, void *priv, void (*callback)(void *, int, void *, int)) { struct usbd_xfer *xfer; usb_device_request_t req; struct uhidev_async_info *info; int actlen = len; char *buf; xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == NULL) return (-1); if (id > 0) len++; buf = usbd_alloc_buffer(xfer, len); if (buf == NULL) { usbd_free_xfer(xfer); return (-1); } info = malloc(sizeof(*info), M_TEMP, M_NOWAIT); if (info == NULL) { usbd_free_xfer(xfer); return (-1); } info->callback = callback; info->priv = priv; info->data = data; info->id = id; req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_GET_REPORT; USETW2(req.wValue, type, id); USETW(req.wIndex, sc->sc_ifaceno); USETW(req.wLength, len); if (usbd_request_async(xfer, &req, info, uhidev_get_report_async_cb)) { free(info, M_TEMP, sizeof(*info)); actlen = -1; } return (actlen); }
/* Build encapsulated cmd / response and transfer it */ static jresult_t encapsulated_transfer(cdc_cmd_priv_t *priv, void *membuf, juint16_t size) { usbd_status status = USBD_NORMAL_COMPLETION; usbd_xfer_handle xfer = NULL; jcdc_dev_softc_t *sc = priv->sc; usb_device_request_t req_t; jbool_t in_xfer = (priv->req_type == SEND_ENCAP_CMD) ? 0 : 1; DECLARE_FNAME("encapsulated_transfer"); DBG_X(DHOST_CDC_GENERAL, ("%s: Entered\n", fname)); xfer = usbd_alloc_xfer(sc->device); if (!xfer) { DBG_E(DHOST_CDC_GENERAL, ("%s: Failed to allocate xfer\n", fname)); return JENOMEM; } /* Build request according to xfer direction */ req_t.bmRequestType = (in_xfer) ? UT_READ_CLASS_INTERFACE : UT_WRITE_CLASS_INTERFACE; req_t.bRequest = (in_xfer) ? CDC_GET_ENC_RESPONSE : CDC_SEND_ENC_COMMAND; USETW(req_t.wValue, 0); USETW(req_t.wIndex, (juint16_t)sc->c_iface->index); USETW(req_t.wLength, size); /* setup xfer */ usbd_setup_default_xfer(xfer, priv->sc->device, priv, CDC_CONTROL_XFER_TIMEOUT, &req_t, membuf, size, 0, jcdc_send_encap_cb); /* Send the request over default pipe (EP0) */ status = usbd_transfer(xfer); if (status && status != USBD_IN_PROGRESS) { DBG_E(DHOST_CDC_GENERAL, ("%s: Failed transferring control request, " "error %d\n", j_device_get_nameunit(priv->sc->dev), status)); usbd_free_xfer(xfer); return status_to_result(status); } return 0; }
int uhidev_set_report_async(struct uhidev_softc *sc, int type, int id, void *data, int len) { struct usbd_xfer *xfer; usb_device_request_t req; int actlen = len; char *buf; xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == NULL) return (-1); if (id > 0) len++; buf = usbd_alloc_buffer(xfer, len); if (buf == NULL) { usbd_free_xfer(xfer); return (-1); } /* Prepend the reportID. */ if (id > 0) { buf[0] = id; memcpy(buf + 1, data, len - 1); } else { memcpy(buf, data, len); } req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_REPORT; USETW2(req.wValue, type, id); USETW(req.wIndex, sc->sc_ifaceno); USETW(req.wLength, len); if (usbd_request_async(xfer, &req, NULL, NULL)) actlen = -1; return (actlen); }
/* General CDC asynchronous transfer function */ static jresult_t cdc_async_transfer(cdc_cmd_priv_t *priv, usbd_pipe_handle pipe, void *membuf, juint32_t size, usbd_xfer_handle xfer) { jresult_t rc; usbd_status status; juint16_t flags = USBD_SHORT_XFER_OK | USBD_FORCE_SHORT_XFER; DECLARE_FNAME("cdc_async_transfer"); DBG_X(DHOST_CDC_GENERAL, ("%s: Entered\n", fname)); /* Allocate a transfer request object and set up a xfer */ xfer = usbd_alloc_xfer(priv->sc->device); if (!xfer) { DBG_E(DHOST_CDC_GENERAL, ("%s: Failed to allocate xfer\n", fname)); rc = JENOMEM; goto Error; } usbd_setup_xfer(xfer, pipe, (void *)priv, membuf, size, flags, CDC_DATA_XFER_TIMEOUT, cdc_data_xfer_complete); /* Execute xfer */ status = usbd_transfer(xfer); if (status && status != USBD_IN_PROGRESS) { DBG_W(DHOST_CDC_GENERAL, ("%s: failed to setup transfer, %s\n", fname, usbd_errstr(status))); rc = status_to_result(status); goto Error; } return 0; Error: if (xfer) usbd_free_xfer(xfer); return rc; }
static int atausb_attach(device_t dev) { struct atausb_softc *sc = device_get_softc(dev); struct usb_attach_arg *uaa = device_get_ivars(dev); usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usbd_device_handle udev; usb_device_request_t request; char devinfo[1024], *proto, *subclass; u_int8_t maxlun; int err, i; sc->dev = dev; usbd_devinfo(uaa->device, 0, devinfo); device_set_desc_copy(dev, devinfo); sc->bulkin = sc->bulkout = sc->bulkirq = -1; sc->bulkin_pipe = sc->bulkout_pipe= sc->bulkirq_pipe = NULL; sc->iface = uaa->iface; sc->ifaceno = uaa->ifaceno; sc->maxlun = 0; sc->timeout = 5000; sc->locked_ch = NULL; sc->restart_ch = NULL; spin_init(&sc->locked_mtx); id = usbd_get_interface_descriptor(sc->iface); switch (id->bInterfaceProtocol) { case UIPROTO_MASS_BBB: case UIPROTO_MASS_BBB_OLD: proto = "Bulk-Only"; break; case UIPROTO_MASS_CBI: proto = "CBI"; break; case UIPROTO_MASS_CBI_I: proto = "CBI with CCI"; break; default: proto = "Unknown"; } switch (id->bInterfaceSubClass) { case UISUBCLASS_RBC: subclass = "RBC"; break; case UISUBCLASS_QIC157: case UISUBCLASS_SFF8020I: case UISUBCLASS_SFF8070I: subclass = "ATAPI"; break; case UISUBCLASS_SCSI: subclass = "SCSI"; break; case UISUBCLASS_UFI: subclass = "UFI"; break; default: subclass = "Unknown"; } device_printf(dev, "using %s over %s\n", subclass, proto); if (strcmp(proto, "Bulk-Only") || (strcmp(subclass, "ATAPI") && strcmp(subclass, "SCSI"))) return ENXIO; for (i = 0 ; i < id->bNumEndpoints ; i++) { if (!(ed = usbd_interface2endpoint_descriptor(sc->iface, i))) { device_printf(sc->dev, "could not read endpoint descriptor\n"); return ENXIO; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { sc->bulkin = ed->bEndpointAddress; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { sc->bulkout = ed->bEndpointAddress; } if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { sc->bulkirq = ed->bEndpointAddress; } } /* check whether we found at least the endpoints we need */ if (!sc->bulkin || !sc->bulkout) { device_printf(sc->dev, "needed endpoints not found (%d,%d)\n", sc->bulkin, sc->bulkout); atausb_detach(dev); return ENXIO; } /* open the pipes */ if (usbd_open_pipe(sc->iface, sc->bulkout, USBD_EXCLUSIVE_USE, &sc->bulkout_pipe)) { device_printf(sc->dev, "cannot open bulkout pipe (%d)\n", sc->bulkout); atausb_detach(dev); return ENXIO; } if (usbd_open_pipe(sc->iface, sc->bulkin, USBD_EXCLUSIVE_USE, &sc->bulkin_pipe)) { device_printf(sc->dev, "cannot open bulkin pipe (%d)\n", sc->bulkin); atausb_detach(dev); return ENXIO; } if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I) { if (usbd_open_pipe(sc->iface, sc->bulkirq, USBD_EXCLUSIVE_USE, &sc->bulkirq_pipe)) { device_printf(sc->dev, "cannot open bulkirq pipe (%d)\n", sc->bulkirq); atausb_detach(dev); return ENXIO; } } sc->state = ATAUSB_S_ATTACH; /* alloc needed number of transfer handles */ for (i = 0; i < ATAUSB_T_MAX; i++) { sc->transfer[i] = usbd_alloc_xfer(uaa->device); if (!sc->transfer[i]) { device_printf(sc->dev, "out of memory\n"); atausb_detach(dev); return ENXIO; } } /* driver is ready to process requests here */ sc->state = ATAUSB_S_IDLE; /* get number of devices so we can add matching channels */ usbd_interface2device_handle(sc->iface, &udev); request.bmRequestType = UT_READ_CLASS_INTERFACE; request.bRequest = 0xfe; /* GET_MAX_LUN; */ USETW(request.wValue, 0); USETW(request.wIndex, sc->ifaceno); USETW(request.wLength, sizeof(maxlun)); switch ((err = usbd_do_request(udev, &request, &maxlun))) { case USBD_NORMAL_COMPLETION: if (bootverbose) device_printf(sc->dev, "maxlun=%d\n", maxlun); sc->maxlun = maxlun; break; default: if (bootverbose) device_printf(sc->dev, "get maxlun not supported %s\n", usbd_errstr(err)); } /* ata channels are children to this USB control device */ for (i = 0; i <= sc->maxlun; i++) { /* XXX TGEN devclass_find_free_unit() implementation */ int freeunit = 2; while (freeunit < devclass_get_maxunit(ata_devclass) && devclass_get_device(ata_devclass, freeunit) != NULL) freeunit++; if (!device_add_child(sc->dev, "ata", freeunit)) { device_printf(sc->dev, "failed to attach ata child device\n"); atausb_detach(dev); return ENXIO; } } bus_generic_attach(sc->dev); return 0; }
int ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) { struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN]; u_int32_t n, tn; char buf[UGEN_BBSIZE]; struct usbd_xfer *xfer; usbd_status err; int s; int flags, error = 0; u_char buffer[UGEN_CHUNK]; DPRINTFN(5, ("%s: ugenread: %d\n", sc->sc_dev.dv_xname, endpt)); if (usbd_is_dying(sc->sc_udev)) return (EIO); if (endpt == USB_CONTROL_ENDPOINT) return (ENODEV); #ifdef DIAGNOSTIC if (sce->edesc == NULL) { printf("ugenread: no edesc\n"); return (EIO); } if (sce->pipeh == NULL) { printf("ugenread: no pipe\n"); return (EIO); } #endif switch (sce->edesc->bmAttributes & UE_XFERTYPE) { case UE_INTERRUPT: /* Block until activity occurred. */ s = splusb(); while (sce->q.c_cc == 0) { if (flag & IO_NDELAY) { splx(s); return (EWOULDBLOCK); } sce->state |= UGEN_ASLP; DPRINTFN(5, ("ugenread: sleep on %p\n", sce)); error = tsleep(sce, PZERO | PCATCH, "ugenri", (sce->timeout * hz) / 1000); sce->state &= ~UGEN_ASLP; DPRINTFN(5, ("ugenread: woke, error=%d\n", error)); if (usbd_is_dying(sc->sc_udev)) error = EIO; if (error == EWOULDBLOCK) { /* timeout, return 0 */ error = 0; break; } if (error) break; } splx(s); /* Transfer as many chunks as possible. */ while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) { n = min(sce->q.c_cc, uio->uio_resid); if (n > sizeof(buffer)) n = sizeof(buffer); /* Remove a small chunk from the input queue. */ q_to_b(&sce->q, buffer, n); DPRINTFN(5, ("ugenread: got %d chars\n", n)); /* Copy the data to the user process. */ error = uiomove(buffer, n, uio); if (error) break; } break; case UE_BULK: xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == 0) return (ENOMEM); flags = USBD_SYNCHRONOUS; if (sce->state & UGEN_SHORT_OK) flags |= USBD_SHORT_XFER_OK; if (sce->timeout == 0) flags |= USBD_CATCH; while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n)); usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n, flags, sce->timeout, NULL); err = usbd_transfer(xfer); if (err) { usbd_clear_endpoint_stall(sce->pipeh); if (err == USBD_INTERRUPTED) error = EINTR; else if (err == USBD_TIMEOUT) error = ETIMEDOUT; else error = EIO; break; } usbd_get_xfer_status(xfer, NULL, NULL, &tn, NULL); DPRINTFN(1, ("ugenread: got %d bytes\n", tn)); error = uiomove(buf, tn, uio); if (error || tn < n) break; } usbd_free_xfer(xfer); break; case UE_ISOCHRONOUS: s = splusb(); while (sce->cur == sce->fill) { if (flag & IO_NDELAY) { splx(s); return (EWOULDBLOCK); } sce->state |= UGEN_ASLP; DPRINTFN(5, ("ugenread: sleep on %p\n", sce)); error = tsleep(sce, PZERO | PCATCH, "ugenri", (sce->timeout * hz) / 1000); sce->state &= ~UGEN_ASLP; DPRINTFN(5, ("ugenread: woke, error=%d\n", error)); if (usbd_is_dying(sc->sc_udev)) error = EIO; if (error == EWOULDBLOCK) { /* timeout, return 0 */ error = 0; break; } if (error) break; } while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) { if(sce->fill > sce->cur) n = min(sce->fill - sce->cur, uio->uio_resid); else n = min(sce->limit - sce->cur, uio->uio_resid); DPRINTFN(5, ("ugenread: isoc got %d chars\n", n)); /* Copy the data to the user process. */ error = uiomove(sce->cur, n, uio); if (error) break; sce->cur += n; if(sce->cur >= sce->limit) sce->cur = sce->ibuf; } splx(s); break; default: return (ENXIO); } return (error); }
int uirda_open(void *h, int flag, int mode, struct lwp *l) { struct uirda_softc *sc = h; int error; usbd_status err; DPRINTF(("%s: sc=%p\n", __func__, sc)); err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe); if (err) { error = EIO; goto bad1; } err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe); if (err) { error = EIO; goto bad2; } sc->sc_rd_xfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_rd_xfer == NULL) { error = ENOMEM; goto bad3; } sc->sc_wr_xfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_wr_xfer == NULL) { error = ENOMEM; goto bad4; } sc->sc_rd_buf = usbd_alloc_buffer(sc->sc_rd_xfer, IRDA_MAX_FRAME_SIZE + sc->sc_hdszi); if (sc->sc_rd_buf == NULL) { error = ENOMEM; goto bad5; } sc->sc_wr_buf = usbd_alloc_buffer(sc->sc_wr_xfer, IRDA_MAX_FRAME_SIZE + UIRDA_OUTPUT_HEADER_SIZE + 2 + 1 /* worst case ST-UIRDA */); if (sc->sc_wr_buf == NULL) { error = ENOMEM; goto bad5; } sc->sc_rd_count = 0; sc->sc_rd_err = 0; sc->sc_params.speed = 0; sc->sc_params.ebofs = 0; sc->sc_params.maxsize = IRDA_MAX_FRAME_SIZE; sc->sc_wr_hdr = -1; err = uirda_start_read(sc); /* XXX check err */ return (0); bad5: usbd_free_xfer(sc->sc_wr_xfer); sc->sc_wr_xfer = NULL; bad4: usbd_free_xfer(sc->sc_rd_xfer); sc->sc_rd_xfer = NULL; bad3: usbd_close_pipe(sc->sc_wr_pipe); sc->sc_wr_pipe = NULL; bad2: usbd_close_pipe(sc->sc_rd_pipe); sc->sc_rd_pipe = NULL; bad1: return (error); }
int ucomopen(dev_t dev, int flag, int mode, struct lwp *l) { int unit = UCOMUNIT(dev); usbd_status err; struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit); struct ucom_buffer *ub; struct tty *tp; int s, i; int error; if (sc == NULL) return (ENXIO); if (sc->sc_dying) return (EIO); if (!device_is_active(sc->sc_dev)) return (ENXIO); tp = sc->sc_tty; DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp)); if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); s = spltty(); /* * Do the following iff this is a first open. */ while (sc->sc_opening) tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0); if (sc->sc_dying) { splx(s); return (EIO); } sc->sc_opening = 1; if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { struct termios t; tp->t_dev = dev; if (sc->sc_methods->ucom_open != NULL) { error = sc->sc_methods->ucom_open(sc->sc_parent, sc->sc_portno); if (error) { ucom_cleanup(sc); sc->sc_opening = 0; wakeup(&sc->sc_opening); splx(s); return (error); } } ucom_status_change(sc); /* * Initialize the termios status to the defaults. Add in the * sticky bits from TIOCSFLAGS. */ t.c_ispeed = 0; t.c_ospeed = TTYDEF_SPEED; t.c_cflag = TTYDEF_CFLAG; if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) SET(t.c_cflag, CLOCAL); if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) SET(t.c_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) SET(t.c_cflag, MDMBUF); /* Make sure ucomparam() will do something. */ tp->t_ospeed = 0; (void) ucomparam(tp, &t); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; ttychars(tp); ttsetwater(tp); /* * Turn on DTR. We must always do this, even if carrier is not * present, because otherwise we'd have to use TIOCSDTR * immediately after setting CLOCAL, which applications do not * expect. We always assert DTR while the device is open * unless explicitly requested to deassert it. Ditto RTS. */ ucom_dtr(sc, 1); ucom_rts(sc, 1); DPRINTF(("ucomopen: open pipes in=%d out=%d\n", sc->sc_bulkin_no, sc->sc_bulkout_no)); /* Open the bulk pipes */ err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe); if (err) { DPRINTF(("%s: open bulk in error (addr %d), err=%s\n", USBDEVNAME(sc->sc_dev), sc->sc_bulkin_no, usbd_errstr(err))); error = EIO; goto fail_0; } err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); if (err) { DPRINTF(("%s: open bulk out error (addr %d), err=%s\n", USBDEVNAME(sc->sc_dev), sc->sc_bulkout_no, usbd_errstr(err))); error = EIO; goto fail_1; } sc->sc_rx_unblock = 0; sc->sc_rx_stopped = 0; sc->sc_tx_stopped = 0; memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff)); memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff)); SIMPLEQ_INIT(&sc->sc_ibuff_empty); SIMPLEQ_INIT(&sc->sc_ibuff_full); SIMPLEQ_INIT(&sc->sc_obuff_free); SIMPLEQ_INIT(&sc->sc_obuff_full); /* Allocate input buffers */ for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS]; ub++) { ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev); if (ub->ub_xfer == NULL) { error = ENOMEM; goto fail_2; } ub->ub_data = usbd_alloc_buffer(ub->ub_xfer, sc->sc_ibufsizepad); if (ub->ub_data == NULL) { error = ENOMEM; goto fail_2; } if (ucomsubmitread(sc, ub) != USBD_NORMAL_COMPLETION) { error = EIO; goto fail_2; } } for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS]; ub++) { ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev); if (ub->ub_xfer == NULL) { error = ENOMEM; goto fail_2; } ub->ub_data = usbd_alloc_buffer(ub->ub_xfer, sc->sc_obufsize); if (ub->ub_data == NULL) { error = ENOMEM; goto fail_2; } SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link); } } sc->sc_opening = 0; wakeup(&sc->sc_opening); splx(s); error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); if (error) goto bad; error = (*tp->t_linesw->l_open)(dev, tp); if (error) goto bad; return (0); fail_2: usbd_abort_pipe(sc->sc_bulkin_pipe); for (i = 0; i < UCOM_IN_BUFFS; i++) { if (sc->sc_ibuff[i].ub_xfer != NULL) { usbd_free_xfer(sc->sc_ibuff[i].ub_xfer); sc->sc_ibuff[i].ub_xfer = NULL; sc->sc_ibuff[i].ub_data = NULL; } } usbd_abort_pipe(sc->sc_bulkout_pipe); for (i = 0; i < UCOM_OUT_BUFFS; i++) { if (sc->sc_obuff[i].ub_xfer != NULL) { usbd_free_xfer(sc->sc_obuff[i].ub_xfer); sc->sc_obuff[i].ub_xfer = NULL; sc->sc_obuff[i].ub_data = NULL; } } usbd_close_pipe(sc->sc_bulkout_pipe); sc->sc_bulkout_pipe = NULL; fail_1: usbd_close_pipe(sc->sc_bulkin_pipe); sc->sc_bulkin_pipe = NULL; fail_0: sc->sc_opening = 0; wakeup(&sc->sc_opening); splx(s); return (error); bad: s = spltty(); CLR(tp->t_state, TS_BUSY); if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { /* * We failed to open the device, and nobody else had it opened. * Clean up the state as appropriate. */ ucom_cleanup(sc); } splx(s); return (error); }
int uriowrite(struct dev_write_args *ap) { cdev_t dev = ap->a_head.a_dev; struct uio *uio = ap->a_uio; #if (USBDI >= 1) struct urio_softc * sc; usbd_xfer_handle reqh; #else usbd_request_handle reqh; #endif int unit = URIOUNIT(dev); usbd_status r; char buf[URIO_BBSIZE]; u_int32_t n; int error = 0; sc = devclass_get_softc(urio_devclass, unit); DPRINTFN(5, ("uriowrite: %d\n", unit)); if (!sc->sc_opened) return EIO; #if (USBDI >= 1) sc->sc_refcnt++; reqh = usbd_alloc_xfer(sc->sc_udev); #else reqh = usbd_alloc_request(); #endif if (reqh == 0) return EIO; while ((n = szmin(URIO_BBSIZE, uio->uio_resid)) != 0) { error = uiomove(buf, n, uio); if (error) break; DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n)); #if (USBDI >= 1) usbd_setup_xfer(reqh, sc->sc_pipeh_out, 0, buf, n, 0, RIO_RW_TIMEOUT, 0); #else r = usbd_setup_request(reqh, sc->sc_pipeh_out, 0, buf, n, 0, RIO_RW_TIMEOUT, 0); if (r != USBD_NORMAL_COMPLETION) { error = EIO; break; } #endif r = usbd_sync_transfer(reqh); if (r != USBD_NORMAL_COMPLETION) { DPRINTFN(1, ("uriowrite: error=%d\n", r)); usbd_clear_endpoint_stall(sc->sc_pipeh_out); error = EIO; break; } #if (USBDI >= 1) usbd_get_xfer_status(reqh, 0, 0, 0, 0); #endif } #if (USBDI >= 1) usbd_free_xfer(reqh); #else usbd_free_request(reqh); #endif return error; }
usbd_status umsm_umass_changemode(struct umsm_softc *sc) { #define UMASS_CMD_REZERO_UNIT 0x01 #define UMASS_CMD_START_STOP 0x1b #define UMASS_CMDPARAM_EJECT 0x02 #define UMASS_SERVICE_ACTION_OUT 0x9f usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; struct usbd_xfer *xfer; struct usbd_pipe *cmdpipe; usbd_status err; u_int32_t n; void *bufp; int target_ep, i; struct umass_bbb_cbw cbw; static int dCBWTag = 0x12345678; USETDW(cbw.dCBWSignature, CBWSIGNATURE); USETDW(cbw.dCBWTag, dCBWTag); cbw.bCBWLUN = 0; cbw.bCDBLength= 6; bzero(cbw.CBWCDB, sizeof(cbw.CBWCDB)); switch (sc->sc_flag) { case DEV_UMASS1: USETDW(cbw.dCBWDataTransferLength, 0x0); cbw.bCBWFlags = CBWFLAGS_OUT; cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT; cbw.CBWCDB[1] = 0x0; /* target LUN: 0 */ break; case DEV_UMASS2: USETDW(cbw.dCBWDataTransferLength, 0x1); cbw.bCBWFlags = CBWFLAGS_IN; cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT; cbw.CBWCDB[1] = 0x0; /* target LUN: 0 */ break; case DEV_UMASS3: /* longcheer */ USETDW(cbw.dCBWDataTransferLength, 0x80); cbw.bCBWFlags = CBWFLAGS_IN; cbw.CBWCDB[0] = 0x06; cbw.CBWCDB[1] = 0xf5; cbw.CBWCDB[2] = 0x04; cbw.CBWCDB[3] = 0x02; cbw.CBWCDB[4] = 0x52; cbw.CBWCDB[5] = 0x70; break; case DEV_UMASS4: USETDW(cbw.dCBWDataTransferLength, 0x0); cbw.bCBWFlags = CBWFLAGS_OUT; cbw.CBWCDB[0] = UMASS_CMD_START_STOP; cbw.CBWCDB[1] = 0x00; /* target LUN: 0 */ cbw.CBWCDB[4] = UMASS_CMDPARAM_EJECT; break; case DEV_UMASS5: cbw.bCBWFlags = CBWFLAGS_OUT; cbw.CBWCDB[0] = 0x11; cbw.CBWCDB[1] = 0x06; break; case DEV_UMASS6: /* ZTE */ USETDW(cbw.dCBWDataTransferLength, 0x20); cbw.bCBWFlags = CBWFLAGS_IN; cbw.bCDBLength= 12; cbw.CBWCDB[0] = 0x85; cbw.CBWCDB[1] = 0x01; cbw.CBWCDB[2] = 0x01; cbw.CBWCDB[3] = 0x01; cbw.CBWCDB[4] = 0x18; cbw.CBWCDB[5] = 0x01; cbw.CBWCDB[6] = 0x01; cbw.CBWCDB[7] = 0x01; cbw.CBWCDB[8] = 0x01; cbw.CBWCDB[9] = 0x01; break; case DEV_UMASS7: /* ZTE */ USETDW(cbw.dCBWDataTransferLength, 0xc0); cbw.bCBWFlags = CBWFLAGS_IN; cbw.CBWCDB[0] = UMASS_SERVICE_ACTION_OUT; cbw.CBWCDB[1] = 0x03; break; case DEV_UMASS8: USETDW(cbw.dCBWDataTransferLength, 0x0); cbw.bCBWFlags = CBWFLAGS_OUT; cbw.CBWCDB[0] = 0xf0; cbw.CBWCDB[1] = 0x01; cbw.CBWCDB[2] = 0x03; break; default: DPRINTF(("%s: unknown device type.\n", sc->sc_dev.dv_xname)); break; } /* get command endpoint address */ id = usbd_get_interface_descriptor(sc->sc_iface); for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (ed == NULL) { return (USBD_IOERROR); } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) target_ep = ed->bEndpointAddress; } /* open command endppoint */ err = usbd_open_pipe(sc->sc_iface, target_ep, USBD_EXCLUSIVE_USE, &cmdpipe); if (err) { DPRINTF(("%s: open pipe for modem change cmd failed: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err))); return (err); } xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == NULL) { usbd_close_pipe(cmdpipe); return (USBD_NOMEM); } else { bufp = usbd_alloc_buffer(xfer, UMASS_BBB_CBW_SIZE); if (bufp == NULL) err = USBD_NOMEM; else { n = UMASS_BBB_CBW_SIZE; memcpy(bufp, &cbw, UMASS_BBB_CBW_SIZE); usbd_setup_xfer(xfer, cmdpipe, 0, bufp, n, USBD_NO_COPY | USBD_SYNCHRONOUS, 0, NULL); err = usbd_transfer(xfer); if (err) { usbd_clear_endpoint_stall(cmdpipe); DPRINTF(("%s: send error:%s", __func__, usbd_errstr(err))); } } usbd_close_pipe(cmdpipe); usbd_free_buffer(xfer); usbd_free_xfer(xfer); } return (err); }
/* ARGSUSED */ static int udsir_open(void *h, int flag, int mode, struct lwp *l) { struct udsir_softc *sc = h; int error; usbd_status err; DPRINTFN(0, ("%s: sc=%p\n", __func__, sc)); err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe); if (err != USBD_NORMAL_COMPLETION) { error = EIO; goto bad1; } err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe); if (err != USBD_NORMAL_COMPLETION) { error = EIO; goto bad2; } sc->sc_rd_xfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_rd_xfer == NULL) { error = ENOMEM; goto bad3; } sc->sc_wr_xfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_wr_xfer == NULL) { error = ENOMEM; goto bad4; } sc->sc_rd_buf = usbd_alloc_buffer(sc->sc_rd_xfer, sc->sc_rd_maxpsz); if (sc->sc_rd_buf == NULL) { error = ENOMEM; goto bad5; } sc->sc_wr_buf = usbd_alloc_buffer(sc->sc_wr_xfer, IRDA_MAX_FRAME_SIZE); if (sc->sc_wr_buf == NULL) { error = ENOMEM; goto bad5; } sc->sc_ur_buf = malloc(IRDA_MAX_FRAME_SIZE, M_USBDEV, M_NOWAIT); if (sc->sc_ur_buf == NULL) { error = ENOMEM; goto bad5; } sc->sc_rd_index = sc->sc_rd_count = 0; sc->sc_closing = 0; sc->sc_rd_readinprogress = 0; sc->sc_rd_expectdataticks = 0; sc->sc_ur_framelen = 0; sc->sc_rd_err = 0; sc->sc_wr_stalewrite = 0; sc->sc_direction = udir_idle; sc->sc_params.speed = 0; sc->sc_params.ebofs = 0; sc->sc_params.maxsize = min(sc->sc_rd_maxpsz, sc->sc_wr_maxpsz); deframe_init(&sc->sc_framestate, sc->sc_ur_buf, IRDA_MAX_FRAME_SIZE); /* Increment reference for thread */ sc->sc_refcnt++; error = kthread_create(PRI_NONE, 0, NULL, udsir_thread, sc, &sc->sc_thread, "%s", device_xname(sc->sc_dev)); if (error) { sc->sc_refcnt--; goto bad5; } return 0; bad5: usbd_free_xfer(sc->sc_wr_xfer); sc->sc_wr_xfer = NULL; bad4: usbd_free_xfer(sc->sc_rd_xfer); sc->sc_rd_xfer = NULL; bad3: usbd_close_pipe(sc->sc_wr_pipe); sc->sc_wr_pipe = NULL; bad2: usbd_close_pipe(sc->sc_rd_pipe); sc->sc_rd_pipe = NULL; bad1: return error; }
int uhidev_open(struct uhidev *scd) { struct uhidev_softc *sc = scd->sc_parent; usbd_status err; int error; DPRINTF(("uhidev_open: open pipe, state=%d refcnt=%d\n", scd->sc_state, sc->sc_refcnt)); if (scd->sc_state & UHIDEV_OPEN) return (EBUSY); scd->sc_state |= UHIDEV_OPEN; if (sc->sc_refcnt++) return (0); if (sc->sc_isize == 0) return (0); sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); /* Set up input interrupt pipe. */ DPRINTF(("uhidev_open: isize=%d, ep=0x%02x\n", sc->sc_isize, sc->sc_iep_addr)); err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep_addr, USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf, sc->sc_isize, uhidev_intr, USBD_DEFAULT_INTERVAL); if (err != USBD_NORMAL_COMPLETION) { DPRINTF(("uhidopen: usbd_open_pipe_intr failed, " "error=%d\n", err)); error = EIO; goto out1; } DPRINTF(("uhidev_open: sc->sc_ipipe=%p\n", sc->sc_ipipe)); sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_ixfer == NULL) { DPRINTF(("uhidev_open: couldn't allocate an xfer\n")); error = ENOMEM; goto out1; // xxxx } /* * Set up output interrupt pipe if an output interrupt endpoint * exists. */ if (sc->sc_oep_addr != -1) { DPRINTF(("uhidev_open: oep=0x%02x\n", sc->sc_oep_addr)); err = usbd_open_pipe(sc->sc_iface, sc->sc_oep_addr, 0, &sc->sc_opipe); if (err != USBD_NORMAL_COMPLETION) { DPRINTF(("uhidev_open: usbd_open_pipe failed, " "error=%d\n", err)); error = EIO; goto out2; } DPRINTF(("uhidev_open: sc->sc_opipe=%p\n", sc->sc_opipe)); sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_oxfer == NULL) { DPRINTF(("uhidev_open: couldn't allocate an xfer\n")); error = ENOMEM; goto out3; } sc->sc_owxfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_owxfer == NULL) { DPRINTF(("uhidev_open: couldn't allocate owxfer\n")); error = ENOMEM; goto out3; } } return (0); out3: /* Abort output pipe */ usbd_close_pipe(sc->sc_opipe); out2: /* Abort input pipe */ usbd_close_pipe(sc->sc_ipipe); out1: DPRINTF(("uhidev_open: failed in someway")); free(sc->sc_ibuf, M_USBDEV); scd->sc_state &= ~UHIDEV_OPEN; sc->sc_refcnt = 0; sc->sc_ipipe = NULL; sc->sc_opipe = NULL; if (sc->sc_oxfer != NULL) { usbd_free_xfer(sc->sc_oxfer); sc->sc_oxfer = NULL; } if (sc->sc_owxfer != NULL) { usbd_free_xfer(sc->sc_owxfer); sc->sc_owxfer = NULL; } return (error); }
int ucomopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = UCOMUNIT(dev); usbd_status err; struct ucom_softc *sc; struct tty *tp; struct termios t; int s; int error; if (unit >= ucom_cd.cd_ndevs) return (ENXIO); sc = ucom_cd.cd_devs[unit]; if (sc == NULL) return (ENXIO); if (sc->sc_dying) return (EIO); if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) return (ENXIO); /* open the pipes if this is the first open */ ucom_lock(sc); if (sc->sc_open++ == 0) { s = splusb(); DPRINTF(("ucomopen: open pipes in=%d out=%d\n", sc->sc_bulkin_no, sc->sc_bulkout_no)); DPRINTF(("ucomopen: hid %p pipes in=%p out=%p\n", sc->sc_uhidev, sc->sc_ipipe, sc->sc_opipe)); if (sc->sc_bulkin_no != -1) { /* Open the bulk pipes */ err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0, &sc->sc_bulkin_pipe); if (err) { DPRINTF(("%s: open bulk out error (addr %d), err=%s\n", sc->sc_dev.dv_xname, sc->sc_bulkin_no, usbd_errstr(err))); error = EIO; goto fail_0; } err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); if (err) { DPRINTF(("%s: open bulk in error (addr %d), err=%s\n", sc->sc_dev.dv_xname, sc->sc_bulkout_no, usbd_errstr(err))); error = EIO; goto fail_1; } /* Allocate a request and an input buffer and start reading. */ sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_ixfer == NULL) { error = ENOMEM; goto fail_2; } sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer, sc->sc_ibufsizepad); if (sc->sc_ibuf == NULL) { error = ENOMEM; goto fail_2; } sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_oxfer == NULL) { error = ENOMEM; goto fail_3; } } else { /* * input/output pipes and xfers already allocated * as is the input buffer. */ sc->sc_ipipe = sc->sc_uhidev->sc_ipipe; sc->sc_ixfer = sc->sc_uhidev->sc_ixfer; sc->sc_opipe = sc->sc_uhidev->sc_opipe; sc->sc_oxfer = sc->sc_uhidev->sc_oxfer; } sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer, sc->sc_obufsize + sc->sc_opkthdrlen); if (sc->sc_obuf == NULL) { error = ENOMEM; goto fail_4; } if (sc->sc_methods->ucom_open != NULL) { error = sc->sc_methods->ucom_open(sc->sc_parent, sc->sc_portno); if (error) { ucom_cleanup(sc); splx(s); ucom_unlock(sc); return (error); } } ucom_status_change(sc); ucomstartread(sc); splx(s); } ucom_unlock(sc); s = spltty(); tp = sc->sc_tty; splx(s); DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp)); tp->t_dev = dev; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_WOPEN); ttychars(tp); /* * Initialize the termios status to the defaults. Add in the * sticky bits from TIOCSFLAGS. */ t.c_ispeed = 0; t.c_ospeed = TTYDEF_SPEED; t.c_cflag = TTYDEF_CFLAG; if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) SET(t.c_cflag, CLOCAL); if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) SET(t.c_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) SET(t.c_cflag, MDMBUF); /* Make sure ucomparam() will do something. */ tp->t_ospeed = 0; (void) ucomparam(tp, &t); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; s = spltty(); ttsetwater(tp); /* * Turn on DTR. We must always do this, even if carrier is not * present, because otherwise we'd have to use TIOCSDTR * immediately after setting CLOCAL, which applications do not * expect. We always assert DTR while the device is open * unless explicitly requested to deassert it. */ ucom_dtr(sc, 1); /* XXX CLR(sc->sc_rx_flags, RX_ANY_BLOCK);*/ ucom_hwiflow(sc); if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || UCOMCUA(dev) || ISSET(sc->sc_msr, UMSR_DCD) || ISSET(tp->t_cflag, MDMBUF)) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) { error = EBUSY; goto bad; } else s = spltty(); if (UCOMCUA(dev)) { if (ISSET(tp->t_state, TS_ISOPEN)) { /* Someone is already dialed in */ error = EBUSY; goto bad1; } sc->sc_cua = 1; } else { /* tty (not cua) device, wait for carrier */ if (ISSET(flag, O_NONBLOCK)) { if (sc->sc_cua) { error = EBUSY; goto bad1; } } else { while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON))) { SET(tp->t_state, TS_WOPEN); error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); /* * If TS_WOPEN has been reset, that means the * cua device has been closed. We don't want * to fail in that case, so just go around * again. */ if (error && ISSET(tp->t_state, TS_WOPEN)) { CLR(tp->t_state, TS_WOPEN); goto bad1; } } } } splx(s); error = ttyopen(UCOMUNIT(dev), tp); if (error) goto bad; error = (*LINESW(tp, l_open))(dev, tp); if (error) goto bad; return (0); fail_4: if (sc->sc_uhidev == NULL) usbd_free_xfer(sc->sc_oxfer); sc->sc_oxfer = NULL; fail_3: usbd_free_xfer(sc->sc_ixfer); sc->sc_ixfer = NULL; fail_2: usbd_close_pipe(sc->sc_bulkout_pipe); sc->sc_bulkout_pipe = NULL; fail_1: usbd_close_pipe(sc->sc_bulkin_pipe); sc->sc_bulkin_pipe = NULL; fail_0: splx(s); ucom_unlock(sc); return (error); bad1: splx(s); bad: ucom_lock(sc); ucom_cleanup(sc); ucom_unlock(sc); return (error); }
/* * Init */ static void lgue_init(void *xsc) { struct lgue_softc *sc; struct ifnet *ifp; usbd_status err; sc = xsc; ifp = &sc->lgue_arpcom.ac_if; if (ifp->if_flags & IFF_RUNNING) return; /* Create RX and TX bufs */ if (sc->lgue_tx_xfer == NULL) { sc->lgue_tx_xfer = usbd_alloc_xfer(sc->lgue_udev); if (sc->lgue_tx_xfer == NULL) { if_printf(ifp, "tx buffer allocate failed\n"); return; } } sc->lgue_tx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK); if (sc->lgue_rx_xfer == NULL) { sc->lgue_rx_xfer = usbd_alloc_xfer(sc->lgue_udev); if (sc->lgue_rx_xfer == NULL) { if_printf(ifp, "rx buffer allocate failed\n"); return; } } sc->lgue_rx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK); /* Create INTR buf */ if (sc->lgue_intr_xfer == NULL) { sc->lgue_intr_xfer = usbd_alloc_xfer(sc->lgue_udev); if (sc->lgue_intr_xfer == NULL) { if_printf(ifp, "intr buffer allocate failed\n"); return; } } sc->lgue_intr_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK); /* Open RX and TX pipes. */ err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_RX], USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_RX]); if (err) { if_printf(ifp, "open RX pipe failed: %s\n", usbd_errstr(err)); return; } err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_TX], USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_TX]); if (err) { if_printf(ifp, "open TX pipe failed: %s\n", usbd_errstr(err)); return; } /* Open INTR pipe. */ err = usbd_open_pipe(sc->lgue_ctl_iface, sc->lgue_ed[LGUE_ENDPT_INTR], USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_INTR]); if (err) { if_printf(ifp, "open INTR pipe failed: %s\n", usbd_errstr(err)); return; } /* Create internal queue */ STAILQ_INIT(&sc->lgue_tx_queue); ifp->if_flags |= IFF_RUNNING; ifq_clr_oactive(&ifp->if_snd); sc->lgue_dying = 0; lgue_rxstart(ifp); lgue_intrstart(ifp); }
int ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) { struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT]; u_int32_t n; int flags, error = 0; char buf[UGEN_BBSIZE]; struct usbd_xfer *xfer; usbd_status err; DPRINTFN(5, ("%s: ugenwrite: %d\n", sc->sc_dev.dv_xname, endpt)); if (usbd_is_dying(sc->sc_udev)) return (EIO); if (endpt == USB_CONTROL_ENDPOINT) return (ENODEV); #ifdef DIAGNOSTIC if (sce->edesc == NULL) { printf("ugenwrite: no edesc\n"); return (EIO); } if (sce->pipeh == NULL) { printf("ugenwrite: no pipe\n"); return (EIO); } #endif flags = USBD_SYNCHRONOUS; if (sce->timeout == 0) flags |= USBD_CATCH; switch (sce->edesc->bmAttributes & UE_XFERTYPE) { case UE_BULK: xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == 0) return (EIO); while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { error = uiomove(buf, n, uio); if (error) break; DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n, flags, sce->timeout, NULL); err = usbd_transfer(xfer); if (err) { usbd_clear_endpoint_stall(sce->pipeh); if (err == USBD_INTERRUPTED) error = EINTR; else if (err == USBD_TIMEOUT) error = ETIMEDOUT; else error = EIO; break; } } usbd_free_xfer(xfer); break; case UE_INTERRUPT: xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == 0) return (EIO); while ((n = min(UGETW(sce->edesc->wMaxPacketSize), uio->uio_resid)) != 0) { error = uiomove(buf, n, uio); if (error) break; DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n, flags, sce->timeout, NULL); err = usbd_transfer(xfer); if (err) { usbd_clear_endpoint_stall(sce->pipeh); if (err == USBD_INTERRUPTED) error = EINTR; else if (err == USBD_TIMEOUT) error = ETIMEDOUT; else error = EIO; break; } } usbd_free_xfer(xfer); break; default: return (ENXIO); } return (error); }
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; }
static int uticom_download_fw(struct uticom_softc *sc, int pipeno, struct usbd_device *dev) { u_char *obuf, *firmware; size_t firmware_size; int buffer_size, pos; uint8_t cs = 0, *buffer; usbd_status err; struct uticom_fw_header *header; struct usbd_xfer *oxfer = 0; usbd_status error = 0; struct usbd_pipe *pipe; error = loadfirmware("tusb3410", &firmware, &firmware_size); if (error) return (error); buffer_size = UTICOM_FW_BUFSZ + sizeof(struct uticom_fw_header); buffer = malloc(buffer_size, M_USBDEV, M_WAITOK | M_CANFAIL); if (!buffer) { printf("%s: uticom_download_fw: out of memory\n", sc->sc_dev.dv_xname); free(firmware, M_DEVBUF); return ENOMEM; } memcpy(buffer, firmware, firmware_size); memset(buffer + firmware_size, 0xff, buffer_size - firmware_size); for (pos = sizeof(struct uticom_fw_header); pos < buffer_size; pos++) cs = (uint8_t)(cs + buffer[pos]); header = (struct uticom_fw_header*)buffer; header->length = (uint16_t)(buffer_size - sizeof(struct uticom_fw_header)); header->checkSum = cs; DPRINTF(("%s: downloading firmware ...\n", sc->sc_dev.dv_xname)); err = usbd_open_pipe(sc->sc_iface, pipeno, USBD_EXCLUSIVE_USE, &pipe); if (err) { printf("%s: open bulk out error (addr %d): %s\n", sc->sc_dev.dv_xname, pipeno, usbd_errstr(err)); error = EIO; goto finish; } oxfer = usbd_alloc_xfer(dev); if (oxfer == NULL) { error = ENOMEM; goto finish; } obuf = usbd_alloc_buffer(oxfer, buffer_size); if (obuf == NULL) { error = ENOMEM; goto finish; } memcpy(obuf, buffer, buffer_size); usbd_setup_xfer(oxfer, pipe, (void *)sc, obuf, buffer_size, USBD_NO_COPY | USBD_SYNCHRONOUS, USBD_NO_TIMEOUT, 0); err = usbd_transfer(oxfer); if (err != USBD_NORMAL_COMPLETION) printf("%s: uticom_download_fw: error: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); finish: free(firmware, M_DEVBUF); usbd_free_buffer(oxfer); usbd_free_xfer(oxfer); oxfer = NULL; usbd_abort_pipe(pipe); usbd_close_pipe(pipe); free(buffer, M_USBDEV); return err; }
int uscanneropen(dev_t dev, int flag, int mode, struct lwp *l) { struct uscanner_softc *sc; int unit = USCANNERUNIT(dev); usbd_status err; sc = device_lookup_private(&uscanner_cd, unit); if (sc == NULL) return ENXIO; DPRINTFN(5, ("uscanneropen: flag=%d, mode=%d, unit=%d\n", flag, mode, unit)); if (sc->sc_dying) return (ENXIO); if (sc->sc_state & USCANNER_OPEN) return (EBUSY); sc->sc_state |= USCANNER_OPEN; sc->sc_bulkin_buffer = malloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK); sc->sc_bulkout_buffer = malloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK); /* No need to check buffers for NULL since we have WAITOK */ sc->sc_bulkin_bufferlen = USCANNER_BUFFERSIZE; sc->sc_bulkout_bufferlen = USCANNER_BUFFERSIZE; /* We have decided on which endpoints to use, now open the pipes */ if (sc->sc_bulkin_pipe == NULL) { err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin, USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe); if (err) { printf("%s: cannot open bulk-in pipe (addr %d)\n", device_xname(sc->sc_dev), sc->sc_bulkin); uscanner_do_close(sc); return (EIO); } } if (sc->sc_bulkout_pipe == NULL) { err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout, USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); if (err) { printf("%s: cannot open bulk-out pipe (addr %d)\n", device_xname(sc->sc_dev), sc->sc_bulkout); uscanner_do_close(sc); return (EIO); } } sc->sc_bulkin_xfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_bulkin_xfer == NULL) { uscanner_do_close(sc); return (ENOMEM); } sc->sc_bulkout_xfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_bulkout_xfer == NULL) { uscanner_do_close(sc); return (ENOMEM); } return (0); /* success */ }
static int ufoma_attach(device_t self) { struct ufoma_softc *sc = device_get_softc(self); struct usb_attach_arg *uaa = device_get_ivars(self); usbd_device_handle dev = uaa->device; usb_config_descriptor_t *cd; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usb_mcpc_acm_descriptor *mad; struct ucom_softc *ucom = &sc->sc_ucom; const char *devname,*modename; int ctl_notify; int i,err; int elements; uByte *mode; struct sysctl_ctx_list *sctx; struct sysctl_oid *soid; ucom->sc_dev = self; ucom->sc_udev = dev; sc->sc_ctl_iface = uaa->iface; mtx_init(&sc->sc_mtx, "ufoma", NULL, MTX_DEF); cd = usbd_get_config_descriptor(ucom->sc_udev); id = usbd_get_interface_descriptor(sc->sc_ctl_iface); sc->sc_ctl_iface_no = id->bInterfaceNumber; devname = device_get_nameunit(self); device_printf(self, "iclass %d/%d ifno:%d\n", id->bInterfaceClass, id->bInterfaceSubClass, sc->sc_ctl_iface_no); ctl_notify = -1; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i); if (ed == NULL) continue; if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { ctl_notify = ed->bEndpointAddress; } } if(ctl_notify== -1){ /*NOTIFY is mandatory.*/ printf("NOTIFY interface not found\n"); goto error; } err = usbd_open_pipe_intr(sc->sc_ctl_iface, ctl_notify, USBD_SHORT_XFER_OK, &sc->sc_notify_pipe, sc, &sc->sc_notify_buf, sizeof(sc->sc_notify_buf), ufoma_intr, USBD_DEFAULT_INTERVAL); if(err){ printf("PIPE open error %d\n", err); goto error; } mad = ufoma_get_intconf(cd, id , UDESC_VS_INTERFACE, UDESCSUB_MCPC_ACM); if(mad ==NULL){ goto error; } printf("%s:Supported Mode:", devname); for(mode = mad->bMode; mode < ((uByte *)mad + mad->bFunctionLength); mode++){ modename = ufoma_mode_to_str(*mode); if(modename){ printf("%s", ufoma_mode_to_str(*mode)); }else{ printf("(%x)", *mode); } if(mode != ((uByte*)mad + mad->bFunctionLength-1)){ printf(","); } } printf("\n"); if((mad->bType == UMCPC_ACM_TYPE_AB5) ||(mad->bType == UMCPC_ACM_TYPE_AB6)){ /*These does not have data interface*/ sc->sc_is_ucom = 0; ufoma_init_pseudo_ucom(sc); }else{ if(ufoma_init_modem(sc, uaa)){ goto error; } } elements = mad->bFunctionLength - sizeof(*mad)+1; sc->sc_msgxf = usbd_alloc_xfer(ucom->sc_udev); sc->sc_nummsg = 0; /*Initialize Mode vars.*/ sc->sc_modetable = malloc(elements + 1, M_USBDEV, M_WAITOK); sc->sc_modetable[0] = elements + 1; bcopy(mad->bMode, &sc->sc_modetable[1], elements); sc->sc_currentmode = UMCPC_ACM_MODE_UNLINKED; sc->sc_modetoactivate = mad->bMode[0]; /*Sysctls*/ sctx = device_get_sysctl_ctx(self); soid = device_get_sysctl_tree(self); SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "supportmode", CTLFLAG_RD|CTLTYPE_STRING, sc, 0, ufoma_sysctl_support, "A", "Supporting port role"); SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "currentmode", CTLFLAG_RD|CTLTYPE_STRING, sc, 0, ufoma_sysctl_current, "A", "Current port role"); SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "openmode", CTLFLAG_RW|CTLTYPE_STRING, sc, 0, ufoma_sysctl_open, "A", "Mode to transit when port is opened"); return 0; error: if(sc->sc_modetable) free(sc->sc_modetable, M_USBDEV); return EIO; }