Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
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);
}
Ejemplo n.º 8
0
Archivo: umidi.c Proyecto: bluhm/sys
/* 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;
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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);
}
Ejemplo n.º 11
0
/* 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;
}
Ejemplo n.º 12
0
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);
}
Ejemplo n.º 13
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);
}
Ejemplo n.º 14
0
int
ugenopen(dev_t dev, int flag, int mode, struct proc *p)
{
	struct ugen_softc *sc;
	int unit = UGENUNIT(dev);
	int endpt = UGENENDPOINT(dev);
	usb_endpoint_descriptor_t *edesc;
	struct ugen_endpoint *sce;
	int dir, isize;
	usbd_status err;
	struct usbd_xfer *xfer;
	void *buf;
	int i, j;

	if (unit >= ugen_cd.cd_ndevs)
		return (ENXIO);
	sc = ugen_cd.cd_devs[unit];
	if (sc == NULL)
		return (ENXIO);

	DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
		     flag, mode, unit, endpt));

	if (sc == NULL || usbd_is_dying(sc->sc_udev))
		return (ENXIO);

	if (sc->sc_is_open[endpt])
		return (EBUSY);

	if (endpt == USB_CONTROL_ENDPOINT) {
		sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
		return (0);
	}

	/* Make sure there are pipes for all directions. */
	for (dir = OUT; dir <= IN; dir++) {
		if (flag & (dir == OUT ? FWRITE : FREAD)) {
			sce = &sc->sc_endpoints[endpt][dir];
			if (sce == 0 || sce->edesc == 0)
				return (ENXIO);
		}
	}

	/* Actually open the pipes. */
	/* XXX Should back out properly if it fails. */
	for (dir = OUT; dir <= IN; dir++) {
		if (!(flag & (dir == OUT ? FWRITE : FREAD)))
			continue;
		sce = &sc->sc_endpoints[endpt][dir];
		sce->state = 0;
		sce->timeout = USBD_NO_TIMEOUT;
		DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
			     sc, endpt, dir, sce));
		edesc = sce->edesc;
		switch (edesc->bmAttributes & UE_XFERTYPE) {
		case UE_INTERRUPT:
			if (dir == OUT) {
				err = usbd_open_pipe(sce->iface,
				    edesc->bEndpointAddress, 0, &sce->pipeh);
				if (err)
					return (EIO);
				break;
			}
			isize = UGETW(edesc->wMaxPacketSize);
			if (isize == 0)	/* shouldn't happen */
				return (EINVAL);
			sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK);
			DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
				     endpt, isize));
			clalloc(&sce->q, UGEN_IBSIZE, 0);
			err = usbd_open_pipe_intr(sce->iface,
				  edesc->bEndpointAddress,
				  USBD_SHORT_XFER_OK, &sce->pipeh, sce,
				  sce->ibuf, isize, ugenintr,
				  USBD_DEFAULT_INTERVAL);
			if (err) {
				free(sce->ibuf, M_USBDEV, 0);
				clfree(&sce->q);
				return (EIO);
			}
			DPRINTFN(5, ("ugenopen: interrupt open done\n"));
			break;
		case UE_BULK:
			err = usbd_open_pipe(sce->iface,
				  edesc->bEndpointAddress, 0, &sce->pipeh);
			if (err)
				return (EIO);
			break;
		case UE_ISOCHRONOUS:
			if (dir == OUT)
				return (EINVAL);
			isize = UGETW(edesc->wMaxPacketSize);
			if (isize == 0)	/* shouldn't happen */
				return (EINVAL);
			sce->ibuf = malloc(isize * UGEN_NISOFRAMES,
				M_USBDEV, M_WAITOK);
			sce->cur = sce->fill = sce->ibuf;
			sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES;
			DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n",
				     endpt, isize));
			err = usbd_open_pipe(sce->iface,
				  edesc->bEndpointAddress, 0, &sce->pipeh);
			if (err) {
				free(sce->ibuf, M_USBDEV, 0);
				return (EIO);
			}
			for(i = 0; i < UGEN_NISOREQS; ++i) {
				sce->isoreqs[i].sce = sce;
				xfer = usbd_alloc_xfer(sc->sc_udev);
				if (xfer == 0)
					goto bad;
				sce->isoreqs[i].xfer = xfer;
				buf = usbd_alloc_buffer
					(xfer, isize * UGEN_NISORFRMS);
				if (buf == 0) {
					i++;
					goto bad;
				}
				sce->isoreqs[i].dmabuf = buf;
				for(j = 0; j < UGEN_NISORFRMS; ++j)
					sce->isoreqs[i].sizes[j] = isize;
				usbd_setup_isoc_xfer
					(xfer, sce->pipeh, &sce->isoreqs[i],
					 sce->isoreqs[i].sizes,
					 UGEN_NISORFRMS, USBD_NO_COPY,
					 ugen_isoc_rintr);
				(void)usbd_transfer(xfer);
			}
			DPRINTFN(5, ("ugenopen: isoc open done\n"));
			break;
		bad:
			while (--i >= 0) /* implicit buffer free */
				usbd_free_xfer(sce->isoreqs[i].xfer);
			return (ENOMEM);
		case UE_CONTROL:
			sce->timeout = USBD_DEFAULT_TIMEOUT;
			return (EINVAL);
		}
	}
	sc->sc_is_open[endpt] = 1;
	return (0);
}
Ejemplo n.º 15
0
Static int
ucomopen(dev_t dev, int flag, int mode, usb_proc_ptr p)
{
	int unit = UCOMUNIT(dev);
	struct ucom_softc *sc;
	usbd_status err;
	struct tty *tp;
	int s;
	int error;

	USB_GET_SC_OPEN(ucom, unit, sc);

	if (sc->sc_dying)
		return (ENXIO);

	tp = sc->sc_tty;

	DPRINTF(("%s: ucomopen: tp = %p\n", USBDEVNAME(sc->sc_dev), tp));

	if (ISSET(tp->t_state, TS_ISOPEN) &&
	    ISSET(tp->t_state, TS_XCLUDE) &&
	    suser(p))
		return (EBUSY);

	/*
	 * Do the following iff this is a first open.
	 */
	s = spltty();
	while (sc->sc_opening)
		tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0);
	sc->sc_opening = 1;

	if (!ISSET(tp->t_state, TS_ISOPEN)) {
		struct termios t;

		sc->sc_poll = 0;
		sc->sc_lsr = sc->sc_msr = sc->sc_mcr = 0;

		tp->t_dev = dev;

		/*
		 * 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;
		/* 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.
		 */
		(void)ucomctl(sc, TIOCM_DTR | TIOCM_RTS, DMBIS);

		/* Device specific open */
		if (sc->sc_callback->ucom_open != NULL) {
			error = sc->sc_callback->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);
			}
		}

		DPRINTF(("ucomopen: open pipes in = %d out = %d\n",
			 sc->sc_bulkin_no, sc->sc_bulkout_no));

		/* Open the bulk pipes */
		/* Bulk-in pipe */
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0,
				     &sc->sc_bulkin_pipe);
		if (err) {
			printf("%s: open bulk in error (addr %d): %s\n",
			       USBDEVNAME(sc->sc_dev), sc->sc_bulkin_no,
			       usbd_errstr(err));
			error = EIO;
			goto fail_0;
		}
		/* Bulk-out pipe */
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
				     USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
		if (err) {
			printf("%s: open bulk out error (addr %d): %s\n",
			       USBDEVNAME(sc->sc_dev), 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_3;
		}

		sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev);
		if (sc->sc_oxfer == NULL) {
			error = ENOMEM;
			goto fail_3;
		}

		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;
		}

		/*
		 * Handle initial DCD.
		 */
		if (ISSET(sc->sc_msr, UMSR_DCD) ||
		    (minor(dev) & UCOM_CALLOUT_MASK))
			(*linesw[tp->t_line].l_modem)(tp, 1);

		ucomstartread(sc);
	}

	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);

	error = ttyopen(dev, tp);
	if (error)
		goto bad;

	error = (*linesw[tp->t_line].l_open)(dev, tp);
	if (error)
		goto bad;

	disc_optim(tp, &tp->t_termios, sc);

	DPRINTF(("%s: ucomopen: success\n", USBDEVNAME(sc->sc_dev)));

	sc->sc_poll = 1;
	sc->sc_refcnt++;

	return (0);

