Exemplo n.º 1
0
static void
usbd_task(device_object *dobj, void *arg)
{
	irp *ip;
	list_entry *l;
	struct ndis_softc *sc = arg;
	struct ndisusb_ep *ne;
	struct ndisusb_task *nt;
	union usbd_urb *urb;

	if (IsListEmpty(&sc->ndisusb_tasklist))
		return;

	KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock);
	l = sc->ndisusb_tasklist.nle_flink;
	while (l != &sc->ndisusb_tasklist) {
		nt = CONTAINING_RECORD(l, struct ndisusb_task, nt_tasklist);

		ip = nt->nt_ctx;
		urb = usbd_geturb(ip);

		KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock);
		NDISUSB_LOCK(sc);
		switch (nt->nt_type) {
		case NDISUSB_TASK_TSTART:
			ne = usbd_get_ndisep(ip, urb->uu_bulkintr.ubi_epdesc);
			if (ne == NULL)
				goto exit;
			usbd_transfer_start(ne->ne_xfer[0]);
			break;
		case NDISUSB_TASK_IRPCANCEL:
			ne = usbd_get_ndisep(ip,
			    (nt->nt_type == NDISUSB_TASK_IRPCANCEL) ?
			    urb->uu_bulkintr.ubi_epdesc :
			    urb->uu_pipe.upr_handle);
			if (ne == NULL)
				goto exit;
			
			usbd_transfer_stop(ne->ne_xfer[0]);
			usbd_transfer_start(ne->ne_xfer[0]);
			break;
		case NDISUSB_TASK_VENDOR:
			ne = (urb->uu_vcreq.uvc_trans_flags &
			    USBD_TRANSFER_DIRECTION_IN) ?
			    &sc->ndisusb_dread_ep : &sc->ndisusb_dwrite_ep;
			usbd_transfer_start(ne->ne_xfer[0]);
			break;
		default:
			break;
		}
