Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Nov 2012 18:10:05 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r243656 - in stable/9/sys: dev/usb/serial sys
Message-ID:  <201211281810.qASIA5E5004369@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Wed Nov 28 18:10:05 2012
New Revision: 243656
URL: http://svnweb.freebsd.org/changeset/base/243656

Log:
  MFC r242619, r242695, r242702 and r242703:
  Implement support for RTS (flow control).
  Improve USB serial console support.
  Implement a USB serial jitter buffer in receive direction.

Modified:
  stable/9/sys/dev/usb/serial/usb_serial.c
  stable/9/sys/dev/usb/serial/usb_serial.h
  stable/9/sys/sys/param.h
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)

Modified: stable/9/sys/dev/usb/serial/usb_serial.c
==============================================================================
--- stable/9/sys/dev/usb/serial/usb_serial.c	Wed Nov 28 17:55:18 2012	(r243655)
+++ stable/9/sys/dev/usb/serial/usb_serial.c	Wed Nov 28 18:10:05 2012	(r243656)
@@ -162,6 +162,7 @@ static tsw_ioctl_t ucom_ioctl;
 static tsw_modem_t ucom_modem;
 static tsw_param_t ucom_param;
 static tsw_outwakeup_t ucom_outwakeup;
+static tsw_inwakeup_t ucom_inwakeup;
 static tsw_free_t ucom_free;
 
 static struct ttydevsw ucom_class = {
@@ -169,6 +170,7 @@ static struct ttydevsw ucom_class = {
 	.tsw_open = ucom_open,
 	.tsw_close = ucom_close,
 	.tsw_outwakeup = ucom_outwakeup,
+	.tsw_inwakeup = ucom_inwakeup,
 	.tsw_ioctl = ucom_ioctl,
 	.tsw_param = ucom_param,
 	.tsw_modem = ucom_modem,
@@ -423,16 +425,13 @@ ucom_attach_tty(struct ucom_super_softc 
 	if ((ucom_cons_softc == NULL) && 
 	    (ssc->sc_unit == ucom_cons_unit) &&
 	    (sc->sc_subunit == ucom_cons_subunit)) {
-		struct termios t;
 
-		DPRINTF("unit %d subunit %d is console", ssc->sc_unit, sc->sc_subunit);
+		DPRINTF("unit %d subunit %d is console",
+		    ssc->sc_unit, sc->sc_subunit);
 
 		ucom_cons_softc = sc;
 
-		memset(&t, 0, sizeof(t));
-		t.c_ispeed = ucom_cons_baud;
-		t.c_ospeed = t.c_ispeed;
-		t.c_cflag = CS8;
+		tty_init_console(tp, ucom_cons_baud);
 
 		UCOM_MTX_LOCK(ucom_cons_softc);
 		ucom_cons_rx_low = 0;
@@ -441,7 +440,7 @@ ucom_attach_tty(struct ucom_super_softc 
 		ucom_cons_tx_high = 0;
 		sc->sc_flag |= UCOM_FLAG_CONSOLE;
 		ucom_open(ucom_cons_softc->sc_tty);
-		ucom_param(ucom_cons_softc->sc_tty, &t);
+		ucom_param(ucom_cons_softc->sc_tty, &tp->t_termios_init_in);
 		UCOM_MTX_UNLOCK(ucom_cons_softc);
 	}
 
@@ -716,6 +715,10 @@ ucom_open(struct tty *tp)
 	sc->sc_pls_set = 0;
 	sc->sc_pls_clr = 0;
 
+	/* reset jitter buffer */
+	sc->sc_jitterbuf_in = 0;
+	sc->sc_jitterbuf_out = 0;
+
 	ucom_queue_command(sc, ucom_cfg_open, NULL,
 	    &sc->sc_open_task[0].hdr,
 	    &sc->sc_open_task[1].hdr);
@@ -780,6 +783,46 @@ ucom_close(struct tty *tp)
 	}
 }
 
+static void
+ucom_inwakeup(struct tty *tp)
+{
+	struct ucom_softc *sc = tty_softc(tp);
+	uint16_t pos;
+
+	if (sc == NULL)
+		return;
+
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
+
+	DPRINTF("tp=%p\n", tp);
+
+	if (ttydisc_can_bypass(tp) != 0 || 
+	    (sc->sc_flag & UCOM_FLAG_HL_READY) == 0) {
+		return;
+	}
+
+	pos = sc->sc_jitterbuf_out;
+
+	while (sc->sc_jitterbuf_in != pos) {
+		int c;
+
+		c = (char)sc->sc_jitterbuf[pos];
+
+		if (ttydisc_rint(tp, c, 0) == -1)
+			break;
+		pos++;
+		if (pos >= UCOM_JITTERBUF_SIZE)
+			pos -= UCOM_JITTERBUF_SIZE;
+	}
+
+	sc->sc_jitterbuf_out = pos;
+
+	/* clear RTS in async fashion */
+	if ((sc->sc_jitterbuf_in == pos) && 
+	    (sc->sc_flag & UCOM_FLAG_RTS_IFLOW))
+		ucom_rts(sc, 0);
+}
+
 static int
 ucom_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
 {
@@ -1139,17 +1182,22 @@ ucom_param(struct tty *tp, struct termio
 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
 
 		/* XXX the TTY layer should call "open()" first! */
-
+		/*
+		 * Not quite: Its ordering is partly backwards, but
+		 * some parameters must be set early in ttydev_open(),
+		 * possibly before calling ttydevsw_open().
+		 */
 		error = ucom_open(tp);
-		if (error) {
+		if (error)
 			goto done;
-		}
+
 		opened = 1;
 	}
 	DPRINTF("sc = %p\n", sc);
 
 	/* Check requested parameters. */
 	if (t->c_ispeed && (t->c_ispeed != t->c_ospeed)) {
+		/* XXX c_ospeed == 0 is perfectly valid. */
 		DPRINTF("mismatch ispeed and ospeed\n");
 		error = EINVAL;
 		goto done;
@@ -1360,6 +1408,11 @@ ucom_put_data(struct ucom_softc *sc, str
 		/* first check if we can pass the buffer directly */
 
 		if (ttydisc_can_bypass(tp)) {
+
+			/* clear any jitter buffer */
+			sc->sc_jitterbuf_in = 0;
+			sc->sc_jitterbuf_out = 0;
+
 			if (ttydisc_rint_bypass(tp, buf, cnt) != cnt) {
 				DPRINTF("tp=%p, data lost\n", tp);
 			}
@@ -1368,8 +1421,31 @@ ucom_put_data(struct ucom_softc *sc, str
 		/* need to loop */
 
 		for (cnt = 0; cnt != res.length; cnt++) {
-			if (ttydisc_rint(tp, buf[cnt], 0) == -1) {
-				/* XXX what should we do? */
+			if (sc->sc_jitterbuf_in != sc->sc_jitterbuf_out ||
+			    ttydisc_rint(tp, buf[cnt], 0) == -1) {
+				uint16_t end;
+				uint16_t pos;
+
+				pos = sc->sc_jitterbuf_in;
+				end = sc->sc_jitterbuf_out +
+				    UCOM_JITTERBUF_SIZE - 1;
+				if (end >= UCOM_JITTERBUF_SIZE)
+					end -= UCOM_JITTERBUF_SIZE;
+
+				for (; cnt != res.length; cnt++) {
+					if (pos == end)
+						break;
+					sc->sc_jitterbuf[pos] = buf[cnt];
+					pos++;
+					if (pos >= UCOM_JITTERBUF_SIZE)
+						pos -= UCOM_JITTERBUF_SIZE;
+				}
+
+				sc->sc_jitterbuf_in = pos;
+
+				/* set RTS in async fashion */
+				if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW)
+					ucom_rts(sc, 1);
 
 				DPRINTF("tp=%p, lost %d "
 				    "chars\n", tp, res.length - cnt);

Modified: stable/9/sys/dev/usb/serial/usb_serial.h
==============================================================================
--- stable/9/sys/dev/usb/serial/usb_serial.h	Wed Nov 28 17:55:18 2012	(r243655)
+++ stable/9/sys/dev/usb/serial/usb_serial.h	Wed Nov 28 18:10:05 2012	(r243656)
@@ -78,6 +78,7 @@
 #define	UCOM_MINVER	1
 #define	UCOM_PREFVER	UCOM_MODVER
 #define	UCOM_MAXVER	1
+#define	UCOM_JITTERBUF_SIZE	128	/* bytes */
 
 struct usb_device;
 struct ucom_softc;
@@ -169,6 +170,8 @@ struct ucom_softc {
 	struct mtx *sc_mtx;
 	void   *sc_parent;
 	int sc_subunit;
+	uint16_t sc_jitterbuf_in;
+	uint16_t sc_jitterbuf_out;
 	uint16_t sc_portno;
 	uint16_t sc_flag;
 #define	UCOM_FLAG_RTS_IFLOW	0x01	/* use RTS input flow control */
@@ -191,6 +194,7 @@ struct ucom_softc {
 #define	UCOM_LS_RTS	0x02
 #define	UCOM_LS_BREAK	0x04
 #define	UCOM_LS_RING	0x08
+	uint8_t sc_jitterbuf[UCOM_JITTERBUF_SIZE];
 };
 
 #define	UCOM_MTX_ASSERT(sc, what) mtx_assert((sc)->sc_mtx, what)

Modified: stable/9/sys/sys/param.h
==============================================================================
--- stable/9/sys/sys/param.h	Wed Nov 28 17:55:18 2012	(r243655)
+++ stable/9/sys/sys/param.h	Wed Nov 28 18:10:05 2012	(r243656)
@@ -58,7 +58,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 901501	/* Master, propagated to newvers */
+#define __FreeBSD_version 901502	/* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211281810.qASIA5E5004369>