USB: serial: ftdi_sio: fix extreme low-latency setting
[pandora-kernel.git] / drivers / usb / serial / ftdi_sio.c
index ce9f87f..7ff9a09 100644 (file)
@@ -156,13 +156,16 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
  * /sys/bus/usb/ftdi_sio/new_id, then send patch/report!
  */
 static struct usb_device_id id_table_combined [] = {
+       { USB_DEVICE(FTDI_VID, FTDI_BRICK_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_BM_ATOM_NANO_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_EV3CON_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) },
@@ -202,6 +205,8 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
+       { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_LP101_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_P200X_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
@@ -489,6 +494,39 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_4701_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9300_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9301_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9302_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9303_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9304_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9305_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9306_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9307_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9308_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9309_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930A_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930B_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930C_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930D_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930E_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930F_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9310_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9311_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9312_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9313_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9314_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9315_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9316_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9317_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9318_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9319_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931A_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931B_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931C_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931D_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931E_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931F_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
@@ -588,6 +626,13 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2WI_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX3_PID) },
        /*
         * ELV devices:
         */
@@ -627,6 +672,8 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_ELV_TFD128_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_FM3RX_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_WS777_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_PALMSENS_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_IVIUM_XSTAT_PID) },
        { USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
        { USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
        { USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
@@ -679,6 +726,11 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
+       { USB_DEVICE(XSENS_VID, XSENS_AWINDA_DONGLE_PID) },
+       { USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) },
+       { USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) },
+       { USB_DEVICE(XSENS_VID, XSENS_MTDEVBOARD_PID) },
+       { USB_DEVICE(XSENS_VID, XSENS_MTW_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
        { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
@@ -726,7 +778,8 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
-       { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) },
+       { USB_DEVICE(TESTO_VID, TESTO_1_PID) },
+       { USB_DEVICE(TESTO_VID, TESTO_3_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
@@ -743,15 +796,43 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
                .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
        { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
-       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) },
-       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) },
-       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_RTS01_PID) },
+       { USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29A_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29F_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_62B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S01_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_63_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29C_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_81B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_82B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K5D_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K4Y_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K5G_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S05_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_60_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_61_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_62_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_63B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_64_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_65_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_92_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_92D_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_W5R_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_A5R_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_PW1_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
        { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },
+       { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID),
@@ -769,6 +850,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
+       { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) },
        { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
 
        /* Papouch devices based on FTDI chip */
@@ -889,6 +971,70 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
        /* Crucible Devices */
        { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) },
+       /* Cressi Devices */
+       { USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) },
+       /* Brainboxes Devices */
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_001_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_012_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_023_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_034_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_101_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_1_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_2_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_3_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_4_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_5_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_6_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_7_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_8_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_257_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_1_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_2_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_3_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_4_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_313_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_324_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_1_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_2_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_357_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_1_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_2_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_3_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_1_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_2_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_1_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) },
+       { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) },
+       /* ekey Devices */
+       { USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) },
+       /* GE Healthcare devices */
+       { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) },
+       /* Active Research (Actisense) devices */
+       { USB_DEVICE(FTDI_VID, ACTISENSE_NDC_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_USG_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_NGT_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_NGW_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AC_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AD_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AE_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AF_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEAGAUGE_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASWITCH_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_NMEA2000_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ETHERNET_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_WIFI_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) },
+       /* ICP DAS I-756xU devices */
+       { USB_DEVICE(ICPDAS_VID, ICPDAS_I7560U_PID) },
+       { USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) },
+       { USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) },
+       { USB_DEVICE(WICED_VID, WICED_USB20706V2_PID) },
+       { USB_DEVICE(TI_VID, TI_CC3200_LAUNCHPAD_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { },                                    /* Optional parameter entry */
        { }                                     /* Terminating entry */
 };
@@ -1329,10 +1475,13 @@ static int read_latency_timer(struct usb_serial_port *port)
                             FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
                             0, priv->interface,
                             buf, 1, WDR_TIMEOUT);
