diff options
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 84 |
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, | |||
923 | static int ftdi_ioctl(struct tty_struct *tty, | 925 | static int ftdi_ioctl(struct tty_struct *tty, |
924 | unsigned int cmd, unsigned long arg); | 926 | unsigned int cmd, unsigned long arg); |
925 | static void ftdi_break_ctl(struct tty_struct *tty, int break_state); | 927 | static void ftdi_break_ctl(struct tty_struct *tty, int break_state); |
928 | static int ftdi_chars_in_buffer(struct tty_struct *tty); | ||
929 | static int ftdi_get_modem_status(struct tty_struct *tty, | ||
930 | unsigned char status[2]); | ||
926 | 931 | ||
927 | static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base); | 932 | static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base); |
928 | static unsigned short int ftdi_232am_baud_to_divisor(int baud); | 933 | static 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 | ||
962 | static struct usb_serial_driver * const serial_drivers[] = { | 968 | static 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 | ||
2097 | static 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 | } | ||
2114 | out: | ||
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 | ||
2275 | static 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 | */ | ||
2309 | static 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]); | ||
2323 | out: | 2364 | out: |
2324 | kfree(buf); | 2365 | kfree(buf); |
2366 | |||
2367 | return ret; | ||
2368 | } | ||
2369 | |||
2370 | static 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 | ||