exit:
		NDISUSB_UNLOCK(sc);
		KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock);

		l = l->nle_flink;
		RemoveEntryList(&nt->nt_tasklist);
		free(nt, M_USBDEV);
	}
	KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock);
}
Exemplo n.º 2
0
static void
cdce_init(struct usb_ether *ue)
{
	struct cdce_softc *sc = uether_getsc(ue);
	struct ifnet *ifp = uether_getifp(ue);

	CDCE_LOCK_ASSERT(sc, MA_OWNED);

	ifp->if_drv_flags |= IFF_DRV_RUNNING;

	/* start interrupt transfer */
	usbd_transfer_start(sc->sc_xfer[CDCE_INTR_RX]);
	usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]);

	/*
	 * Stall data write direction, which depends on USB mode.
	 *
	 * Some USB host stacks (e.g. Mac OS X) don't clears stall
	 * bit as it should, so set it in our host mode only.
	 */
	if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST)
		usbd_xfer_set_stall(sc->sc_xfer[CDCE_BULK_TX]);

	/* start data transfers */
	cdce_start(ue);
}
Exemplo n.º 3
0
static void
usie_if_init(void *arg)
{
	struct usie_softc *sc = arg;
	struct ifnet *ifp = sc->sc_ifp;
	uint8_t i;

	mtx_lock(&sc->sc_mtx);

	/* write tx descriptor */
	sc->sc_txd.hip.id = USIE_HIP_CTX;
	sc->sc_txd.hip.param = 0;	/* init value */
	sc->sc_txd.desc_type = htobe16(USIE_IP_TX);

	for (i = 0; i != USIE_IF_N_XFER; i++)
		usbd_xfer_set_stall(sc->sc_if_xfer[i]);

	usbd_transfer_start(sc->sc_uc_xfer[USIE_HIP_IF][USIE_UC_RX]);
	usbd_transfer_start(sc->sc_if_xfer[USIE_IF_STATUS]);
	usbd_transfer_start(sc->sc_if_xfer[USIE_IF_RX]);

	/* if not running, initiate the modem */
	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
		usie_cns_req(sc, USIE_CNS_ID_INIT, USIE_CNS_OB_LINK_UPDATE);

	mtx_unlock(&sc->sc_mtx);

	DPRINTF("ifnet initialized\n");
}
Exemplo n.º 4
0
static void
cdce_start(struct usb_ether *ue)
{
	struct cdce_softc *sc = uether_getsc(ue);

	/*
	 * Start the USB transfers, if not already started:
	 */
	usbd_transfer_start(sc->sc_xfer[CDCE_BULK_TX]);
	usbd_transfer_start(sc->sc_xfer[CDCE_BULK_RX]);
}
Exemplo n.º 5
0
static void
uhid_start_read(struct usb_fifo *fifo)
{
	struct uhid_softc *sc = usb_fifo_softc(fifo);

	if (sc->sc_flags & UHID_FLAG_IMMED) {
		usbd_transfer_start(sc->sc_xfer[UHID_CTRL_DT_RD]);
	} else {
		usbd_transfer_start(sc->sc_xfer[UHID_INTR_DT_RD]);
	}
}
static void
ugen_start_write(struct usb_fifo *f)
{
	/* check that pipes are open */
	if (ugen_open_pipe_write(f)) {
		/* signal error */
		usb_fifo_get_data_error(f);
	}
	/* start transfers */
	usbd_transfer_start(f->xfer[0]);
	usbd_transfer_start(f->xfer[1]);
}
Exemplo n.º 7
0
static void
uhid_start_write(struct usb_fifo *fifo)
{
	struct uhid_softc *sc = usb_fifo_softc(fifo);

	if ((sc->sc_flags & UHID_FLAG_IMMED) ||
	    sc->sc_xfer[UHID_INTR_DT_WR] == NULL) {
		usbd_transfer_start(sc->sc_xfer[UHID_CTRL_DT_WR]);
	} else {
		usbd_transfer_start(sc->sc_xfer[UHID_INTR_DT_WR]);
	}
}
static void
ugen_default_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
	struct usb_fifo *f = usbd_xfer_softc(xfer);
	struct usb_mbuf *m;

	DPRINTFN(4, "actlen=%u, aframes=%u\n", xfer->actlen, xfer->aframes);

	switch (USB_GET_STATE(xfer)) {
	case USB_ST_TRANSFERRED:
		if (xfer->actlen == 0) {
			if (f->fifo_zlp != 4) {
				f->fifo_zlp++;
			} else {
				/*
				 * Throttle a little bit we have multiple ZLPs
				 * in a row!
				 */
				xfer->interval = 64;	/* ms */
			}
		} else {
			/* clear throttle */
			xfer->interval = 0;
			f->fifo_zlp = 0;
		}
		usb_fifo_put_data(f, xfer->frbuffers, 0,
		    xfer->actlen, 1);

	case USB_ST_SETUP:
		if (f->flag_stall) {
			usbd_transfer_start(f->xfer[1]);
			break;
		}
		USB_IF_POLL(&f->free_q, m);
		if (m) {
			usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
			usbd_transfer_submit(xfer);
		}
		break;

	default:			/* Error */
		if (xfer->error != USB_ERR_CANCELLED) {
			/* send a zero length packet to userland */
			usb_fifo_put_data(f, xfer->frbuffers, 0, 0, 1);
			f->flag_stall = 1;
			f->fifo_zlp = 0;
			usbd_transfer_start(f->xfer[1]);
		}
		break;
	}
}
Exemplo n.º 9
0
static void
usbd_irpcancel(device_object *dobj, irp *ip)
{
	device_t dev = IRP_NDIS_DEV(ip);
	struct ndis_softc *sc = device_get_softc(dev);
	struct ndisusb_ep *ne = IRP_NDISUSB_EP(ip);

	if (ne == NULL) {
		ip->irp_cancel = TRUE;
		IoReleaseCancelSpinLock(ip->irp_cancelirql);
		return;
	}

	/*
	 * Make sure that the current USB transfer proxy is
	 * cancelled and then restarted.
	 */
	NDISUSB_LOCK(sc);
	usbd_transfer_stop(ne->ne_xfer[0]);
	usbd_transfer_start(ne->ne_xfer[0]);
	NDISUSB_UNLOCK(sc);

	ip->irp_cancel = TRUE;
	IoReleaseCancelSpinLock(ip->irp_cancelirql);
}
Exemplo n.º 10
0
static void
rtwn_usb_start_xfers(struct rtwn_softc *sc)
{
	struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc);

	usbd_transfer_start(uc->uc_xfer[RTWN_BULK_RX]);
}
Exemplo n.º 11
0
static void
usie_uc_start_write(struct ucom_softc *ucom)
{
	struct usie_softc *sc = ucom->sc_parent;

	usbd_transfer_start(sc->sc_uc_xfer[ucom->sc_subunit][USIE_UC_TX]);
}
Exemplo n.º 12
0
static int
cdce_handle_request(device_t dev,
    const void *preq, void **pptr, uint16_t *plen,
    uint16_t offset, uint8_t *pstate)
{
	struct cdce_softc *sc = device_get_softc(dev);
	const struct usb_device_request *req = preq;
	uint8_t is_complete = *pstate;

	/*
	 * When Mac OS X resumes after suspending it expects
	 * to be notified again after this request.
	 */
	if (req->bmRequestType == UT_WRITE_CLASS_INTERFACE && \
	    req->bRequest == UCDC_NCM_SET_ETHERNET_PACKET_FILTER) {

		if (is_complete == 1) {
			mtx_lock(&sc->sc_mtx);
			sc->sc_notify_state = CDCE_NOTIFY_SPEED_CHANGE;
			usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]);
			mtx_unlock(&sc->sc_mtx);
		}

		return (0);
	}

	return (ENXIO);			/* use builtin handler */
}
Exemplo n.º 13
0
static void
uhso_mux_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
	struct uhso_softc *sc = usbd_xfer_softc(xfer);
	struct usb_page_cache *pc;
	struct usb_device_request req;
	struct uhso_tty *ht;
	int actlen, len;

	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);

	UHSO_DPRINTF(3, "status %d\n", USB_GET_STATE(xfer));

	ht = usbd_xfer_get_priv(xfer);
	UHSO_DPRINTF(3, "ht=%p open=%d\n", ht, ht->ht_open);

	switch (USB_GET_STATE(xfer)) {
	case USB_ST_TRANSFERRED:
		/* Got data, send to ucom */
		pc = usbd_xfer_get_frame(xfer, 1);
		len = usbd_xfer_frame_len(xfer, 1);

		UHSO_DPRINTF(3, "got %d bytes on mux port %d\n", len,
		    ht->ht_muxport);
		if (len <= 0) {
			usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
			break;
		}

		/* Deliver data if the TTY is open, discard otherwise */
		if (ht->ht_open)
			ucom_put_data(&sc->sc_ucom[ht->ht_muxport], pc, 0, len);
		/* FALLTHROUGH */
	case USB_ST_SETUP:
tr_setup:
		memset(&req, 0, sizeof(struct usb_device_request));
		req.bmRequestType = UT_READ_CLASS_INTERFACE;
		req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE;
		USETW(req.wValue, 0);
		USETW(req.wIndex, ht->ht_muxport);
		USETW(req.wLength, 1024);

		pc = usbd_xfer_get_frame(xfer, 0);
		usbd_copy_in(pc, 0, &req, sizeof(req));

		usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
		usbd_xfer_set_frame_len(xfer, 1, 1024);
		usbd_xfer_set_frames(xfer, 2);
		usbd_transfer_submit(xfer);
		break;
	default:
		UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
		if (error == USB_ERR_CANCELLED)
			break;
		usbd_xfer_set_stall(xfer);
		goto tr_setup;
	}
}
Exemplo n.º 14
0
static void
usie_uc_cfg_open(struct ucom_softc *ucom)
{
	struct usie_softc *sc = ucom->sc_parent;

	/* usbd_transfer_start() is NULL safe */

	usbd_transfer_start(sc->sc_uc_xfer[ucom->sc_subunit][USIE_UC_STATUS]);
}
Exemplo n.º 15
0
static void
g_audio_timeout(void *arg)
{
	struct g_audio_softc *sc = arg;

	sc->sc_mode = g_audio_mode;

	memcpy(sc->sc_pattern, g_audio_pattern_data, sizeof(sc->sc_pattern));

	sc->sc_pattern[G_AUDIO_MAX_STRLEN - 1] = 0;

	sc->sc_pattern_len = strlen(sc->sc_pattern);

	if (sc->sc_mode != G_AUDIO_MODE_LOOP) {
		usbd_transfer_start(sc->sc_xfer[G_AUDIO_ISOC0_WR]);
		usbd_transfer_start(sc->sc_xfer[G_AUDIO_ISOC1_WR]);
	}
	g_audio_timeout_reset(sc);
}
Exemplo n.º 16
0
static void
uhso_ucom_start_read(struct ucom_softc *ucom)
{
	struct uhso_softc *sc = ucom->sc_parent;

	UHSO_DPRINTF(3, "unit=%d, subunit=%d\n",
	    ucom->sc_super->sc_unit, ucom->sc_subunit);

	if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
		sc->sc_tty[ucom->sc_subunit].ht_open = 1;
		usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
	}
	else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
		sc->sc_tty[0].ht_open = 1;
		usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_READ]);
		if (sc->sc_xfer[UHSO_BULK_ENDPT_INTR] != NULL)
			usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_INTR]);
	}
}
Exemplo n.º 17
0
static void
g_modem_timeout(void *arg)
{
	struct g_modem_softc *sc = arg;

	sc->sc_mode = g_modem_mode;

	memcpy(sc->sc_pattern, g_modem_pattern_data, sizeof(sc->sc_pattern));

	sc->sc_pattern[G_MODEM_MAX_STRLEN - 1] = 0;

	sc->sc_pattern_len = strlen(sc->sc_pattern);

	DPRINTFN(11, "Timeout %p\n", sc->sc_xfer[G_MODEM_INTR_DT]);

	usbd_transfer_start(sc->sc_xfer[G_MODEM_BULK_WR]);
	usbd_transfer_start(sc->sc_xfer[G_MODEM_BULK_RD]);

	g_modem_timeout_reset(sc);
}
Exemplo n.º 18
0
static void
cdce_init(struct usb_ether *ue)
{
	struct cdce_softc *sc = uether_getsc(ue);
	struct ifnet *ifp = uether_getifp(ue);

	CDCE_LOCK_ASSERT(sc, MA_OWNED);

	ifp->if_drv_flags |= IFF_DRV_RUNNING;

	/* start interrupt transfer */
	usbd_transfer_start(sc->sc_xfer[CDCE_INTR_RX]);
	usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]);

	/* stall data write direction, which depends on USB mode */
	usbd_xfer_set_stall(sc->sc_xfer[CDCE_BULK_TX]);

	/* start data transfers */
	cdce_start(ue);
}
Exemplo n.º 19
0
static void
uhso_ucom_start_write(struct ucom_softc *ucom)
{
	struct uhso_softc *sc = ucom->sc_parent;

	if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
		UHSO_DPRINTF(3, "local unit %d\n", ucom->sc_subunit);

		usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);

		usbd_xfer_set_priv(
		    sc->sc_tty[ucom->sc_subunit].ht_xfer[UHSO_CTRL_WRITE],
		    &sc->sc_tty[ucom->sc_subunit]);
		usbd_transfer_start(
		    sc->sc_tty[ucom->sc_subunit].ht_xfer[UHSO_CTRL_WRITE]);

	}
	else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
		usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_WRITE]);
	}
}
Exemplo n.º 20
0
/*
 * Interrupt callback for the multiplexed serial port. Indicates
 * which serial port has data waiting.
 */