fail_4:
	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:
	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);
	return (error);

bad:
	if (!ISSET(tp->t_state, TS_ISOPEN)) {
		/*
		 * We failed to open the device, and nobody else had it opened.
		 * Clean up the state as appropriate.
		 */
		ucom_cleanup(sc);
	}

	DPRINTF(("%s: ucomopen: failed\n", USBDEVNAME(sc->sc_dev)));

	return (error);
}
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
0
/* 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;
}
Ejemplo n.º 18
0
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);
}
Ejemplo n.º 19
0
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);
}
Ejemplo n.º 20
0
int
uirda_set_params(void *h, struct irda_params *p)
{
	struct uirda_softc *sc = h;
	usbd_status err;
	int i;
	u_int8_t hdr;
	u_int32_t n;
	u_int mask;

	DPRINTF(("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", __func__,
		 sc, p->speed, p->ebofs, p->maxsize));

	if (sc->sc_dying)
		return (EIO);

	hdr = 0;
	if (p->ebofs != sc->sc_params.ebofs) {
		/* round up ebofs */
		mask = 1 /* sc->sc_irdadesc.bmAdditionalBOFs*/;
		DPRINTF(("u.s.p.: mask=0x%x, sc->ebofs=%d, p->ebofs=%d\n",
			mask, sc->sc_params.ebofs, p->ebofs));
		for (i = 0; i < UIRDA_NEBOFS; i++) {
			DPRINTF(("u.s.p.: u_e[%d].mask=0x%x, count=%d\n",
				i, uirda_ebofs[i].mask, uirda_ebofs[i].count));
			if ((mask & uirda_ebofs[i].mask) &&
			    uirda_ebofs[i].count >= p->ebofs) {
				hdr = uirda_ebofs[i].header;
				goto found1;
			}
		}
		for (i = 0; i < UIRDA_NEBOFS; i++) {
			DPRINTF(("u.s.p.: u_e[%d].mask=0x%x, count=%d\n",
				i, uirda_ebofs[i].mask, uirda_ebofs[i].count));
			if ((mask & uirda_ebofs[i].mask)) {
				hdr = uirda_ebofs[i].header;
				goto found1;
			}
		}
		/* no good value found */
		return (EINVAL);
	found1:
		DPRINTF(("uirda_set_params: ebofs hdr=0x%02x\n", hdr));
		;

	}
	if (hdr != 0 || p->speed != sc->sc_params.speed) {
		/* find speed */
		mask = UGETW(sc->sc_irdadesc.wBaudRate);
		for (i = 0; i < UIRDA_NSPEEDS; i++) {
			if ((mask & uirda_speeds[i].mask) &&
			    uirda_speeds[i].speed == p->speed) {
				hdr |= uirda_speeds[i].header;
				goto found2;
			}
		}
		/* no good value found */
		return (EINVAL);
	found2:
		DPRINTF(("uirda_set_params: speed hdr=0x%02x\n", hdr));
		;
	}
	if (p->maxsize != sc->sc_params.maxsize) {
		if (p->maxsize > IRDA_MAX_FRAME_SIZE)
			return (EINVAL);
		sc->sc_params.maxsize = p->maxsize;
#if 0
		DPRINTF(("%s: new buffers, old size=%d\n", __func__,
			 sc->sc_params.maxsize));
		if (p->maxsize > 10000 || p < 0) /* XXX */
			return (EINVAL);

		/* Change the write buffer */
		mutex_enter(&sc->sc_wr_buf_lk);
		if (sc->sc_wr_buf != NULL)
			usbd_free_buffer(sc->sc_wr_xfer);
		sc->sc_wr_buf = usbd_alloc_buffer(sc->sc_wr_xfer, p->maxsize+1);
		mutex_exit(&sc->sc_wr_buf_lk);
		if (sc->sc_wr_buf == NULL)
			return (ENOMEM);

		/* Change the read buffer */
		mutex_enter(&sc->sc_rd_buf_lk);
		usbd_abort_pipe(sc->sc_rd_pipe);
		if (sc->sc_rd_buf != NULL)
			usbd_free_buffer(sc->sc_rd_xfer);
		sc->sc_rd_buf = usbd_alloc_buffer(sc->sc_rd_xfer, p->maxsize+1);
		sc->sc_rd_count = 0;
		if (sc->sc_rd_buf == NULL) {
			mutex_exit(&sc->sc_rd_buf_lk);
			return (ENOMEM);
		}
		sc->sc_params.maxsize = p->maxsize;
		err = uirda_start_read(sc); /* XXX check */
		mutex_exit(&sc->sc_rd_buf_lk);
#endif
	}
	if (hdr != 0 && hdr != sc->sc_wr_hdr) {
		/*
		 * A change has occurred, transmit a 0 length frame with
		 * the new settings.  The 0 length frame is not sent to the
		 * device.
		 */
		DPRINTF(("%s: sc=%p setting header 0x%02x\n",
			 __func__, sc, hdr));
		sc->sc_wr_hdr = hdr;
		mutex_enter(&sc->sc_wr_buf_lk);
		sc->sc_wr_buf[0] = hdr;
		n = UIRDA_OUTPUT_HEADER_SIZE;
		err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe,
			  USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
			  UIRDA_WR_TIMEOUT, sc->sc_wr_buf, &n, "uirdast");
		if (err) {
			aprint_error_dev(sc->sc_dev, "set failed, err=%d\n",
			    err);
			usbd_clear_endpoint_stall(sc->sc_wr_pipe);
		}
		mutex_exit(&sc->sc_wr_buf_lk);
	}

	sc->sc_params = *p;

	return (0);
}
Ejemplo n.º 21
0
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;
		
}
Ejemplo n.º 22
0
/*******************************************************************************
 *
 * Bluetooth Unit/USB callbacks
 *
 * All of this will be called at the IPL_ we specified above
 */
