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.c84
1 files changed, 73 insertions, 11 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index be845873e23d..ba68835d06a6 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) },
@@ -875,6 +875,8 @@ static struct usb_device_id id_table_combined [] = {
875 { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), 875 { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
876 .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 876 .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
877 { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, 877 { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
878 /* Crucible Devices */
879 { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) },
878 { }, /* Optional parameter entry */ 880 { }, /* Optional parameter entry */
879 { } /* Terminating entry */ 881 { } /* Terminating entry */
880}; 882};
@@ -923,6 +925,9 @@ static int ftdi_get_icount(struct tty_struct *tty,
923static int ftdi_ioctl(struct tty_struct *tty, 925static int ftdi_ioctl(struct tty_struct *tty,
924 unsigned int cmd, unsigned long arg); 926 unsigned int cmd, unsigned long arg);
925static void ftdi_break_ctl(struct tty_struct *tty, int break_state); 927static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
928static int ftdi_chars_in_buffer(struct tty_struct *tty);
929static int ftdi_get_modem_status(struct tty_struct *tty,
930 unsigned char status[2]);
926 931
927static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base); 932static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
928static unsigned short int ftdi_232am_baud_to_divisor(int baud); 933static unsigned short int ftdi_232am_baud_to_divisor(int baud);
@@ -957,6 +962,7 @@ static struct usb_serial_driver ftdi_sio_device = {
957 .ioctl = ftdi_ioctl, 962 .ioctl = ftdi_ioctl,
958 .set_termios = ftdi_set_termios, 963 .set_termios = ftdi_set_termios,
959 .break_ctl = ftdi_break_ctl, 964 .break_ctl = ftdi_break_ctl,
965 .chars_in_buffer = ftdi_chars_in_buffer,
960}; 966};
961 967
962static struct usb_serial_driver * const serial_drivers[] = { 968static struct usb_serial_driver * const serial_drivers[] = {
@@ -1090,6 +1096,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
1090 __func__, 1096 __func__,
1091 (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", 1097 (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
1092 (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged"); 1098 (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged");
1099 rv = usb_translate_errors(rv);
1093 } else { 1100 } else {
1094 dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__, 1101 dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__,
1095 (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", 1102 (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
@@ -1682,7 +1689,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
1682 1689
1683 kref_init(&priv->kref); 1690 kref_init(&priv->kref);
1684 mutex_init(&priv->cfg_lock); 1691 mutex_init(&priv->cfg_lock);
1685 memset(&priv->icount, 0x00, sizeof(priv->icount));
1686 init_waitqueue_head(&priv->delta_msr_wait); 1692 init_waitqueue_head(&priv->delta_msr_wait);
1687 1693
1688 priv->flags = ASYNC_LOW_LATENCY; 1694 priv->flags = ASYNC_LOW_LATENCY;
@@ -1691,7 +1697,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
1691 if (quirk && quirk->port_probe) 1697 if (quirk && quirk->port_probe)
1692 quirk->port_probe(priv); 1698 quirk->port_probe(priv);
1693 1699
1694 priv->port = port;
1695 usb_set_serial_port_data(port, priv); 1700 usb_set_serial_port_data(port, priv);
1696 1701
1697 ftdi_determine_type(port); 1702 ftdi_determine_type(port);
@@ -1781,7 +1786,7 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
1781 struct usb_device *udev = serial->dev; 1786 struct usb_device *udev = serial->dev;
1782 1787
1783 if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) || 1788 if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
1784 (udev->product && !strcmp(udev->product, "BeagleBone/XDS100"))) 1789 (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2")))
1785 return ftdi_jtag_probe(serial); 1790 return ftdi_jtag_probe(serial);
1786 1791
1787 return 0; 1792 return 0;
@@ -2089,6 +2094,29 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
2089 2094
2090} 2095}
2091 2096
2097static int ftdi_chars_in_buffer(struct tty_struct *tty)
2098{
2099 struct usb_serial_port *port = tty->driver_data;
2100 int chars;
2101 unsigned char buf[2];
2102 int ret;
2103
2104 chars = usb_serial_generic_chars_in_buffer(tty);
2105 if (chars)
2106 goto out;
2107
2108 /* Check if hardware buffer is empty. */
2109 ret = ftdi_get_modem_status(tty, buf);
2110 if (ret == 2) {
2111 if (!(buf[1] & FTDI_RS_TEMT))
2112 chars = 1;
2113 }
2114out:
2115 dev_dbg(&port->dev, "%s - %d\n", __func__, chars);
2116
2117 return chars;
2118}
2119
2092/* old_termios contains the original termios settings and tty->termios contains 2120/* old_termios contains the original termios settings and tty->termios contains
2093 * the new setting to be used 2121 * the new setting to be used
2094 * WARNING: set_termios calls this with old_termios in kernel space 2122 * WARNING: set_termios calls this with old_termios in kernel space
@@ -2272,7 +2300,14 @@ no_c_cflag_changes:
2272 } 2300 }
2273} 2301}
2274 2302
2275static int ftdi_tiocmget(struct tty_struct *tty) 2303/*
2304 * Get modem-control status.
2305 *
2306 * Returns the number of status bytes retrieved (device dependant), or
2307 * negative error code.
2308 */
2309static int ftdi_get_modem_status(struct tty_struct *tty,
2310 unsigned char status[2])
2276{ 2311{
2277 struct usb_serial_port *port = tty->driver_data; 2312 struct usb_serial_port *port = tty->driver_data;
2278 struct ftdi_private *priv = usb_get_serial_port_data(port); 2313 struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -2312,16 +2347,43 @@ static int ftdi_tiocmget(struct tty_struct *tty)
2312 FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 2347 FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
2313 0, priv->interface, 2348 0, priv->interface,
2314 buf, len, WDR_TIMEOUT); 2349 buf, len, WDR_TIMEOUT);
2315 if (ret < 0) 2350 if (ret < 0) {
2351 dev_err(&port->dev, "failed to get modem status: %d\n", ret);
2352 ret = usb_translate_errors(ret);
2316 goto out; 2353 goto out;
2354 }
2317 2355
2318 ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | 2356 status[0] = buf[0];
2319 (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | 2357 if (ret > 1)
2320 (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | 2358 status[1] = buf[1];
2321 (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | 2359 else
2322 priv->last_dtr_rts; 2360 status[1] = 0;
2361
2362 dev_dbg(&port->dev, "%s - 0x%02x%02x\n", __func__, status[0],
2363 status[1]);
2323out: 2364out:
2324 kfree(buf); 2365 kfree(buf);
2366
2367 return ret;
2368}
2369
2370static int ftdi_tiocmget(struct tty_struct *tty)
2371{
2372 struct usb_serial_port *port = tty->driver_data;
2373 struct ftdi_private *priv = usb_get_serial_port_data(port);
2374 unsigned char buf[2];
2375 int ret;
2376
2377 ret = ftdi_get_modem_status(tty, buf);
2378 if (ret < 0)
2379 return ret;
2380
2381 ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
2382 (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
2383 (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
2384 (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) |
2385 priv->last_dtr_rts;
2386
2325 return ret; 2387 return ret;
2326} 2388}
2327 2389