static void
uhso_mux_intr_callback(struct usb_xfer *xfer, usb_error_t error)
{
	struct usb_page_cache *pc;
	struct usb_page_search res;
	struct uhso_softc *sc = usbd_xfer_softc(xfer);
	unsigned int i, mux;

	UHSO_DPRINTF(3, "status %d\n", USB_GET_STATE(xfer));

	switch (USB_GET_STATE(xfer)) {
	case USB_ST_TRANSFERRED:
		/*
		 * The multiplexed port number can be found at the first byte.
		 * It contains a bit mask, we transform this in to an integer.
		 */
		pc = usbd_xfer_get_frame(xfer, 0);
		usbd_get_page(pc, 0, &res);

		i = *((unsigned char *)res.buffer);
		mux = 0;
		while (i >>= 1) {
			mux++;
		}

		UHSO_DPRINTF(3, "mux port %d (%d)\n", mux, i);
		if (mux > UHSO_MPORT_TYPE_NOMAX)
			break;

		/* Issue a read for this serial port */
		usbd_xfer_set_priv(
		    sc->sc_tty[mux].ht_xfer[UHSO_CTRL_READ],
		    &sc->sc_tty[mux]);
		usbd_transfer_start(sc->sc_tty[mux].ht_xfer[UHSO_CTRL_READ]);

		break;
	case USB_ST_SETUP:
tr_setup:
		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
		usbd_transfer_submit(xfer);
		break;
	default:
		UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
		if (error == USB_ERR_CANCELLED)
			break;

		usbd_xfer_set_stall(xfer);
		goto tr_setup;
	}
}
Exemplo n.º 21
0
static void
ugen_default_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
	struct usb_fifo *f = usbd_xfer_softc(xfer);
	usb_frlength_t actlen;

	DPRINTFN(4, "actlen=%u, aframes=%u\n", xfer->actlen, xfer->aframes);

	switch (USB_GET_STATE(xfer)) {
	case USB_ST_SETUP:
	case USB_ST_TRANSFERRED:
		/*
		 * If writing is in stall, just jump to clear stall
		 * callback and solve the situation.
		 */
		if (f->flag_stall) {
			usbd_transfer_start(f->xfer[1]);
			break;
		}
		/*
		 * Write data, setup and perform hardware transfer.
		 */
		if (usb_fifo_get_data(f, xfer->frbuffers, 0,
		    xfer->max_data_length, &actlen, 0)) {
			usbd_xfer_set_frame_len(xfer, 0, actlen);
			usbd_transfer_submit(xfer);
		}
		break;

	default:			/* Error */
		if (xfer->error != USB_ERR_CANCELLED) {
			f->flag_stall = 1;
			usbd_transfer_start(f->xfer[1]);
		}
		break;
	}
}
Exemplo n.º 22
0
static void
usie_if_start(struct ifnet *ifp)
{
    struct usie_softc *sc = ifp->if_softc;

    if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
        DPRINTF("Not running\n");
        return;
    }
    mtx_lock(&sc->sc_mtx);
    usbd_transfer_start(sc->sc_if_xfer[USIE_IF_TX]);
    mtx_unlock(&sc->sc_mtx);

    DPRINTFN(3, "interface started\n");
}
Exemplo n.º 23
0
static void
ugen_write_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
{
	struct usb_fifo *f = usbd_xfer_softc(xfer);
	struct usb_xfer *xfer_other = f->xfer[0];

	if (f->flag_stall == 0) {
		/* nothing to do */
		return;
	}
	if (usbd_clear_stall_callback(xfer, xfer_other)) {
		DPRINTFN(5, "f=%p: stall cleared\n", f);
		f->flag_stall = 0;
		usbd_transfer_start(xfer_other);
	}
}
Exemplo n.º 24
0
static void
g_modem_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
	struct g_modem_softc *sc = usbd_xfer_softc(xfer);
	int actlen;
	int aframes;

	usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);

	DPRINTF("st=%d aframes=%d actlen=%d bytes\n",
	    USB_GET_STATE(xfer), aframes, actlen);

	switch (USB_GET_STATE(xfer)) {
	case USB_ST_TRANSFERRED:

		sc->sc_throughput += actlen;

		if (sc->sc_mode == G_MODEM_MODE_LOOP) {
			sc->sc_tx_busy = 1;
			sc->sc_data_len = actlen;
			usbd_transfer_start(sc->sc_xfer[G_MODEM_BULK_WR]);
			break;
		}

	case USB_ST_SETUP:
tr_setup:
		if ((sc->sc_mode == G_MODEM_MODE_SILENT) ||
		    (sc->sc_tx_busy != 0))
			break;

		usbd_xfer_set_frame_data(xfer, 0, sc->sc_data_buf, G_MODEM_BUFSIZE);
		usbd_xfer_set_frames(xfer, 1);
		usbd_transfer_submit(xfer);
		break;

	default:			/* Error */
		DPRINTF("error=%s\n", usbd_errstr(error));

		if (error != USB_ERR_CANCELLED) {
			/* try to clear stall first */
			usbd_xfer_set_stall(xfer);
			goto tr_setup;
		}
		break;
	}
}
Exemplo n.º 25
0
static void
uhso_ucom_stop_read(struct ucom_softc *ucom)
{

	struct uhso_softc *sc = ucom->sc_parent;

	if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
		sc->sc_tty[ucom->sc_subunit].ht_open = 0;
		usbd_transfer_stop(
		    sc->sc_tty[ucom->sc_subunit].ht_xfer[UHSO_CTRL_READ]);
	}
	else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
		sc->sc_tty[0].ht_open = 0;
		usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_READ]);
		if (sc->sc_xfer[UHSO_BULK_ENDPT_INTR] != NULL)
			usbd_transfer_stop(sc->sc_xfer[UHSO_BULK_ENDPT_INTR]);
	}
}
Exemplo n.º 26
0
static int32_t
usbd_func_abort_pipe(irp *ip)
{
	device_t dev = IRP_NDIS_DEV(ip);
	struct ndis_softc *sc = device_get_softc(dev);
	struct ndisusb_ep *ne;
	union usbd_urb *urb;

	urb = usbd_geturb(ip);
	ne = usbd_get_ndisep(ip, urb->uu_pipe.upr_handle);
	if (ne == NULL) {
		device_printf(IRP_NDIS_DEV(ip), "get NULL endpoint info.\n");
		return (USBD_STATUS_INVALID_PIPE_HANDLE);
	}

	NDISUSB_LOCK(sc);
	usbd_transfer_stop(ne->ne_xfer[0]);
	usbd_transfer_start(ne->ne_xfer[0]);
	NDISUSB_UNLOCK(sc);

	return (USBD_STATUS_SUCCESS);
}
Exemplo n.º 27
0
static int
ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
{
	struct usb_config usb_config[1];
	struct usb_device_request req;
	union {
		struct usb_fs_complete *pcomp;
		struct usb_fs_start *pstart;
		struct usb_fs_stop *pstop;
		struct usb_fs_open *popen;
		struct usb_fs_close *pclose;
		struct usb_fs_clear_stall_sync *pstall;
		void   *addr;
	}     u;
	struct usb_endpoint *ep;
	struct usb_endpoint_descriptor *ed;
	int error = 0;
	uint8_t iface_index;
	uint8_t isread;
	uint8_t ep_index;

	u.addr = addr;

	DPRINTFN(6, "cmd=0x%08lx\n", cmd);

	switch (cmd) {
	case USB_FS_COMPLETE:
		mtx_lock(f->priv_mtx);
		error = ugen_fs_get_complete(f, &ep_index);
		mtx_unlock(f->priv_mtx);

		if (error) {
			error = EBUSY;
			break;
		}
		u.pcomp->ep_index = ep_index;
		error = ugen_fs_copy_out(f, u.pcomp->ep_index);
		break;

	case USB_FS_START:
		error = ugen_fs_copy_in(f, u.pstart->ep_index);
		if (error) {
			break;
		}
		mtx_lock(f->priv_mtx);
		usbd_transfer_start(f->fs_xfer[u.pstart->ep_index]);
		mtx_unlock(f->priv_mtx);
		break;

	case USB_FS_STOP:
		if (u.pstop->ep_index >= f->fs_ep_max) {
			error = EINVAL;
			break;
		}
		mtx_lock(f->priv_mtx);
		usbd_transfer_stop(f->fs_xfer[u.pstop->ep_index]);
		mtx_unlock(f->priv_mtx);
		break;

	case USB_FS_OPEN:
		if (u.popen->ep_index >= f->fs_ep_max) {
			error = EINVAL;
			break;
		}
		if (f->fs_xfer[u.popen->ep_index] != NULL) {
			error = EBUSY;
			break;
		}
		if (u.popen->max_bufsize > USB_FS_MAX_BUFSIZE) {
			u.popen->max_bufsize = USB_FS_MAX_BUFSIZE;
		}
		if (u.popen->max_frames > USB_FS_MAX_FRAMES) {
			u.popen->max_frames = USB_FS_MAX_FRAMES;
			break;
		}
		if (u.popen->max_frames == 0) {
			error = EINVAL;
			break;
		}
		ep = usbd_get_ep_by_addr(f->udev, u.popen->ep_no);
		if (ep == NULL) {
			error = EINVAL;
			break;
		}
		ed = ep->edesc;
		if (ed == NULL) {
			error = ENXIO;
			break;
		}
		iface_index = ep->iface_index;

		bzero(usb_config, sizeof(usb_config));

		usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
		usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
		usb_config[0].direction = ed->bEndpointAddress & (UE_DIR_OUT | UE_DIR_IN);
		usb_config[0].interval = USB_DEFAULT_INTERVAL;
		usb_config[0].flags.proxy_buffer = 1;
		usb_config[0].callback = &ugen_default_fs_callback;
		usb_config[0].timeout = 0;	/* no timeout */
		usb_config[0].frames = u.popen->max_frames;
		usb_config[0].bufsize = u.popen->max_bufsize;
		usb_config[0].usb_mode = USB_MODE_DUAL;	/* both modes */

		if (usb_config[0].type == UE_CONTROL) {
			if (f->udev->flags.usb_mode != USB_MODE_HOST) {
				error = EINVAL;
				break;
			}
		} else {

			isread = ((usb_config[0].endpoint &
			    (UE_DIR_IN | UE_DIR_OUT)) == UE_DIR_IN);

			if (f->udev->flags.usb_mode != USB_MODE_HOST) {
				isread = !isread;
			}
			/* check permissions */
			if (isread) {
				if (!(fflags & FREAD)) {
					error = EPERM;
					break;
				}
			} else {
				if (!(fflags & FWRITE)) {
					error = EPERM;
					break;
				}
			}
		}
		error = usbd_transfer_setup(f->udev, &iface_index,
		    f->fs_xfer + u.popen->ep_index, usb_config, 1,
		    f, f->priv_mtx);
		if (error == 0) {
			/* update maximums */
			u.popen->max_packet_length =
			    f->fs_xfer[u.popen->ep_index]->max_frame_size;
			u.popen->max_bufsize =
			    f->fs_xfer[u.popen->ep_index]->max_data_length;
			f->fs_xfer[u.popen->ep_index]->priv_fifo =
			    ((uint8_t *)0) + u.popen->ep_index;
		} else {
			error = ENOMEM;
		}
		break;

	case USB_FS_CLOSE:
		if (u.pclose->ep_index >= f->fs_ep_max) {
			error = EINVAL;
			break;
		}
		if (f->fs_xfer[u.pclose->ep_index] == NULL) {
			error = EINVAL;
			break;
		}
		usbd_transfer_unsetup(f->fs_xfer + u.pclose->ep_index, 1);
		break;

	case USB_FS_CLEAR_STALL_SYNC:
		if (u.pstall->ep_index >= f->fs_ep_max) {
			error = EINVAL;
			break;
		}
		if (f->fs_xfer[u.pstall->ep_index] == NULL) {
			error = EINVAL;
			break;
		}
		if (f->udev->flags.usb_mode != USB_MODE_HOST) {
			error = EINVAL;
			break;
		}
		mtx_lock(f->priv_mtx);
		error = usbd_transfer_pending(f->fs_xfer[u.pstall->ep_index]);
		mtx_unlock(f->priv_mtx);

		if (error) {
			return (EBUSY);
		}
		ep = f->fs_xfer[u.pstall->ep_index]->endpoint;

		/* setup a clear-stall packet */
		req.bmRequestType = UT_WRITE_ENDPOINT;
		req.bRequest = UR_CLEAR_FEATURE;
		USETW(req.wValue, UF_ENDPOINT_HALT);
		req.wIndex[0] = ep->edesc->bEndpointAddress;
		req.wIndex[1] = 0;
		USETW(req.wLength, 0);

		error = usbd_do_request(f->udev, NULL, &req, NULL);
		if (error == 0) {
			usbd_clear_data_toggle(f->udev, ep);
		} else {
			error = ENXIO;
		}
		break;

	default:
		error = ENOIOCTL;
		break;
	}

	DPRINTFN(6, "error=%d\n", error);

	return (error);
}
Exemplo n.º 28
0
/*
 * Probes an interface for its particular capabilities and attaches if
 * it's a supported interface.
 */
