Date: Fri, 26 Sep 2008 17:29:56 GMT From: Andrew Thompson <thompsa@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 150512 for review Message-ID: <200809261729.m8QHTuvq025959@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=150512 Change 150512 by thompsa@thompsa_burger on 2008/09/26 17:29:13 Add in a custom rint routine, we should buffer the input intil the hotchar is seen. In most cases this will be the PPP framing char of 0x7e. Affected files ... .. //depot/projects/mpsafetty/sys/netgraph/ng_tty.c#7 edit Differences ... ==== //depot/projects/mpsafetty/sys/netgraph/ng_tty.c#7 (text+ko) ==== @@ -87,6 +87,7 @@ hook_p hook; /* Netgraph hook */ struct ifqueue outq; /* Queue of outgoing data */ size_t outqlen; /* Number of bytes in outq */ + struct mbuf *m; /* Incoming non-bypass data buffer */ short hotchar; /* Hotchar, or -1 if none */ u_int flags; /* Flags */ }; @@ -110,6 +111,7 @@ static th_getc_inject_t ngt_getc_inject; static th_getc_poll_t ngt_getc_poll; +static th_rint_t ngt_rint; static th_rint_bypass_t ngt_rint_bypass; static th_rint_poll_t ngt_rint_poll; static th_close_t ngt_close; @@ -117,7 +119,8 @@ static struct ttyhook ngt_hook = { .th_getc_inject = ngt_getc_inject, .th_getc_poll = ngt_getc_poll, - .th_rint_bypass = ngt_rint_bypass, + .th_rint = ngt_rint, + .th_rint_bypass = ngt_rint_bypass, .th_rint_poll = ngt_rint_poll, .th_close = ngt_close, }; @@ -401,6 +404,12 @@ return (sc->outqlen); } +/* + * Optimised TTY input. + * + * We get a buffer pointer to hopefully a complete data frame. Do not check for + * the hotchar, just pass it on. + */ static size_t ngt_rint_bypass(struct tty *tp, const void *buf, size_t len) { @@ -410,6 +419,8 @@ size_t total = 0; int error = 0, length; + tty_lock_assert(tp, MA_OWNED); + if (sc->hook == NULL) return (0); @@ -430,11 +441,75 @@ total += length; m->m_pkthdr.len += length; } + if (sc->m != NULL) { + /* + * Odd, we have changed from non-bypass to bypass. It is + * unlikely but not impossible, flush the data first. + */ + sc->m->m_data = sc->m->m_pktdat; + NG_SEND_DATA_ONLY(error, sc->hook, sc->m); + sc->m = NULL; + } NG_SEND_DATA_ONLY(error, sc->hook, m); return (total); } +/* + * Receive data coming from the device one char at a time, when it is not in + * bypass mode. + */ +static int +ngt_rint(struct tty *tp, char c, int flags) +{ + sc_p sc = ttyhook_softc(tp); + node_p node = sc->node; + struct mbuf *m; + int error = 0; + + tty_lock_assert(tp, MA_OWNED); + + if (sc->hook == NULL) + return (0); + + if (flags != 0) { + /* framing error or overrun on this char */ + if (sc->flags & FLG_DEBUG) + log(LOG_DEBUG, "%s: line error %x\n", + NG_NODE_NAME(node), flags); + return (0); + } + + /* Get a new header mbuf if we need one */ + if (!(m = sc->m)) { + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (!m) { + if (sc->flags & FLG_DEBUG) + log(LOG_ERR, + "%s: can't get mbuf\n", NG_NODE_NAME(node)); + return (ENOBUFS); + } + m->m_len = m->m_pkthdr.len = 0; + m->m_pkthdr.rcvif = NULL; + sc->m = m; + } + + /* Add char to mbuf */ + *mtod(m, u_char *) = c; + m->m_data++; + m->m_len++; + m->m_pkthdr.len++; + + /* Ship off mbuf if it's time */ + if (sc->hotchar == -1 || c == sc->hotchar || m->m_len >= MHLEN) { + m->m_data = m->m_pktdat; + sc->m = NULL; + NG_SEND_DATA_ONLY(error, sc->hook, m); /* Will queue */ + } + + return (error); +} + static size_t ngt_rint_poll(struct tty *tp) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200809261729.m8QHTuvq025959>