Module Name:    src
Committed By:   skrll
Date:           Mon May 30 06:54:17 UTC 2016

Modified Files:
        src/sys/dev/usb [nick-nhusb]: ucom.c ucomvar.h umct.c

Log Message:
WIP ucom support for devices with interrupt endpoints like umct


To generate a diff of this commit:
cvs rdiff -u -r1.108.2.14 -r1.108.2.15 src/sys/dev/usb/ucom.c
cvs rdiff -u -r1.20.24.4 -r1.20.24.5 src/sys/dev/usb/ucomvar.h
cvs rdiff -u -r1.32.24.12 -r1.32.24.13 src/sys/dev/usb/umct.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/ucom.c
diff -u src/sys/dev/usb/ucom.c:1.108.2.14 src/sys/dev/usb/ucom.c:1.108.2.15
--- src/sys/dev/usb/ucom.c:1.108.2.14	Sun May 29 08:44:31 2016
+++ src/sys/dev/usb/ucom.c	Mon May 30 06:54:17 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ucom.c,v 1.108.2.14 2016/05/29 08:44:31 skrll Exp $	*/
+/*	$NetBSD: ucom.c,v 1.108.2.15 2016/05/30 06:54:17 skrll Exp $	*/
 
 /*
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.108.2.14 2016/05/29 08:44:31 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.108.2.15 2016/05/30 06:54:17 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -158,6 +158,11 @@ struct ucom_softc {
 	SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_free;
 	SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_full;
 
+	struct usbd_pipe	*sc_ipipe;
+	struct usbd_xfer	*sc_ixfer;
+	struct usbd_pipe	*sc_opipe;
+	struct usbd_xfer	*sc_oxfer;
+
 	void			*sc_si;
 
 	const struct ucom_methods *sc_methods;
@@ -224,7 +229,6 @@ static void	ucom_break(struct ucom_softc
 static void	tiocm_to_ucom(struct ucom_softc *, u_long, int);
 static int	ucom_to_tiocm(struct ucom_softc *);
 
-static void	ucomreadcb(struct usbd_xfer *, void *, usbd_status);
 static void	ucom_submit_write(struct ucom_softc *, struct ucom_buffer *);
 static void	ucom_write_status(struct ucom_softc *, struct ucom_buffer *,
 			usbd_status);
@@ -264,6 +268,9 @@ ucom_attach(device_t parent, device_t se
 	prop_dictionary_set_int32(device_properties(self), "port",
 	    ucaa->ucaa_portno);
 
+	KASSERT(ucaa->ucaa_bulkin != -1 || (ucaa->ucaa_ipipe && ucaa->ucaa_ixfer));
+	KASSERT(ucaa->ucaa_bulkout != -1 || (ucaa->ucaa_opipe && ucaa->ucaa_oxfer));
+
 	sc->sc_dev = self;
 	sc->sc_udev = ucaa->ucaa_device;
 	sc->sc_iface = ucaa->ucaa_iface;
@@ -307,41 +314,57 @@ ucom_attach(device_t parent, device_t se
 	usbd_status err;
 	int error;
 
-	/* 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("open bulk in error (addr %d), err=%d",
-		    sc->sc_bulkin_no, err, 0, 0);
-		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("open bulk out error (addr %d), err=%d",
-		    sc->sc_bulkout_no, err, 0, 0);
-		error = EIO;
-		goto fail_1;
+	if (sc->sc_bulkin_no != -1) {
+		/* 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("open bulk in error (addr %d), err=%d",
+			    sc->sc_bulkin_no, err, 0, 0);
+			error = EIO;
+			goto fail_0;
+		}
+		/* Allocate input buffers */
+		for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
+		    ub++) {
+			error = usbd_create_xfer(sc->sc_bulkin_pipe,
+			    sc->sc_ibufsizepad, USBD_SHORT_XFER_OK, 0,
+			    &ub->ub_xfer);
+			if (error)
+				goto fail_1;
+			ub->ub_data = usbd_get_buffer(ub->ub_xfer);
+		}
+
 	}
 