static int
uhso_probe_iface(struct uhso_softc *sc, int index,
    int (*probe)(struct usb_device *, int))
{
	struct usb_interface *iface;
	int type, error;

	UHSO_DPRINTF(1, "Probing for interface %d, probe_func=%p\n", index, probe);

	type = probe(sc->sc_udev, index);
	UHSO_DPRINTF(1, "Probe result %x\n", type);
	if (type <= 0)
		return (ENXIO);

	sc->sc_type = type;
	iface = usbd_get_iface(sc->sc_udev, index);

	if (UHSO_IFACE_PORT_TYPE(type) == UHSO_PORT_TYPE_NETWORK) {
		error = uhso_attach_ifnet(sc, iface, type);
		if (error) {
			UHSO_DPRINTF(1, "uhso_attach_ifnet failed");
			return (ENXIO);
		}

		/*
		 * If there is an additional interrupt endpoint on this
		 * interface then we most likely have a multiplexed serial port
		 * available.
		 */
		if (iface->idesc->bNumEndpoints < 3) {
			sc->sc_type = UHSO_IFACE_SPEC( 
			    UHSO_IFACE_USB_TYPE(type) & ~UHSO_IF_MUX,
			    UHSO_IFACE_PORT(type) & ~UHSO_PORT_SERIAL,
			    UHSO_IFACE_PORT_TYPE(type));
			return (0);
		}

		UHSO_DPRINTF(1, "Trying to attach mux. serial\n");
		error = uhso_attach_muxserial(sc, iface, type);
		if (error == 0 && sc->sc_ttys > 0) {
			error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom,
			    sc->sc_ttys, sc, &uhso_ucom_callback, &sc->sc_mtx);
			if (error) {
				device_printf(sc->sc_dev, "ucom_attach failed\n");
				return (ENXIO);
			}
			ucom_set_pnpinfo_usb(&sc->sc_super_ucom, sc->sc_dev);

			mtx_lock(&sc->sc_mtx);
			usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
			mtx_unlock(&sc->sc_mtx);
		}
	} else if ((UHSO_IFACE_USB_TYPE(type) & UHSO_IF_BULK) &&
	    UHSO_IFACE_PORT(type) & UHSO_PORT_SERIAL) {

		error = uhso_attach_bulkserial(sc, iface, type);
		if (error)
			return (ENXIO);

		error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom,
		    sc->sc_ttys, sc, &uhso_ucom_callback, &sc->sc_mtx);
		if (error) {
			device_printf(sc->sc_dev, "ucom_attach failed\n");
			return (ENXIO);
		}
		ucom_set_pnpinfo_usb(&sc->sc_super_ucom, sc->sc_dev);
	}
	else {
		UHSO_DPRINTF(0, "Unknown type %x\n", type);
		return (ENXIO);
	}

	return (0);
}
Exemplo n.º 29
0
static void
usie_cns_req(struct usie_softc *sc, uint32_t id, uint16_t obj)
{
	struct ifnet *ifp = sc->sc_ifp;
	struct mbuf *m;
	struct usb_xfer *xfer;
	struct usie_hip *hip;
	struct usie_cns *cns;
	uint8_t *param;
	uint8_t *tmp;
	uint8_t cns_len;

	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
	if (__predict_false(m == NULL)) {
		DPRINTF("could not allocate mbuf\n");
		ifp->if_ierrors++;
		return;
	}
	/* to align usie_hip{} on 32 bit */
	m->m_data += 3;
	param = mtod(m, uint8_t *);
	*param++ = USIE_HIP_FRM_CHR;
	hip = (struct usie_hip *)param;
	cns = (struct usie_cns *)(hip + 1);

	tmp = param + USIE_HIPCNS_MIN - 2;

	switch (obj) {
	case USIE_CNS_OB_LINK_UPDATE:
		cns_len = 2;
		cns->op = USIE_CNS_OP_SET;
		*tmp++ = 1;		/* profile ID, always use 1 for now */
		*tmp++ = id == USIE_CNS_ID_INIT ? 1 : 0;
		break;

	case USIE_CNS_OB_PROF_WRITE:
		cns_len = 245;
		cns->op = USIE_CNS_OP_SET;
		*tmp++ = 1;		/* profile ID, always use 1 for now */
		*tmp++ = 2;
		memcpy(tmp, &sc->sc_net, 34);
		memset(tmp + 35, 0, 245 - 36);
		tmp += 243;
		break;

	case USIE_CNS_OB_RSSI:
		cns_len = 0;
		cns->op = USIE_CNS_OP_REQ;
		break;

	default:
		DPRINTF("unsupported CnS object type\n");
		return;
	}
	*tmp = USIE_HIP_FRM_CHR;

	hip->len = htobe16(sizeof(struct usie_cns) + cns_len);
	hip->id = USIE_HIP_CNS2M;
	hip->param = 0;			/* none for CnS */

	cns->obj = htobe16(obj);
	cns->id = htobe32(id);
	cns->len = cns_len;
	cns->rsv0 = cns->rsv1 = 0;	/* always '0' */

	param = (uint8_t *)(cns + 1);

	DPRINTF("param: %16D\n", param, ":");

	m->m_pkthdr.len = m->m_len = USIE_HIPCNS_MIN + cns_len + 2;

	xfer = sc->sc_uc_xfer[USIE_HIP_IF][USIE_UC_TX];

	if (usbd_xfer_get_priv(xfer) == NULL) {
		usbd_xfer_set_priv(xfer, m);
		usbd_transfer_start(xfer);
	} else {
		DPRINTF("Dropped CNS event\n");
		m_freem(m);
	}
}
Exemplo n.º 30
0
static void
g_modem_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
	struct g_modem_softc *sc = usbd_xfer_softc(xfer);
	int actlen;
	int aframes;
	int mod;
	int x;
	int max;

	usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);

	DPRINTF("st=%d aframes=%d actlen=%d bytes\n",
	    USB_GET_STATE(xfer), aframes, actlen);

	switch (USB_GET_STATE(xfer)) {
	case USB_ST_TRANSFERRED:

		sc->sc_tx_busy = 0;
		sc->sc_throughput += actlen;

		if (sc->sc_mode == G_MODEM_MODE_LOOP) {
			/* start loop */
			usbd_transfer_start(sc->sc_xfer[G_MODEM_BULK_RD]);
			break;
		} else if ((sc->sc_mode == G_MODEM_MODE_PATTERN) && (sc->sc_tx_interval != 0)) {
			/* wait for next timeout */
			break;
		}
	case USB_ST_SETUP:
tr_setup:
		if (sc->sc_mode == G_MODEM_MODE_PATTERN) {

			mod = sc->sc_pattern_len;
			max = sc->sc_tx_interval ? mod : G_MODEM_BUFSIZE;

			if (mod == 0) {
				for (x = 0; x != max; x++)
					sc->sc_data_buf[x] = x % 255;
			} else {
				for (x = 0; x != max; x++)
					sc->sc_data_buf[x] = sc->sc_pattern[x % mod];
			}

			usbd_xfer_set_frame_data(xfer, 0, sc->sc_data_buf, max);
			usbd_xfer_set_interval(xfer, 0);
			usbd_xfer_set_frames(xfer, 1);
			usbd_transfer_submit(xfer);

		} else if (sc->sc_mode == G_MODEM_MODE_LOOP) {

			if (sc->sc_tx_busy == 0)
				break;

			x = sc->sc_tx_interval;

			if (x < 0)
				x = 0;
			else if (x > 256)
				x = 256;

			usbd_xfer_set_frame_data(xfer, 0, sc->sc_data_buf, sc->sc_data_len);
			usbd_xfer_set_interval(xfer, x);
			usbd_xfer_set_frames(xfer, 1);
			usbd_transfer_submit(xfer);
		} else {
			sc->sc_tx_busy = 0;
		}
		break;

	default:			/* Error */
		DPRINTF("error=%s\n", usbd_errstr(error));

		if (error != USB_ERR_CANCELLED) {
			/* try to clear stall first */
			usbd_xfer_set_stall(xfer);
			goto tr_setup;
		}
		break;
	}
}