diff --git a/share/man/man4/ucom.4 b/share/man/man4/ucom.4 index e7dc77fb6243..4eb2d12c217c 100644 --- a/share/man/man4/ucom.4 +++ b/share/man/man4/ucom.4 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 24, 2018 +.Dd April 25, 2018 .Dt UCOM 4 .Os .Sh NAME @@ -74,6 +74,11 @@ tunables: Debug output level, where 0 is debugging disabled and larger values increase debug message verbosity. Default is 0. +.It Va hw.usb.ucom.device_mode_console +When set to 1, the +.Nm +driver will mark terminals as console devices when operating in device mode. +Default is 1. .It Va hw.usb.ucom.pps_mode Enables and configure PPS capture mode as described below. .Sh Pulse Per Second (PPS) Timing Interface diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c index 11bd375113fb..567fbe3fd417 100644 --- a/sys/dev/usb/serial/umodem.c +++ b/sys/dev/usb/serial/umodem.c @@ -457,6 +457,8 @@ umodem_attach(device_t dev) mtx_unlock(&sc->sc_mtx); } + ucom_set_usb_mode(&sc->sc_super_ucom, uaa->usb_mode); + error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, &umodem_callback, &sc->sc_mtx); if (error) { diff --git a/sys/dev/usb/serial/usb_serial.c b/sys/dev/usb/serial/usb_serial.c index 96c2c45c5ee6..445c9f2127b8 100644 --- a/sys/dev/usb/serial/usb_serial.c +++ b/sys/dev/usb/serial/usb_serial.c @@ -105,6 +105,12 @@ SYSCTL_INT(_hw_usb_ucom, OID_AUTO, pps_mode, CTLFLAG_RWTUN, &ucom_pps_mode, 0, "pulse capture mode: 0/1/2=disabled/CTS/DCD; add 0x10 to invert"); +static int ucom_device_mode_console = 1; + +SYSCTL_INT(_hw_usb_ucom, OID_AUTO, device_mode_console, CTLFLAG_RW, + &ucom_device_mode_console, 0, + "set to 1 to mark terminals as consoles when in device mode"); + #ifdef USB_DEBUG static int ucom_debug = 0; @@ -288,7 +294,7 @@ ucom_attach(struct ucom_super_softc *ssc, struct ucom_softc *sc, } ssc->sc_subunits = subunits; ssc->sc_flag = UCOM_FLAG_ATTACHED | - UCOM_FLAG_FREE_UNIT; + UCOM_FLAG_FREE_UNIT | (ssc->sc_flag & UCOM_FLAG_DEVICE_MODE); if (callback->ucom_free == NULL) ssc->sc_flag |= UCOM_FLAG_WAIT_REFS; @@ -388,6 +394,24 @@ ucom_drain_all(void *arg) mtx_unlock(&ucom_mtx); } +static cn_probe_t ucom_cnprobe; +static cn_init_t ucom_cninit; +static cn_term_t ucom_cnterm; +static cn_getc_t ucom_cngetc; +static cn_putc_t ucom_cnputc; +static cn_grab_t ucom_cngrab; +static cn_ungrab_t ucom_cnungrab; + +const struct consdev_ops ucom_cnops = { + .cn_probe = ucom_cnprobe, + .cn_init = ucom_cninit, + .cn_term = ucom_cnterm, + .cn_getc = ucom_cngetc, + .cn_putc = ucom_cnputc, + .cn_grab = ucom_cngrab, + .cn_ungrab = ucom_cnungrab, +}; + static int ucom_attach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) { @@ -450,6 +474,24 @@ ucom_attach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) UCOM_MTX_UNLOCK(ucom_cons_softc); } + if ((ssc->sc_flag & UCOM_FLAG_DEVICE_MODE) != 0 && + ucom_device_mode_console > 0 && + ucom_cons_softc == NULL) { + struct consdev *cp; + + cp = malloc(sizeof(struct consdev), M_USBDEV, + M_WAITOK|M_ZERO); + cp->cn_ops = &ucom_cnops; + cp->cn_arg = NULL; + cp->cn_pri = CN_NORMAL; + strlcpy(cp->cn_name, "tty", sizeof(cp->cn_name)); + strlcat(cp->cn_name, buf, sizeof(cp->cn_name)); + + sc->sc_consdev = cp; + + cnadd(cp); + } + return (0); } @@ -460,6 +502,12 @@ ucom_detach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) DPRINTF("sc = %p, tp = %p\n", sc, sc->sc_tty); + if (sc->sc_consdev != NULL) { + cnremove(sc->sc_consdev); + free(sc->sc_consdev, M_USBDEV); + sc->sc_consdev = NULL; + } + if (sc->sc_flag & UCOM_FLAG_CONSOLE) { UCOM_MTX_LOCK(ucom_cons_softc); ucom_close(ucom_cons_softc->sc_tty); @@ -533,6 +581,20 @@ ucom_set_pnpinfo_usb(struct ucom_super_softc *ssc, device_t dev) } } +void +ucom_set_usb_mode(struct ucom_super_softc *ssc, enum usb_hc_mode usb_mode) +{ + + switch (usb_mode) { + case USB_MODE_DEVICE: + ssc->sc_flag |= UCOM_FLAG_DEVICE_MODE; + break; + default: + ssc->sc_flag &= ~UCOM_FLAG_DEVICE_MODE; + break; + } +} + static void ucom_queue_command(struct ucom_softc *sc, usb_proc_callback_t *fn, struct termios *pt, @@ -1533,14 +1595,6 @@ ucom_free(void *xsc) mtx_unlock(&ucom_mtx); } -static cn_probe_t ucom_cnprobe; -static cn_init_t ucom_cninit; -static cn_term_t ucom_cnterm; -static cn_getc_t ucom_cngetc; -static cn_putc_t ucom_cnputc; -static cn_grab_t ucom_cngrab; -static cn_ungrab_t ucom_cnungrab; - CONSOLE_DRIVER(ucom); static void diff --git a/sys/dev/usb/serial/usb_serial.h b/sys/dev/usb/serial/usb_serial.h index 9a5e043e2474..cd60bcfb97a2 100644 --- a/sys/dev/usb/serial/usb_serial.h +++ b/sys/dev/usb/serial/usb_serial.h @@ -165,6 +165,7 @@ struct ucom_softc { const struct ucom_callback *sc_callback; struct ucom_super_softc *sc_super; struct tty *sc_tty; + struct consdev *sc_consdev; struct mtx *sc_mtx; void *sc_parent; int sc_subunit; @@ -183,6 +184,7 @@ struct ucom_softc { #define UCOM_FLAG_FREE_UNIT 0x0200 /* set if we must free the unit */ #define UCOM_FLAG_INWAKEUP 0x0400 /* set if we are in the tsw_inwakeup callback */ #define UCOM_FLAG_LSRTXIDLE 0x0800 /* set if sc_lsr bits ULSR_TSRE+TXRDY work */ +#define UCOM_FLAG_DEVICE_MODE 0x1000 /* set if we're an USB device, not a host */ uint8_t sc_lsr; uint8_t sc_msr; uint8_t sc_mcr; @@ -211,6 +213,7 @@ int ucom_attach(struct ucom_super_softc *, const struct ucom_callback *callback, struct mtx *); void ucom_detach(struct ucom_super_softc *, struct ucom_softc *); void ucom_set_pnpinfo_usb(struct ucom_super_softc *, device_t); +void ucom_set_usb_mode(struct ucom_super_softc *, enum usb_hc_mode); void ucom_status_change(struct ucom_softc *); uint8_t ucom_get_data(struct ucom_softc *, struct usb_page_cache *, uint32_t, uint32_t, uint32_t *);