aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/ftdi_sio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r--drivers/usb/serial/ftdi_sio.c82
1 files changed, 71 insertions, 11 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index be845873e23d..0a373b3ae96a 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -73,7 +73,6 @@ struct ftdi_private {
73 char prev_status; /* Used for TIOCMIWAIT */ 73 char prev_status; /* Used for TIOCMIWAIT */
74 bool dev_gone; /* Used to abort TIOCMIWAIT */ 74 bool dev_gone; /* Used to abort TIOCMIWAIT */
75 char transmit_empty; /* If transmitter is empty or not */ 75 char transmit_empty; /* If transmitter is empty or not */
76 struct usb_serial_port *port;
77 __u16 interface; /* FT2232C, FT2232H or FT4232H port interface 76 __u16 interface; /* FT2232C, FT2232H or FT4232H port interface
78 (0 for FT232/245) */ 77 (0 for FT232/245) */
79 78
@@ -192,6 +191,7 @@ static struct usb_device_id id_table_combined [] = {
192 { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) }, 191 { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
193 { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) }, 192 { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
194 { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) }, 193 { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) },
194 { USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) },
195 { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, 195 { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
196 { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, 196 { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
197 { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, 197 { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
@@ -923,6 +923,9 @@ 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);
927static int ftdi_get_modem_status(struct tty_struct *tty,
928 unsigned char status[2]);
926 929
927static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base); 930static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
928static unsigned short int ftdi_232am_baud_to_divisor(int baud); 931static unsigned short int ftdi_232am_baud_to_divisor(int baud);
@@ -957,6 +960,7 @@ static struct usb_serial_driver ftdi_sio_device = {
957 .ioctl = ftdi_ioctl, 960 .ioctl = ftdi_ioctl,
958 .set_termios = ftdi_set_termios, 961 .set_termios = ftdi_set_termios,
959 .break_ctl = ftdi_break_ctl, 962 .break_ctl = ftdi_break_ctl,
963 .chars_in_buffer = ftdi_chars_in_buffer,
960}; 964};
961 965
962static struct usb_serial_driver * const serial_drivers[] = { 966static struct usb_serial_driver * const serial_drivers[] = {
@@ -1090,6 +1094,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
1090 __func__, 1094 __func__,
1091 (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", 1095 (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
1092 (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged"); 1096 (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged");
1097 rv = usb_translate_errors(rv);
1093 } else { 1098 } else {
1094 dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__, 1099 dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__,
1095 (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", 1100 (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
@@ -1682,7 +1687,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
1682 1687
1683 kref_init(&priv->kref); 1688 kref_init(&priv->kref);
1684 mutex_init(&priv->cfg_lock); 1689 mutex_init(&priv->cfg_lock);
1685 memset(&priv->icount, 0x00, sizeof(priv->icount));
1686 init_waitqueue_head(&priv->delta_msr_wait); 1690 init_waitqueue_head(&priv->delta_msr_wait);
1687 1691
1688 priv->flags = ASYNC_LOW_LATENCY; 1692 priv->flags = ASYNC_LOW_LATENCY;
@@ -1691,7 +1695,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
1691 if (quirk && quirk->port_probe) 1695 if (quirk && quirk->port_probe)
1692 quirk->port_probe(priv); 1696 quirk->port_probe(priv);
1693 1697
1694 priv->port = port;
1695 usb_set_serial_port_data(port, priv); 1698 usb_set_serial_port_data(port, priv);
1696 1699
1697 ftdi_determine_type(port); 1700 ftdi_determine_type(port);
@@ -1781,7 +1784,7 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
1781 struct usb_device *udev = serial->dev; 1784 struct usb_device *udev = serial->dev;
1782 1785
1783 if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) || 1786 if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
1784 (udev->product && !strcmp(udev->product, "BeagleBone/XDS100"))) 1787 (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2")))
1785 return ftdi_jtag_probe(serial); 1788 return ftdi_jtag_probe(serial);
1786 1789
1787 return 0; 1790 return 0;
@@ -2089,6 +2092,29 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
2089 2092
2090} 2093}
2091 2094
2095static int ftdi_chars_in_buffer(struct tty_struct *tty)
2096{
2097 struct usb_serial_port *port = tty->driver_data;
2098 int chars;
2099 unsigned char buf[2];
2100 int ret;
2101
2102 chars = usb_serial_generic_chars_in_buffer(tty);
2103 if (chars)
2104 goto out;
2105
2106 /* Check if hardware buffer is empty. */
2107 ret = ftdi_get_modem_status(tty, buf);
2108 if (ret == 2) {
2109 if (!(buf[1] & FTDI_RS_TEMT))
2110 chars = 1;
2111 }
2112out:
2113 dev_dbg(&port->dev, "%s - %d\n", __func__, chars);
2114
2115 return chars;
2116}
2117
2092/* old_termios contains the original termios settings and tty->termios contains 2118/* old_termios contains the original termios settings and tty->termios contains
2093 * the new setting to be used 2119 * the new setting to be used
2094 * WARNING: set_termios calls this with old_termios in kernel space 2120 * WARNING: set_termios calls this with old_termios in kernel space
@@ -2272,7 +2298,14 @@ no_c_cflag_changes:
2272 } 2298 }
2273} 2299}
2274 2300
2275static int ftdi_tiocmget(struct tty_struct *tty) 2301/*
2302 * Get modem-control status.
2303 *
2304 * Returns the number of status bytes retrieved (device dependant), or
2305 * negative error code.
2306 */
2307static int ftdi_get_modem_status(struct tty_struct *tty,
2308 unsigned char status[2])
2276{ 2309{
2277 struct usb_serial_port *port = tty->driver_data; 2310 struct usb_serial_port *port = tty->driver_data;
2278 struct ftdi_private *priv = usb_get_serial_port_data(port); 2311 struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -2312,16 +2345,43 @@ static int ftdi_tiocmget(struct tty_struct *tty)
2312 FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 2345 FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
2313 0, priv->interface, 2346 0, priv->interface,
2314 buf, len, WDR_TIMEOUT); 2347 buf, len, WDR_TIMEOUT);
2315 if (ret < 0) 2348 if (ret < 0) {
2349 dev_err(&port->dev, "failed to get modem status: %d\n", ret);
2350 ret = usb_translate_errors(ret);
2316 goto out; 2351 goto out;
2352 }
2317 2353
2318 ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | 2354 status[0] = buf[0];
2319 (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | 2355 if (ret > 1)
2320 (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | 2356 status[1] = buf[1];
2321 (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | 2357 else
2322 priv->last_dtr_rts; 2358 status[1] = 0;
2359
2360 dev_dbg(&port->dev, "%s - 0x%02x%02x\n", __func__, status[0],
2361 status[1]);
2323out: 2362out:
2324 kfree(buf); 2363 kfree(buf);
2364
2365 return ret;
2366}
2367
2368static int ftdi_tiocmget(struct tty_struct *tty)
2369{
2370 struct usb_serial_port *port = tty->driver_data;
2371 struct ftdi_private *priv = usb_get_serial_port_data(port);
2372 unsigned char buf[2];
2373 int ret;
2374
2375 ret = ftdi_get_modem_status(tty, buf);
2376 if (ret < 0)
2377 return ret;
2378
2379 ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
2380 (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
2381 (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
2382 (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) |
2383 priv->last_dtr_rts;
2384
2325 return ret; 2385 return ret;
2326} 2386}
2327 2387