aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/serial/ftdi_sio.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index be845873e23d..381515572235 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -923,6 +923,7 @@ static int ftdi_get_icount(struct tty_struct *tty,
923static int ftdi_ioctl(struct tty_struct *tty, 923static int ftdi_ioctl(struct tty_struct *tty,
924 unsigned int cmd, unsigned long arg); 924 unsigned int cmd, unsigned long arg);
925static void ftdi_break_ctl(struct tty_struct *tty, int break_state); 925static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
926static int ftdi_chars_in_buffer(struct tty_struct *tty);
926 927
927static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base); 928static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
928static unsigned short int ftdi_232am_baud_to_divisor(int baud); 929static unsigned short int ftdi_232am_baud_to_divisor(int baud);
@@ -957,6 +958,7 @@ static struct usb_serial_driver ftdi_sio_device = {
957 .ioctl = ftdi_ioctl, 958 .ioctl = ftdi_ioctl,
958 .set_termios = ftdi_set_termios, 959 .set_termios = ftdi_set_termios,
959 .break_ctl = ftdi_break_ctl, 960 .break_ctl = ftdi_break_ctl,
961 .chars_in_buffer = ftdi_chars_in_buffer,
960}; 962};
961 963
962static struct usb_serial_driver * const serial_drivers[] = { 964static struct usb_serial_driver * const serial_drivers[] = {
@@ -2089,6 +2091,64 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
2089 2091
2090} 2092}
2091 2093
2094static int ftdi_chars_in_buffer(struct tty_struct *tty)
2095{
2096 struct usb_serial_port *port = tty->driver_data;
2097 struct ftdi_private *priv = usb_get_serial_port_data(port);
2098 unsigned long flags;
2099 int chars;
2100 unsigned char *buf;
2101 int ret;
2102
2103 /* Check software buffer (code from
2104 * usb_serial_generic_chars_in_buffer()) */
2105 spin_lock_irqsave(&port->lock, flags);
2106 chars = kfifo_len(&port->write_fifo) + port->tx_bytes;
2107 spin_unlock_irqrestore(&port->lock, flags);
2108
2109 /* Check hardware buffer */
2110 switch (priv->chip_type) {
2111 case FT8U232AM:
2112 case FT232BM:
2113 case FT2232C:
2114 case FT232RL:
2115 case FT2232H:
2116 case FT4232H:
2117 case FT232H:
2118 case FTX:
2119 break;
2120 case SIO:
2121 default:
2122 return chars;
2123 }
2124
2125 buf = kmalloc(2, GFP_KERNEL);
2126 if (!buf) {
2127 dev_err(&port->dev, "kmalloc failed");
2128 return chars;
2129 }
2130
2131 ret = usb_control_msg(port->serial->dev,
2132 usb_rcvctrlpipe(port->serial->dev, 0),
2133 FTDI_SIO_GET_MODEM_STATUS_REQUEST,
2134 FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
2135 0, priv->interface,
2136 buf, 2, WDR_TIMEOUT);
2137
2138 if (ret < 2) {
2139 dev_err(&port->dev, "Unable to read modem and line status: "
2140 "%i\n", ret);
2141 goto chars_in_buffer_out;
2142 }
2143
2144 if (!(buf[1] & FTDI_RS_TEMT))
2145 chars++;
2146
2147chars_in_buffer_out:
2148 kfree(buf);
2149 return chars;
2150}
2151
2092/* old_termios contains the original termios settings and tty->termios contains 2152/* old_termios contains the original termios settings and tty->termios contains
2093 * the new setting to be used 2153 * the new setting to be used
2094 * WARNING: set_termios calls this with old_termios in kernel space 2154 * WARNING: set_termios calls this with old_termios in kernel space