-       if (rv < 0)
+       if (rv < 1) {
                dev_err(&port->dev, "Unable to read latency timer: %i\n", rv);
-       else
+               if (rv >= 0)
+                       rv = -EIO;
+       } else {
                priv->latency = buf[0];
+       }
 
        kfree(buf);
 
@@ -1525,14 +1674,17 @@ static void ftdi_set_max_packet_size(struct usb_serial_port *port)
        struct usb_device *udev = serial->dev;
 
        struct usb_interface *interface = serial->interface;
-       struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;
+       struct usb_endpoint_descriptor *ep_desc;
 
        unsigned num_endpoints;
-       int i;
+       unsigned i;
 
        num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
        dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
 
+       if (!num_endpoints)
+               return;
+
        /* NOTE: some customers have programmed FT232R/FT245R devices
         * with an endpoint size of 0 - not good.  In this case, we
         * want to override the endpoint descriptor setting and use a
@@ -1712,8 +1864,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
        mutex_init(&priv->cfg_lock);
        memset(&priv->icount, 0x00, sizeof(priv->icount));
 
-       priv->flags = ASYNC_LOW_LATENCY;
-
        if (quirk && quirk->port_probe)
                quirk->port_probe(priv);
 
@@ -1813,8 +1963,12 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
 
        dbg("%s", __func__);
 
-       if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
-           (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2")))
+       if (udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems"))
+               return ftdi_jtag_probe(serial);
+
+       if (udev->product &&
+               (!strcmp(udev->product, "BeagleBone/XDS100V2") ||
+                !strcmp(udev->product, "SNAP Connect E10")))
                return ftdi_jtag_probe(serial);
 
        return 0;
@@ -2167,6 +2321,30 @@ static void ftdi_set_termios(struct tty_struct *tty,
                termios->c_cflag |= CRTSCTS;
        }
 
+       /*
+        * All FTDI UART chips are limited to CS7/8. We shouldn't pretend to
+        * support CS5/6 and revert the CSIZE setting instead.
+        *
+        * CS5 however is used to control some smartcard readers which abuse
+        * this limitation to switch modes. Original FTDI chips fall back to
+        * eight data bits.
+        *
+        * TODO: Implement a quirk to only allow this with mentioned
+        *       readers. One I know of (Argolis Smartreader V1)
+        *       returns "USB smartcard server" as iInterface string.
+        *       The vendor didn't bother with a custom VID/PID of
+        *       course.
+        */
+       if (C_CSIZE(tty) == CS6) {
+               dev_warn(&port->dev, "requested CSIZE setting not supported\n");
+
+               termios->c_cflag &= ~CSIZE;
+               if (old_termios)
+                       termios->c_cflag |= old_termios->c_cflag & CSIZE;
+               else
+                       termios->c_cflag |= CS8;
+       }
+
        cflag = termios->c_cflag;
 
        if (!old_termios)
@@ -2203,13 +2381,19 @@ no_skip:
        } else {
                urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE;
        }
-       if (cflag & CSIZE) {
-               switch (cflag & CSIZE) {
-               case CS7: urb_value |= 7; dbg("Setting CS7"); break;
-               case CS8: urb_value |= 8; dbg("Setting CS8"); break;
-               default:
-                       dev_err(&port->dev, "CSIZE was set but not CS7-CS8\n");
-               }
+       switch (cflag & CSIZE) {
+       case CS5:
+               dev_dbg(&port->dev, "Setting CS5 quirk\n");
+               break;
+       case CS7:
+               urb_value |= 7;
+               dev_dbg(&port->dev, "Setting CS7\n");
+               break;
+       default:
+       case CS8:
+               urb_value |= 8;
+               dev_dbg(&port->dev, "Setting CS8\n");
+               break;
        }
 
        /* This is needed by the break command since it uses the same command
@@ -2359,8 +2543,13 @@ static int ftdi_tiocmget(struct tty_struct *tty)
                        FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
                        0, priv->interface,
                        buf, len, WDR_TIMEOUT);
-       if (ret < 0)
+
+       /* NOTE: We allow short responses and handle that below. */
+       if (ret < 1) {
+               if (ret >= 0)
+                       ret = -EIO;
                goto out;
+       }
 
        ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
                (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |