static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; unsigned int control = 0; dbg("%s - port %d", __func__, port->number); if (set & TIOCM_RTS) { control |= CONTROL_RTS; control |= CONTROL_WRITE_RTS; } if (set & TIOCM_DTR) { control |= CONTROL_DTR; control |= CONTROL_WRITE_DTR; } if (clear & TIOCM_RTS) { control &= ~CONTROL_RTS; control |= CONTROL_WRITE_RTS; } if (clear & TIOCM_DTR) { control &= ~CONTROL_DTR; control |= CONTROL_WRITE_DTR; } dbg("%s - control = 0x%.4x", __func__, control); return cp2101_set_config(port, CP2101_CONTROL, &control, 2); }
static void cp2101_break_ctl (struct usb_serial_port *port, int break_state) { int state; dbg("%s - port %d", __FUNCTION__, port->number); if (break_state == 0) state = BREAK_OFF; else state = BREAK_ON; dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on"); cp2101_set_config(port, CP2101_BREAK, &state, 2); }
static void cp2101_break_ctl (struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; unsigned int state; dbg("%s - port %d", __func__, port->number); if (break_state == 0) state = BREAK_OFF; else state = BREAK_ON; dbg("%s - turning break %s", __func__, state == BREAK_OFF ? "off" : "on"); cp2101_set_config(port, CP2101_BREAK, &state, 2); }
static void cp2101_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag, old_cflag; unsigned int baud = 0, bits; unsigned int modem_ctl[4]; dbg("%s - port %d", __func__, port->number); if (!tty) return; tty->termios->c_cflag &= ~CMSPAR; cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; baud = tty_get_baud_rate(tty); /* If the baud rate is to be updated*/ if (baud != tty_termios_baud_rate(old_termios)) { switch (baud) { case 0: case 600: case 1200: case 1800: case 2400: case 4800: case 7200: case 9600: case 14400: case 19200: case 28800: case 38400: case 55854: case 57600: case 115200: case 127117: case 230400: case 460800: case 921600: case 3686400: break; default: baud = 9600; break; } if (baud) { dbg("%s - Setting baud rate to %d baud", __func__, baud); if (cp2101_set_config_single(port, CP2101_BAUDRATE, (BAUD_RATE_GEN_FREQ / baud))) { dev_err(&port->dev, "Baud rate requested not " "supported by device\n"); baud = tty_termios_baud_rate(old_termios); } } } /* Report back the resulting baud rate */ tty_encode_baud_rate(tty, baud, baud); /* If the number of data bits is to be updated */ if ((cflag & CSIZE) != (old_cflag & CSIZE)) { cp2101_get_config(port, CP2101_BITS, &bits, 2); bits &= ~BITS_DATA_MASK; switch (cflag & CSIZE) { case CS5: bits |= BITS_DATA_5; dbg("%s - data bits = 5", __func__); break; case CS6: bits |= BITS_DATA_6; dbg("%s - data bits = 6", __func__); break; case CS7: bits |= BITS_DATA_7; dbg("%s - data bits = 7", __func__); break; case CS8: bits |= BITS_DATA_8; dbg("%s - data bits = 8", __func__); break; /*case CS9: bits |= BITS_DATA_9; dbg("%s - data bits = 9", __func__); break;*/ default: dev_err(&port->dev, "cp2101 driver does not " "support the number of bits requested," " using 8 bit mode\n"); bits |= BITS_DATA_8; break; } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) dev_err(&port->dev, "Number of data bits requested " "not supported by device\n"); } if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) { cp2101_get_config(port, CP2101_BITS, &bits, 2); bits &= ~BITS_PARITY_MASK; if (cflag & PARENB) { if (cflag & PARODD) { bits |= BITS_PARITY_ODD; dbg("%s - parity = ODD", __func__); } else { bits |= BITS_PARITY_EVEN; dbg("%s - parity = EVEN", __func__); } } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) dev_err(&port->dev, "Parity mode not supported " "by device\n"); } if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { cp2101_get_config(port, CP2101_BITS, &bits, 2); bits &= ~BITS_STOP_MASK; if (cflag & CSTOPB) { bits |= BITS_STOP_2; dbg("%s - stop bits = 2", __func__); } else { bits |= BITS_STOP_1; dbg("%s - stop bits = 1", __func__); } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) dev_err(&port->dev, "Number of stop bits requested " "not supported by device\n"); } if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", __func__, modem_ctl[0], modem_ctl[1], modem_ctl[2], modem_ctl[3]); if (cflag & CRTSCTS) { modem_ctl[0] &= ~0x7B; modem_ctl[0] |= 0x09; modem_ctl[1] = 0x80; dbg("%s - flow control = CRTSCTS", __func__); } else { modem_ctl[0] &= ~0x7B; modem_ctl[0] |= 0x01; modem_ctl[1] |= 0x40; dbg("%s - flow control = NONE", __func__); } dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", __func__, modem_ctl[0], modem_ctl[1], modem_ctl[2], modem_ctl[3]); cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16); } }
/* * cp2101_get_termios * Reads the baud rate, data bits, parity, stop bits and flow control mode * from the device, corrects any unsupported values, and configures the * termios structure to reflect the state of the device */ static void cp2101_get_termios (struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; unsigned int cflag, modem_ctl[4]; unsigned int baud; unsigned int bits; dbg("%s - port %d", __func__, port->number); cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); /* Convert to baudrate */ if (baud) baud = BAUD_RATE_GEN_FREQ / baud; dbg("%s - baud rate = %d", __func__, baud); tty_encode_baud_rate(tty, baud, baud); cflag = tty->termios->c_cflag; cp2101_get_config(port, CP2101_BITS, &bits, 2); cflag &= ~CSIZE; switch (bits & BITS_DATA_MASK) { case BITS_DATA_5: dbg("%s - data bits = 5", __func__); cflag |= CS5; break; case BITS_DATA_6: dbg("%s - data bits = 6", __func__); cflag |= CS6; break; case BITS_DATA_7: dbg("%s - data bits = 7", __func__); cflag |= CS7; break; case BITS_DATA_8: dbg("%s - data bits = 8", __func__); cflag |= CS8; break; case BITS_DATA_9: dbg("%s - data bits = 9 (not supported, using 8 data bits)", __func__); cflag |= CS8; bits &= ~BITS_DATA_MASK; bits |= BITS_DATA_8; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; default: dbg("%s - Unknown number of data bits, using 8", __func__); cflag |= CS8; bits &= ~BITS_DATA_MASK; bits |= BITS_DATA_8; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; } switch (bits & BITS_PARITY_MASK) { case BITS_PARITY_NONE: dbg("%s - parity = NONE", __func__); cflag &= ~PARENB; break; case BITS_PARITY_ODD: dbg("%s - parity = ODD", __func__); cflag |= (PARENB|PARODD); break; case BITS_PARITY_EVEN: dbg("%s - parity = EVEN", __func__); cflag &= ~PARODD; cflag |= PARENB; break; case BITS_PARITY_MARK: dbg("%s - parity = MARK (not supported, disabling parity)", __func__); cflag &= ~PARENB; bits &= ~BITS_PARITY_MASK; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; case BITS_PARITY_SPACE: dbg("%s - parity = SPACE (not supported, disabling parity)", __func__); cflag &= ~PARENB; bits &= ~BITS_PARITY_MASK; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; default: dbg("%s - Unknown parity mode, disabling parity", __func__); cflag &= ~PARENB; bits &= ~BITS_PARITY_MASK; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; } cflag &= ~CSTOPB; switch (bits & BITS_STOP_MASK) { case BITS_STOP_1: dbg("%s - stop bits = 1", __func__); break; case BITS_STOP_1_5: dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)", __func__); bits &= ~BITS_STOP_MASK; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; case BITS_STOP_2: dbg("%s - stop bits = 2", __func__); cflag |= CSTOPB; break; default: dbg("%s - Unknown number of stop bits, using 1 stop bit", __func__); bits &= ~BITS_STOP_MASK; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; } cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); if (modem_ctl[0] & 0x0008) { dbg("%s - flow control = CRTSCTS", __func__); cflag |= CRTSCTS; } else { dbg("%s - flow control = NONE", __func__); cflag &= ~CRTSCTS; } tty->termios->c_cflag = cflag; }
/* * cp2101_set_config_single * Convenience function for calling cp2101_set_config on single data values * without requiring an integer pointer */ static inline int cp2101_set_config_single(struct usb_serial_port *port, u8 request, unsigned int data) { return cp2101_set_config(port, request, &data, 2); }
/* * cp2101_get_termios * Reads the baud rate, data bits, parity, stop bits and flow control mode * from the device, corrects any unsupported values, and configures the * termios structure to reflect the state of the device */ static void cp2101_get_termios (struct usb_serial_port *port) { unsigned int cflag, modem_ctl[4]; int baud; int bits; dbg("%s - port %d", __FUNCTION__, port->number); if (!port->tty || !port->tty->termios) { dbg("%s - no tty structures", __FUNCTION__); return; } cflag = port->tty->termios->c_cflag; cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); /* Convert to baudrate */ if (baud) baud = BAUD_RATE_GEN_FREQ / baud; dbg("%s - baud rate = %d", __FUNCTION__, baud); cflag &= ~CBAUD; switch (baud) { /* * The baud rates which are commented out below * appear to be supported by the device * but are non-standard */ case 600: cflag |= B600; break; case 1200: cflag |= B1200; break; case 1800: cflag |= B1800; break; case 2400: cflag |= B2400; break; case 4800: cflag |= B4800; break; /*case 7200: cflag |= B7200; break;*/ case 9600: cflag |= B9600; break; /*case 14400: cflag |= B14400; break;*/ case 19200: cflag |= B19200; break; /*case 28800: cflag |= B28800; break;*/ case 38400: cflag |= B38400; break; /*case 55854: cflag |= B55054; break;*/ case 57600: cflag |= B57600; break; case 115200: cflag |= B115200; break; /*case 127117: cflag |= B127117; break;*/ case 230400: cflag |= B230400; break; case 460800: cflag |= B460800; break; case 921600: cflag |= B921600; break; /*case 3686400: cflag |= B3686400; break;*/ default: dbg("%s - Baud rate is not supported, " "using 9600 baud", __FUNCTION__); cflag |= B9600; cp2101_set_config_single(port, CP2101_BAUDRATE, (BAUD_RATE_GEN_FREQ/9600)); break; } cp2101_get_config(port, CP2101_BITS, &bits, 2); cflag &= ~CSIZE; switch(bits & BITS_DATA_MASK) { case BITS_DATA_5: dbg("%s - data bits = 5", __FUNCTION__); cflag |= CS5; break; case BITS_DATA_6: dbg("%s - data bits = 6", __FUNCTION__); cflag |= CS6; break; case BITS_DATA_7: dbg("%s - data bits = 7", __FUNCTION__); cflag |= CS7; break; case BITS_DATA_8: dbg("%s - data bits = 8", __FUNCTION__); cflag |= CS8; break; case BITS_DATA_9: dbg("%s - data bits = 9 (not supported, " "using 8 data bits)", __FUNCTION__); cflag |= CS8; bits &= ~BITS_DATA_MASK; bits |= BITS_DATA_8; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; default: dbg("%s - Unknown number of data bits, " "using 8", __FUNCTION__); cflag |= CS8; bits &= ~BITS_DATA_MASK; bits |= BITS_DATA_8; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; } switch(bits & BITS_PARITY_MASK) { case BITS_PARITY_NONE: dbg("%s - parity = NONE", __FUNCTION__); cflag &= ~PARENB; break; case BITS_PARITY_ODD: dbg("%s - parity = ODD", __FUNCTION__); cflag |= (PARENB|PARODD); break; case BITS_PARITY_EVEN: dbg("%s - parity = EVEN", __FUNCTION__); cflag &= ~PARODD; cflag |= PARENB; break; case BITS_PARITY_MARK: dbg("%s - parity = MARK (not supported, " "disabling parity)", __FUNCTION__); cflag &= ~PARENB; bits &= ~BITS_PARITY_MASK; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; case BITS_PARITY_SPACE: dbg("%s - parity = SPACE (not supported, " "disabling parity)", __FUNCTION__); cflag &= ~PARENB; bits &= ~BITS_PARITY_MASK; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; default: dbg("%s - Unknown parity mode, " "disabling parity", __FUNCTION__); cflag &= ~PARENB; bits &= ~BITS_PARITY_MASK; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; } cflag &= ~CSTOPB; switch(bits & BITS_STOP_MASK) { case BITS_STOP_1: dbg("%s - stop bits = 1", __FUNCTION__); break; case BITS_STOP_1_5: dbg("%s - stop bits = 1.5 (not supported, " "using 1 stop bit)", __FUNCTION__); bits &= ~BITS_STOP_MASK; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; case BITS_STOP_2: dbg("%s - stop bits = 2", __FUNCTION__); cflag |= CSTOPB; break; default: dbg("%s - Unknown number of stop bits, " "using 1 stop bit", __FUNCTION__); bits &= ~BITS_STOP_MASK; cp2101_set_config(port, CP2101_BITS, &bits, 2); break; } cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); if (modem_ctl[0] & 0x0008) { dbg("%s - flow control = CRTSCTS", __FUNCTION__); cflag |= CRTSCTS; } else { dbg("%s - flow control = NONE", __FUNCTION__); cflag &= ~CRTSCTS; } port->tty->termios->c_cflag = cflag; }