int
ubt_enable(struct device *self)
{
	struct ubt_softc *sc = device_get_softc(self);
	usbd_status err;
	int i, error;

	DPRINTFN(1, "%s: sc=%p\n", __func__, sc);

	if (sc->sc_enabled)
		return 0;

	crit_enter();

	/* Events */
	sc->sc_evt_buf = kmalloc(UBT_BUFSIZ_EVENT, M_USBDEV, M_NOWAIT);
	if (sc->sc_evt_buf == NULL) {
		error = ENOMEM;
		goto bad;
	}

	err = usbd_open_pipe_intr(sc->sc_iface0,
				  sc->sc_evt_addr,
				  USBD_SHORT_XFER_OK,
				  &sc->sc_evt_pipe,
				  sc,
				  sc->sc_evt_buf,
				  UBT_BUFSIZ_EVENT,
				  ubt_recv_event,
				  UBT_INTR_TIMEOUT);
	if (err != USBD_NORMAL_COMPLETION) {
		error = EIO;
		kprintf("can't open events pipe_intr\n");
		goto bad;
	}

	/* Commands */
	sc->sc_cmd_xfer = usbd_alloc_xfer(sc->sc_udev);
	if (sc->sc_cmd_xfer == NULL) {
		kprintf("can't allocate cmd_xfer\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_cmd_buf = usbd_alloc_buffer(sc->sc_cmd_xfer, UBT_BUFSIZ_CMD);
	if (sc->sc_cmd_buf == NULL) {
		kprintf("can't allocate cmd_buf\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_cmd_busy = 0;

	/* ACL read */
	err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclrd_addr,
				USBD_EXCLUSIVE_USE, &sc->sc_aclrd_pipe);
	if (err != USBD_NORMAL_COMPLETION) {
		kprintf("can't open aclrd pipe\n");
		error = EIO;
		goto bad;
	}
	sc->sc_aclrd_xfer = usbd_alloc_xfer(sc->sc_udev);
	if (sc->sc_aclrd_xfer == NULL) {
		kprintf("can't allocate aclrd_xfer\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_aclrd_buf = usbd_alloc_buffer(sc->sc_aclrd_xfer, UBT_BUFSIZ_ACL);
	if (sc->sc_aclrd_buf == NULL) {
		kprintf("can't allocate aclrd_buf\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_aclrd_busy = 0;
	ubt_recv_acl_start(sc);

	/* ACL write */
	err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclwr_addr,
				USBD_EXCLUSIVE_USE, &sc->sc_aclwr_pipe);
	if (err != USBD_NORMAL_COMPLETION) {
		kprintf("can't open aclwr pipe\n");
		error = EIO;
		goto bad;
	}
	sc->sc_aclwr_xfer = usbd_alloc_xfer(sc->sc_udev);
	if (sc->sc_aclwr_xfer == NULL) {
		kprintf("can't allocate aclwr_xfer\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_aclwr_buf = usbd_alloc_buffer(sc->sc_aclwr_xfer, UBT_BUFSIZ_ACL);
	if (sc->sc_aclwr_buf == NULL) {
		kprintf("can't allocate aclwr_buf\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_aclwr_busy = 0;

	/* SCO read */
	if (sc->sc_scord_size > 0) {
		err = usbd_open_pipe(sc->sc_iface1, sc->sc_scord_addr,
					USBD_EXCLUSIVE_USE, &sc->sc_scord_pipe);
		if (err != USBD_NORMAL_COMPLETION) {
			error = EIO;
			goto bad;
		}

		for (i = 0 ; i < UBT_NXFERS ; i++) {
			sc->sc_scord[i].xfer = usbd_alloc_xfer(sc->sc_udev);
			if (sc->sc_scord[i].xfer == NULL) {
				error = ENOMEM;
				goto bad;
			}
			sc->sc_scord[i].buf = usbd_alloc_buffer(sc->sc_scord[i].xfer,
						sc->sc_scord_size * UBT_NFRAMES);
			if (sc->sc_scord[i].buf == NULL) {
				error = ENOMEM;
				goto bad;
			}
			sc->sc_scord[i].softc = sc;
			sc->sc_scord[i].busy = 0;
			ubt_recv_sco_start1(sc, &sc->sc_scord[i]);
		}
	}

	/* SCO write */
	if (sc->sc_scowr_size > 0) {
		err = usbd_open_pipe(sc->sc_iface1, sc->sc_scowr_addr,
					USBD_EXCLUSIVE_USE, &sc->sc_scowr_pipe);
		if (err != USBD_NORMAL_COMPLETION) {
			error = EIO;
			goto bad;
		}

		for (i = 0 ; i < UBT_NXFERS ; i++) {
			sc->sc_scowr[i].xfer = usbd_alloc_xfer(sc->sc_udev);
			if (sc->sc_scowr[i].xfer == NULL) {
				error = ENOMEM;
				goto bad;
			}
			sc->sc_scowr[i].buf = usbd_alloc_buffer(sc->sc_scowr[i].xfer,
						sc->sc_scowr_size * UBT_NFRAMES);
			if (sc->sc_scowr[i].buf == NULL) {
				error = ENOMEM;
				goto bad;
			}
			sc->sc_scowr[i].softc = sc;
			sc->sc_scowr[i].busy = 0;
		}

		sc->sc_scowr_busy = 0;
	}

	sc->sc_enabled = 1;
	crit_exit();
	return 0;

bad:
	ubt_abortdealloc(sc);
	crit_exit();
	return error;
}
Ejemplo n.º 23
0
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);
}
Ejemplo n.º 24
0
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);
}