-	/* Allocate input buffers */
-	for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
-	    ub++) {
-		error = usbd_create_xfer(sc->sc_bulkin_pipe, sc->sc_ibufsizepad,
-		    USBD_SHORT_XFER_OK, 0, &ub->ub_xfer);
-		if (error)
-			goto fail_2;
-		ub->ub_data = usbd_get_buffer(ub->ub_xfer);
+	if (sc->sc_bulkout_no != -1) {
+		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
+		    USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
+		if (err) {
+			DPRINTF("open bulk out error (addr %d), err=%d",
+			    sc->sc_bulkout_no, err, 0, 0);
+			error = EIO;
+			goto fail_1;
+		}
+		for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
+		    ub++) {
+			error = usbd_create_xfer(sc->sc_bulkout_pipe,
+			    sc->sc_obufsize, 0, 0, &ub->ub_xfer);
+			if (error)
+				goto fail_2;
+			ub->ub_data = usbd_get_buffer(ub->ub_xfer);
+			SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
+		}
 	}
 
-	for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
-	    ub++) {
-		error = usbd_create_xfer(sc->sc_bulkout_pipe, sc->sc_obufsize,
-		    0, 0, &ub->ub_xfer);
-		if (error)
-			goto fail_2;
-		ub->ub_data = usbd_get_buffer(ub->ub_xfer);
+	if (sc->sc_ipipe && sc->sc_ixfer) {
+		ub = &sc->sc_ibuff[0];
+		ub->ub_data = usbd_get_buffer(sc->sc_ixfer);
+		SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_empty, ub, ub_link);
+	}
+	if (sc->sc_opipe && sc->sc_oxfer) {
+		ub = &sc->sc_obuff[0];
+		ub->ub_data = usbd_get_buffer(sc->sc_oxfer);
 		SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
 	}
 
@@ -362,18 +385,20 @@ ucom_attach(device_t parent, device_t se
 	return;
 
 fail_2:
-	for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
+	for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
 	    ub++) {
 		if (ub->ub_xfer)
 			usbd_destroy_xfer(ub->ub_xfer);
 	}
-	for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
+
+	usbd_close_pipe(sc->sc_bulkout_pipe);
+
+fail_1:
+	for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
 	    ub++) {
 		if (ub->ub_xfer)
 			usbd_destroy_xfer(ub->ub_xfer);
 	}
-
-fail_1:
 	usbd_close_pipe(sc->sc_bulkin_pipe);
 
 fail_0:
