From 96dab77ebf3868cc8723ac95e048e8a9c1dccf22 Mon Sep 17 00:00:00 2001 From: Olivier Bornet Date: Thu, 11 Jun 2009 12:54:20 +0100 Subject: [PATCH] tty: iuu_phoenix: set termios. set_termios can now be used for setting the parity and the stopbits. This is needed to use with cards which use a different parity then the parity used at start (even). If the iuu_uart_baud function return an error, we will return the old_termios instead of the new one. Signed-off-by: Olivier Bornet This was then revamped to use the various helpers, not copy non-hardware bits any to add mark/space parity and csize reporting Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/usb/serial/iuu_phoenix.c | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index ef6d12fd579c..fa86f6e7415f 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -942,6 +942,55 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud, return status; } +static void iuu_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) +{ + const u32 supported_mask = CMSPAR|PARENB|PARODD; + + unsigned int cflag = tty->termios->c_cflag; + int status; + u32 actual; + u32 parity; + int csize = CS7; + int baud = 9600; /* Fixed for the moment */ + u32 newval = cflag & supported_mask; + + /* compute the parity parameter */ + parity = 0; + if (cflag & CMSPAR) { /* Using mark space */ + if (cflag & PARODD) + parity |= IUU_PARITY_SPACE; + else + parity |= IUU_PARITY_MARK; + } else if (!(cflag & PARENB)) { + parity |= IUU_PARITY_NONE; + csize = CS8; + } else if (cflag & PARODD) + parity |= IUU_PARITY_ODD; + else + parity |= IUU_PARITY_EVEN; + + parity |= (cflag & CSTOPB ? IUU_TWO_STOP_BITS : IUU_ONE_STOP_BIT); + + /* set it */ + status = iuu_uart_baud(port, + (clockmode == 2) ? 16457 : 9600 * boost / 100, + &actual, parity); + + /* set the termios value to the real one, so the user now what has + * changed. We support few fields so its easies to copy the old hw + * settings back over and then adjust them + */ + if (old_termios) + tty_termios_copy_hw(tty->termios, old_termios); + if (status != 0) /* Set failed - return old bits */ + return; + /* Re-encode speed, parity and csize */ + tty_encode_baud_rate(tty, baud, baud); + tty->termios->c_cflag &= ~(supported_mask|CSIZE); + tty->termios->c_cflag |= newval | csize; +} + static void iuu_close(struct usb_serial_port *port) { /* iuu_led (port,255,0,0,0); */ @@ -1151,6 +1200,7 @@ static struct usb_serial_driver iuu_device = { .read_bulk_callback = iuu_uart_read_callback, .tiocmget = iuu_tiocmget, .tiocmset = iuu_tiocmset, + .set_termios = iuu_set_termios, .attach = iuu_startup, .shutdown = iuu_shutdown, }; -- 2.20.1