Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/usb/serial/usb_serial.c
| Show First 20 Lines • Show All 145 Lines • ▼ Show 20 Lines | |||||
| static usb_proc_callback_t ucom_cfg_line_state; | static usb_proc_callback_t ucom_cfg_line_state; | ||||
| static usb_proc_callback_t ucom_cfg_status_change; | static usb_proc_callback_t ucom_cfg_status_change; | ||||
| static usb_proc_callback_t ucom_cfg_param; | static usb_proc_callback_t ucom_cfg_param; | ||||
| static int ucom_unit_alloc(void); | static int ucom_unit_alloc(void); | ||||
| static void ucom_unit_free(int); | static void ucom_unit_free(int); | ||||
| static int ucom_attach_tty(struct ucom_super_softc *, struct ucom_softc *); | static int ucom_attach_tty(struct ucom_super_softc *, struct ucom_softc *); | ||||
| static void ucom_detach_tty(struct ucom_super_softc *, struct ucom_softc *); | static void ucom_detach_tty(struct ucom_super_softc *, struct ucom_softc *); | ||||
| static void ucom_queue_command(struct ucom_softc *, | static int ucom_queue_command(struct ucom_softc *, | ||||
| usb_proc_callback_t *, struct termios *pt, | usb_proc_callback_t *, struct termios *pt, | ||||
| struct usb_proc_msg *t0, struct usb_proc_msg *t1); | struct usb_proc_msg *t0, struct usb_proc_msg *t1); | ||||
| static void ucom_shutdown(struct ucom_softc *); | static void ucom_shutdown(struct ucom_softc *); | ||||
| static void ucom_ring(struct ucom_softc *, uint8_t); | static void ucom_ring(struct ucom_softc *, uint8_t); | ||||
| static void ucom_break(struct ucom_softc *, uint8_t); | static void ucom_break(struct ucom_softc *, uint8_t); | ||||
| static void ucom_dtr(struct ucom_softc *, uint8_t); | static void ucom_dtr(struct ucom_softc *, uint8_t); | ||||
| static void ucom_rts(struct ucom_softc *, uint8_t); | static void ucom_rts(struct ucom_softc *, uint8_t); | ||||
| ▲ Show 20 Lines • Show All 424 Lines • ▼ Show 20 Lines | case USB_MODE_DEVICE: | ||||
| ssc->sc_flag |= UCOM_FLAG_DEVICE_MODE; | ssc->sc_flag |= UCOM_FLAG_DEVICE_MODE; | ||||
| break; | break; | ||||
| default: | default: | ||||
| ssc->sc_flag &= ~UCOM_FLAG_DEVICE_MODE; | ssc->sc_flag &= ~UCOM_FLAG_DEVICE_MODE; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| static void | static int | ||||
| ucom_queue_command(struct ucom_softc *sc, | ucom_queue_command(struct ucom_softc *sc, | ||||
| usb_proc_callback_t *fn, struct termios *pt, | usb_proc_callback_t *fn, struct termios *pt, | ||||
| struct usb_proc_msg *t0, struct usb_proc_msg *t1) | struct usb_proc_msg *t0, struct usb_proc_msg *t1) | ||||
| { | { | ||||
| struct ucom_super_softc *ssc = sc->sc_super; | struct ucom_super_softc *ssc = sc->sc_super; | ||||
| struct ucom_param_task *task; | struct ucom_param_task *task; | ||||
| UCOM_MTX_ASSERT(sc, MA_OWNED); | UCOM_MTX_ASSERT(sc, MA_OWNED); | ||||
| if (usb_proc_is_gone(&ssc->sc_tq)) { | if (usb_proc_is_gone(&ssc->sc_tq)) { | ||||
| DPRINTF("proc is gone\n"); | DPRINTF("proc is gone\n"); | ||||
| return; /* nothing to do */ | return (ENXIO); /* nothing to do */ | ||||
| } | } | ||||
| /* | /* | ||||
| * NOTE: The task cannot get executed before we drop the | * NOTE: The task cannot get executed before we drop the | ||||
| * "sc_mtx" mutex. It is safe to update fields in the message | * "sc_mtx" mutex. It is safe to update fields in the message | ||||
| * structure after that the message got queued. | * structure after that the message got queued. | ||||
| */ | */ | ||||
| task = (struct ucom_param_task *) | task = (struct ucom_param_task *) | ||||
| usb_proc_msignal(&ssc->sc_tq, t0, t1); | usb_proc_msignal(&ssc->sc_tq, t0, t1); | ||||
| Show All 16 Lines | if (fn == ucom_cfg_close || fn == ucom_cfg_open) | ||||
| usb_proc_mwait(&ssc->sc_tq, t0, t1); | usb_proc_mwait(&ssc->sc_tq, t0, t1); | ||||
| /* | /* | ||||
| * In case of multiple configure requests, | * In case of multiple configure requests, | ||||
| * keep track of the last one! | * keep track of the last one! | ||||
| */ | */ | ||||
| if (fn == ucom_cfg_start_transfers) | if (fn == ucom_cfg_start_transfers) | ||||
| sc->sc_last_start_xfer = &task->hdr; | sc->sc_last_start_xfer = &task->hdr; | ||||
| return (0); | |||||
| } | } | ||||
| static void | static void | ||||
| ucom_shutdown(struct ucom_softc *sc) | ucom_shutdown(struct ucom_softc *sc) | ||||
| { | { | ||||
| struct tty *tp = sc->sc_tty; | struct tty *tp = sc->sc_tty; | ||||
| UCOM_MTX_ASSERT(sc, MA_OWNED); | UCOM_MTX_ASSERT(sc, MA_OWNED); | ||||
| ▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | ucom_open(struct tty *tp) | ||||
| DPRINTF("tp = %p\n", tp); | DPRINTF("tp = %p\n", tp); | ||||
| if (sc->sc_callback->ucom_pre_open) { | if (sc->sc_callback->ucom_pre_open) { | ||||
| /* | /* | ||||
| * give the lower layer a chance to disallow TTY open, for | * give the lower layer a chance to disallow TTY open, for | ||||
| * example if the device is not present: | * example if the device is not present: | ||||
| */ | */ | ||||
| error = (sc->sc_callback->ucom_pre_open) (sc); | error = (sc->sc_callback->ucom_pre_open) (sc); | ||||
| if (error) { | if (error != 0) | ||||
| return (error); | goto out; | ||||
| } | } | ||||
| } | |||||
| sc->sc_flag |= UCOM_FLAG_HL_READY; | sc->sc_flag |= UCOM_FLAG_HL_READY; | ||||
| /* Disable transfers */ | /* Disable transfers */ | ||||
| sc->sc_flag &= ~UCOM_FLAG_GP_DATA; | sc->sc_flag &= ~UCOM_FLAG_GP_DATA; | ||||
| sc->sc_lsr = 0; | sc->sc_lsr = 0; | ||||
| sc->sc_msr = 0; | sc->sc_msr = 0; | ||||
| sc->sc_mcr = 0; | sc->sc_mcr = 0; | ||||
| /* reset programmed line state */ | /* reset programmed line state */ | ||||
| sc->sc_pls_curr = 0; | sc->sc_pls_curr = 0; | ||||
| sc->sc_pls_set = 0; | sc->sc_pls_set = 0; | ||||
| sc->sc_pls_clr = 0; | sc->sc_pls_clr = 0; | ||||
| /* reset jitter buffer */ | /* reset jitter buffer */ | ||||
| sc->sc_jitterbuf_in = 0; | sc->sc_jitterbuf_in = 0; | ||||
| sc->sc_jitterbuf_out = 0; | sc->sc_jitterbuf_out = 0; | ||||
| ucom_queue_command(sc, ucom_cfg_open, NULL, | error = ucom_queue_command(sc, ucom_cfg_open, NULL, | ||||
| &sc->sc_open_task[0].hdr, | &sc->sc_open_task[0].hdr, | ||||
| &sc->sc_open_task[1].hdr); | &sc->sc_open_task[1].hdr); | ||||
| if (error != 0) | |||||
| goto out; | |||||
| /* Queue transfer enable command last */ | /* Queue transfer enable command last */ | ||||
| ucom_queue_command(sc, ucom_cfg_start_transfers, NULL, | error = ucom_queue_command(sc, ucom_cfg_start_transfers, NULL, | ||||
| &sc->sc_start_task[0].hdr, | &sc->sc_start_task[0].hdr, | ||||
| &sc->sc_start_task[1].hdr); | &sc->sc_start_task[1].hdr); | ||||
| if (error != 0) | |||||
| goto out; | |||||
| if (sc->sc_tty == NULL || (sc->sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0) | if (sc->sc_tty == NULL || (sc->sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0) | ||||
| ucom_modem(tp, SER_DTR | SER_RTS, 0); | ucom_modem(tp, SER_DTR | SER_RTS, 0); | ||||
| ucom_ring(sc, 0); | ucom_ring(sc, 0); | ||||
| ucom_break(sc, 0); | ucom_break(sc, 0); | ||||
| ucom_status_change(sc); | ucom_status_change(sc); | ||||
| return (0); | out: | ||||
| return (error); | |||||
kib: Why return ENOTTY and then translate the error? | |||||
Done Inline ActionsWill fix- originally this bubbled up to ucom_ioctl as well, where it didn't get translated. Later revisions added ucom_command_barrier which will get used in some contexts where ENOTTY makes sense for the tty layer (ioctl) and others where ENXIO makes more sense. kevans: Will fix- originally this bubbled up to ucom_ioctl as well, where it didn't get translated. | |||||
| } | } | ||||
| static void | static void | ||||
| ucom_cfg_close(struct usb_proc_msg *_task) | ucom_cfg_close(struct usb_proc_msg *_task) | ||||
| { | { | ||||
| struct ucom_cfg_task *task = | struct ucom_cfg_task *task = | ||||
| (struct ucom_cfg_task *)_task; | (struct ucom_cfg_task *)_task; | ||||
| struct ucom_softc *sc = task->sc; | struct ucom_softc *sc = task->sc; | ||||
| Show All 19 Lines | ucom_close(struct tty *tp) | ||||
| DPRINTF("tp=%p\n", tp); | DPRINTF("tp=%p\n", tp); | ||||
| if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { | if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { | ||||
| DPRINTF("tp=%p already closed\n", tp); | DPRINTF("tp=%p already closed\n", tp); | ||||
| return; | return; | ||||
| } | } | ||||
| ucom_shutdown(sc); | ucom_shutdown(sc); | ||||
| ucom_queue_command(sc, ucom_cfg_close, NULL, | (void)ucom_queue_command(sc, ucom_cfg_close, NULL, | ||||
| &sc->sc_close_task[0].hdr, | &sc->sc_close_task[0].hdr, | ||||
| &sc->sc_close_task[1].hdr); | &sc->sc_close_task[1].hdr); | ||||
| sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_RTS_IFLOW); | sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_RTS_IFLOW); | ||||
| if (sc->sc_callback->ucom_stop_read) { | if (sc->sc_callback->ucom_stop_read) { | ||||
| (sc->sc_callback->ucom_stop_read) (sc); | (sc->sc_callback->ucom_stop_read) (sc); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | ucom_line_state(struct ucom_softc *sc, | ||||
| DPRINTF("on=0x%02x, off=0x%02x\n", set_bits, clear_bits); | DPRINTF("on=0x%02x, off=0x%02x\n", set_bits, clear_bits); | ||||
| /* update current programmed line state */ | /* update current programmed line state */ | ||||
| sc->sc_pls_curr |= set_bits; | sc->sc_pls_curr |= set_bits; | ||||
| sc->sc_pls_curr &= ~clear_bits; | sc->sc_pls_curr &= ~clear_bits; | ||||
| sc->sc_pls_set |= set_bits; | sc->sc_pls_set |= set_bits; | ||||
| sc->sc_pls_clr |= clear_bits; | sc->sc_pls_clr |= clear_bits; | ||||
| /* defer driver programming */ | /* | ||||
| ucom_queue_command(sc, ucom_cfg_line_state, NULL, | * defer driver programming - we don't propagate any error from | ||||
| * this call because we'll catch such errors further up the call stack. | |||||
| */ | |||||
| (void)ucom_queue_command(sc, ucom_cfg_line_state, NULL, | |||||
| &sc->sc_line_state_task[0].hdr, | &sc->sc_line_state_task[0].hdr, | ||||
| &sc->sc_line_state_task[1].hdr); | &sc->sc_line_state_task[1].hdr); | ||||
| } | } | ||||
| static void | static void | ||||
| ucom_ring(struct ucom_softc *sc, uint8_t onoff) | ucom_ring(struct ucom_softc *sc, uint8_t onoff) | ||||
| { | { | ||||
| DPRINTF("onoff = %d\n", onoff); | DPRINTF("onoff = %d\n", onoff); | ||||
| ▲ Show 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | ucom_status_change(struct ucom_softc *sc) | ||||
| if (sc->sc_flag & UCOM_FLAG_CONSOLE) | if (sc->sc_flag & UCOM_FLAG_CONSOLE) | ||||
| return; /* not supported */ | return; /* not supported */ | ||||
| if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { | if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { | ||||
| return; | return; | ||||
| } | } | ||||
| DPRINTF("\n"); | DPRINTF("\n"); | ||||
| ucom_queue_command(sc, ucom_cfg_status_change, NULL, | (void)ucom_queue_command(sc, ucom_cfg_status_change, NULL, | ||||
| &sc->sc_status_task[0].hdr, | &sc->sc_status_task[0].hdr, | ||||
| &sc->sc_status_task[1].hdr); | &sc->sc_status_task[1].hdr); | ||||
| } | } | ||||
| static void | static void | ||||
| ucom_cfg_param(struct usb_proc_msg *_task) | ucom_cfg_param(struct usb_proc_msg *_task) | ||||
| { | { | ||||
| struct ucom_param_task *task = | struct ucom_param_task *task = | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | if (error) { | ||||
| goto done; | goto done; | ||||
| } | } | ||||
| } | } | ||||
| /* Disable transfers */ | /* Disable transfers */ | ||||
| sc->sc_flag &= ~UCOM_FLAG_GP_DATA; | sc->sc_flag &= ~UCOM_FLAG_GP_DATA; | ||||
| /* Queue baud rate programming command first */ | /* Queue baud rate programming command first */ | ||||
| ucom_queue_command(sc, ucom_cfg_param, t, | error = ucom_queue_command(sc, ucom_cfg_param, t, | ||||
| &sc->sc_param_task[0].hdr, | &sc->sc_param_task[0].hdr, | ||||
| &sc->sc_param_task[1].hdr); | &sc->sc_param_task[1].hdr); | ||||
| if (error != 0) | |||||
| goto done; | |||||
| /* Queue transfer enable command last */ | /* Queue transfer enable command last */ | ||||
| ucom_queue_command(sc, ucom_cfg_start_transfers, NULL, | error = ucom_queue_command(sc, ucom_cfg_start_transfers, NULL, | ||||
| &sc->sc_start_task[0].hdr, | &sc->sc_start_task[0].hdr, | ||||
| &sc->sc_start_task[1].hdr); | &sc->sc_start_task[1].hdr); | ||||
| if (error != 0) | |||||
| goto done; | |||||
| if (t->c_cflag & CRTS_IFLOW) { | if (t->c_cflag & CRTS_IFLOW) { | ||||
| sc->sc_flag |= UCOM_FLAG_RTS_IFLOW; | sc->sc_flag |= UCOM_FLAG_RTS_IFLOW; | ||||
| } else if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW) { | } else if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW) { | ||||
| sc->sc_flag &= ~UCOM_FLAG_RTS_IFLOW; | sc->sc_flag &= ~UCOM_FLAG_RTS_IFLOW; | ||||
| ucom_modem(tp, SER_RTS, 0); | ucom_modem(tp, SER_RTS, 0); | ||||
| } | } | ||||
| done: | done: | ||||
| ▲ Show 20 Lines • Show All 455 Lines • Show Last 20 Lines | |||||
Why return ENOTTY and then translate the error?