@@ -620,6 +645,9 @@ ucomopen(dev_t dev, int flag, int mode, 
 		sc->sc_rx_stopped = 0;
 		sc->sc_tx_stopped = 0;
 
+		/*
+		 * ucomsubmitread handles bulk vs other
+		 */
 		for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
 		    ub++) {
 			if (ucomsubmitread(sc, ub) != USBD_NORMAL_COMPLETION) {
@@ -643,8 +671,10 @@ ucomopen(dev_t dev, int flag, int mode, 
 	return 0;
 
 fail_2:
-	usbd_abort_pipe(sc->sc_bulkin_pipe);
-	usbd_abort_pipe(sc->sc_bulkout_pipe);
+	if (sc->sc_bulkin_no != -1)
+		usbd_abort_pipe(sc->sc_bulkin_pipe);
+	if (sc->sc_bulkout_no != -1)
+		usbd_abort_pipe(sc->sc_bulkout_pipe);
 
 	mutex_enter(&sc->sc_lock);
 	sc->sc_opening = 0;
@@ -1381,13 +1411,15 @@ ucomsubmitread(struct ucom_softc *sc, st
 {
 	usbd_status err;
 
-	usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, sc->sc_ibufsize,
-	    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ucomreadcb);
-
-	if ((err = usbd_transfer(ub->ub_xfer)) != USBD_IN_PROGRESS) {
-		/* XXX: Recover from this, please! */
-		printf("ucomsubmitread: err=%s\n", usbd_errstr(err));
-		return err;
+	if (sc->sc_bulkin_no != -1) {
+		usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, sc->sc_ibufsize,
+		    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ucomreadcb);
+
+		if ((err = usbd_transfer(ub->ub_xfer)) != USBD_IN_PROGRESS) {
+			/* XXX: Recover from this, please! */
+			printf("%s: err=%s\n", __func__, usbd_errstr(err));
+			return err;
+		}
 	}
 
 	SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_empty, ub, ub_link);
@@ -1395,7 +1427,7 @@ ucomsubmitread(struct ucom_softc *sc, st
 	return USBD_NORMAL_COMPLETION;
 }
 
-static void
+void
 ucomreadcb(struct usbd_xfer *xfer, void *p, usbd_status status)
 {
 	struct ucom_softc *sc = (struct ucom_softc *)p;
@@ -1426,7 +1458,10 @@ ucomreadcb(struct usbd_xfer *xfer, void 
 	SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_empty, ub_link);
 
 	if (status == USBD_STALLED) {
-		usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
+		if (sc->sc_bulkin_no != -1)
+			usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
+		if (sc->sc_ipipe)
+			usbd_clear_endpoint_stall_async(sc->sc_ipipe);
 		ucomsubmitread(sc, ub);
 		mutex_exit(&sc->sc_lock);
 		return;

Index: src/sys/dev/usb/ucomvar.h
diff -u src/sys/dev/usb/ucomvar.h:1.20.24.4 src/sys/dev/usb/ucomvar.h:1.20.24.5
--- src/sys/dev/usb/ucomvar.h:1.20.24.4	Sat Apr 16 13:22:00 2016
+++ src/sys/dev/usb/ucomvar.h	Mon May 30 06:54:17 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ucomvar.h,v 1.20.24.4 2016/04/16 13:22:00 skrll Exp $	*/
+/*	$NetBSD: ucomvar.h,v 1.20.24.5 2016/05/30 06:54:17 skrll Exp $	*/
 
 /*
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -93,6 +93,10 @@ struct ucom_attach_args {
 	int ucaa_portno;
 	int ucaa_bulkin;
 	int ucaa_bulkout;
+	struct usbd_xfer *ucaa_ixfer;
+	struct usbd_pipe *ucaa_ipipe;
+	struct usbd_xfer *ucaa_oxfer;
+	struct usbd_pipe *ucaa_opipe;
 	u_int ucaa_ibufsize;
 	u_int ucaa_ibufsizepad;
 	u_int ucaa_obufsize;
@@ -107,3 +111,5 @@ struct ucom_attach_args {
 int ucomprint(void *, const char *);
 int ucomsubmatch(device_t t, cfdata_t, const int *, void *);
 void ucom_status_change(struct ucom_softc *);
+void ucomreadcb(struct usbd_xfer *, void *, usbd_status);
+

Index: src/sys/dev/usb/umct.c
diff -u src/sys/dev/usb/umct.c:1.32.24.12 src/sys/dev/usb/umct.c:1.32.24.13
--- src/sys/dev/usb/umct.c:1.32.24.12	Sat Apr 16 13:30:35 2016
+++ src/sys/dev/usb/umct.c	Mon May 30 06:54:17 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: umct.c,v 1.32.24.12 2016/04/16 13:30:35 skrll Exp $	*/
+/*	$NetBSD: umct.c,v 1.32.24.13 2016/05/30 06:54:17 skrll Exp $	*/
 /*
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umct.c,v 1.32.24.12 2016/04/16 13:30:35 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umct.c,v 1.32.24.13 2016/05/30 06:54:17 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -74,13 +74,17 @@ int	umctdebug = 0;
 
 struct	umct_softc {
 	device_t		sc_dev;		/* base device */
-	struct usbd_device *	sc_udev;	/* USB device */
-	struct usbd_interface *	sc_iface;	/* interface */
+	struct usbd_device	*sc_udev;	/* USB device */
+	struct usbd_interface	*sc_iface;	/* interface */
 	int			sc_iface_number;	/* interface number */
 	uint16_t		sc_product;
 
+	int			sc_inendpt;	/* data in endpoint */
+	struct usbd_pipe	*sc_inpipe;	/* data in pipe */
+	u_char			*sc_inbuf;	/* interrupt buffer */
+
 	int			sc_intr_number;	/* interrupt number */
-	struct usbd_pipe *	sc_intr_pipe;	/* interrupt pipe */
+	struct usbd_pipe	*sc_intr_pipe;	/* interrupt pipe */
 	u_char			*sc_intr_buf;	/* interrupt buffer */
 	int			sc_isize;
 
@@ -113,6 +117,8 @@ Static	void umct_set_baudrate(struct umc
 Static	void umct_set_lcr(struct umct_softc *, u_int);
 Static	void umct_intr(struct usbd_xfer *, void *, usbd_status);
 
+Static	void umct_rxintr(struct usbd_xfer *, void *, usbd_status);
+
 Static	void umct_set(void *, int, int, int);
 Static	void umct_dtr(struct umct_softc *, int);
 Static	void umct_rts(struct umct_softc *, int);
@@ -242,14 +248,15 @@ umct_attach(device_t parent, device_t se
 		}
 
 		/*
-		 * The Bulkin endpoint is marked as an interrupt. Since
+		 * Input is done via an interrupt endpoint, so we handle
+		 * the pipe and pass RX characters up to ucom.  Since
 		 * we can't rely on the endpoint descriptor order, we'll
 		 * check the wMaxPacketSize field to differentiate.
 		 */
 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT &&
 		    UGETW(ed->wMaxPacketSize) != 0x2) {
-			ucaa.ucaa_bulkin = ed->bEndpointAddress;
+			sc->sc_inendpt = ed->bEndpointAddress;
 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
 			ucaa.ucaa_bulkout = ed->bEndpointAddress;
@@ -260,8 +267,8 @@ umct_attach(device_t parent, device_t se
 		}
 	}
 
-	if (ucaa.ucaa_bulkin == -1) {
-		aprint_error_dev(self, "Could not find data bulk in\n");
+	if (sc->sc_inendpt == -1) {
+		aprint_error_dev(self, "Could not find data in\n");
 		sc->sc_dying = 1;
 		return;
 	}
@@ -278,6 +285,16 @@ umct_attach(device_t parent, device_t se
 		return;
 	}
 
+	if (sc->sc_inendpt != -1) {
+		err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_inendpt,
+		    USBD_SHORT_XFER_OK, &sc->sc_inpipe, sc, sc->sc_inbuf,
+		    sc->sc_isize, umct_rxintr, USBD_DEFAULT_INTERVAL);
+		if (err) {
+			DPRINTF(("%s: cannot open interrupt pipe (addr %d)\n",
+			    device_xname(sc->sc_dev), sc->sc_inendpt));
+			return EIO;
+		}
+	}
 	sc->sc_dtr = sc->sc_rts = 0;
 	ucaa.ucaa_portno = UCOM_UNK_PORTNO;
 	/* ucaa_bulkin, ucaa_bulkout set above */
@@ -592,8 +609,18 @@ umct_close(void *addr, int portno)
 }
 
 void
-umct_intr(struct usbd_xfer *xfer, void *priv,
-    usbd_status status)
+umct_rxintr(struct usbd_xfer *xfer, void *priv, usbd_status status)
+{
+	struct umct_softc *sc = priv;
+
+	if (sc->sc_dying)
+		return;
+
+	ucomreadcb(xfer, device_private(sc->sc_subdev), status);
+}
+
+void
+umct_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
 {
 	struct umct_softc *sc = priv;
 	u_char *tbuf = sc->sc_intr_buf;

Reply via email to