Example #1
0
static usb_error_t
usbd_setup_endpoint_one(irp *ip, uint8_t ifidx, struct ndisusb_ep *ne,
    struct usb_config *epconf)
{
	device_t dev = IRP_NDIS_DEV(ip);
	struct ndis_softc *sc = device_get_softc(dev);
	struct usb_xfer *xfer;
	usb_error_t status;

	InitializeListHead(&ne->ne_active);
	InitializeListHead(&ne->ne_pending);
	KeInitializeSpinLock(&ne->ne_lock);

	status = usbd_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer,
	    epconf, 1, sc, &sc->ndisusb_mtx);
	if (status != USB_ERR_NORMAL_COMPLETION) {
		device_printf(dev, "couldn't setup xfer: %s\n",
		    usbd_errstr(status));
		return (status);
	}
	xfer = ne->ne_xfer[0];
	usbd_xfer_set_priv(xfer, ne);

	return (status);
}
Example #2
0
static usb_error_t
usbd_setup_endpoint(irp *ip, uint8_t ifidx,
    struct usb_endpoint_descriptor *ep)
{
	device_t dev = IRP_NDIS_DEV(ip);
	struct ndis_softc *sc = device_get_softc(dev);
	struct ndisusb_ep *ne;
	struct usb_config cfg;
	struct usb_xfer *xfer;
	usb_error_t status;

	/* check for non-supported transfer types */
	if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_CONTROL ||
	    UE_GET_XFERTYPE(ep->bmAttributes) == UE_ISOCHRONOUS) {
		device_printf(dev, "%s: unsuppotted transfer types %#x\n",
		    __func__, UE_GET_XFERTYPE(ep->bmAttributes));
		return (USB_ERR_INVAL);
	}

	ne = &sc->ndisusb_ep[NDISUSB_GET_ENDPT(ep->bEndpointAddress)];
	InitializeListHead(&ne->ne_active);
	InitializeListHead(&ne->ne_pending);
	KeInitializeSpinLock(&ne->ne_lock);
	ne->ne_dirin = UE_GET_DIR(ep->bEndpointAddress) >> 7;

	memset(&cfg, 0, sizeof(struct usb_config));
	cfg.type	= UE_GET_XFERTYPE(ep->bmAttributes);
	cfg.endpoint	= UE_GET_ADDR(ep->bEndpointAddress);
	cfg.direction	= UE_GET_DIR(ep->bEndpointAddress);
	cfg.callback	= &usbd_non_isoc_callback;
	cfg.bufsize	= UGETW(ep->wMaxPacketSize);
	cfg.flags.proxy_buffer = 1;
	if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN)
		cfg.flags.short_xfer_ok = 1;

	status = usbd_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer,
	    &cfg, 1, sc, &sc->ndisusb_mtx);
	if (status != USB_ERR_NORMAL_COMPLETION) {
		device_printf(dev, "couldn't setup xfer: %s\n",
		    usbd_errstr(status));
		return (status);
	}
	xfer = ne->ne_xfer[0];
	usbd_xfer_set_priv(xfer, ne);
	if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN)
		usbd_xfer_set_timeout(xfer, NDISUSB_NO_TIMEOUT);
	else {
		if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_BULK)
			usbd_xfer_set_timeout(xfer, NDISUSB_TX_TIMEOUT);
		else
			usbd_xfer_set_timeout(xfer, NDISUSB_INTR_TIMEOUT);
	}

	return (status);
}
Example #3
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;
	}
}
Example #4
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]);
	}
}
Example #5
0
static void
usie_uc_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
	struct ucom_softc *ucom = usbd_xfer_softc(xfer);
	struct usb_page_cache *pc;
	uint32_t actlen;

	switch (USB_GET_STATE(xfer)) {
	case USB_ST_TRANSFERRED:
	case USB_ST_SETUP:
tr_setup:
		pc = usbd_xfer_get_frame(xfer, 0);

		/* handle CnS request */
		struct mbuf *m = usbd_xfer_get_priv(xfer);

		if (m != NULL) {
			usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len);
			usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len);
			usbd_xfer_set_priv(xfer, NULL);
			usbd_transfer_submit(xfer);
			m_freem(m);
			break;
		}
		/* standard ucom transfer */
		if (ucom_get_data(ucom, pc, 0, USIE_BUFSIZE, &actlen)) {
			usbd_xfer_set_frame_len(xfer, 0, actlen);
			usbd_transfer_submit(xfer);
		}
		break;

	default:			/* Error */
		if (error != USB_ERR_CANCELLED) {
			usbd_xfer_set_stall(xfer);
			goto tr_setup;
		}
		break;
	}
}
Example #6
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);
	}
}