USB: ftdi: support NDI devices

It enhances the driver for FTDI-based USB serial adapters to recognize and
support Northern Digital Inc (NDI) measurement equipment. NDI has been
providing this patch for various kernel flavors for several years and we would
like to see these changes built in to the driver so that our equipement works
without the need for customers to patch the kernel themselves.

The patch makes small modifications to 2 files: ./drivers/usb/serial/ftdi_sio.c
and ./drivers/usb/serial/ftdi_sio.h. It accomplishes 3 things:

1. Define the VID and PIDs to allow the driver to recognize the NDI devices.
2. Map the 19200 baud rate setting to our higher baud rate of 1.2Mb
We would have chosen to map 38400 to the higher rate, similar to what
several other vendors have done, but some of our legacy customers actually
use 38400, therefore we remap 19200 to the higher rate.
3. We set the default transmit latency in the FTDI chip to 1ms for our devices.
Our devices are typically polled at 60Hz and the default ftdi latency
seriously affects turn-around time and results in missed data frames. We
have created a modprobe option that allows this setting to be increased.
This has proven necessary particularly in some virtualized environments.

Signed-off-by: Martin P. Geleynse <mgeleyns@ndigital.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>


authored by Martin Geleynse and committed by Greg Kroah-Hartman b760dac2 e12df02a

+69 -4
+60 -1
drivers/usb/serial/ftdi_sio.c
··· 107 107 108 108 static int ftdi_jtag_probe(struct usb_serial *serial); 109 109 static int ftdi_mtxorb_hack_setup(struct usb_serial *serial); 110 + static int ftdi_NDI_device_setup(struct usb_serial *serial); 110 111 static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); 111 112 static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); 112 113 ··· 117 116 118 117 static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = { 119 118 .probe = ftdi_mtxorb_hack_setup, 119 + }; 120 + 121 + static struct ftdi_sio_quirk ftdi_NDI_device_quirk = { 122 + .probe = ftdi_NDI_device_setup, 120 123 }; 121 124 122 125 static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { ··· 653 648 { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, 654 649 { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, 655 650 { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, 651 + { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID), 652 + .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, 653 + { USB_DEVICE(FTDI_VID, FTDI_NDI_SPECTRA_SCU_PID), 654 + .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, 655 + { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_2_PID), 656 + .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, 657 + { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_3_PID), 658 + .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, 659 + { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID), 660 + .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, 656 661 { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, 657 662 { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, 658 663 { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, ··· 686 671 { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, 687 672 { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, 688 673 { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, 689 - { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) }, 690 674 { USB_DEVICE(ATMEL_VID, STK541_PID) }, 691 675 { USB_DEVICE(DE_VID, STB_PID) }, 692 676 { USB_DEVICE(DE_VID, WHT_PID) }, ··· 1041 1027 case FT2232C: /* FT2232C chip */ 1042 1028 case FT232RL: 1043 1029 if (baud <= 3000000) { 1030 + __u16 product_id = le16_to_cpu( 1031 + port->serial->dev->descriptor.idProduct); 1032 + if (((FTDI_NDI_HUC_PID == product_id) || 1033 + (FTDI_NDI_SPECTRA_SCU_PID == product_id) || 1034 + (FTDI_NDI_FUTURE_2_PID == product_id) || 1035 + (FTDI_NDI_FUTURE_3_PID == product_id) || 1036 + (FTDI_NDI_AURORA_SCU_PID == product_id)) && 1037 + (baud == 19200)) { 1038 + baud = 1200000; 1039 + } 1044 1040 div_value = ftdi_232bm_baud_to_divisor(baud); 1045 1041 } else { 1046 1042 dbg("%s - Baud rate too high!", __func__); ··· 1580 1556 priv->force_baud = 38400; 1581 1557 priv->force_rtscts = 1; 1582 1558 } /* ftdi_HE_TIRA1_setup */ 1559 + 1560 + /* 1561 + * Module parameter to control latency timer for NDI FTDI-based USB devices. 1562 + * If this value is not set in modprobe.conf.local its value will be set to 1ms. 1563 + */ 1564 + static int ndi_latency_timer = 1; 1565 + 1566 + /* Setup for the NDI FTDI-based USB devices, which requires hardwired 1567 + * baudrate (19200 gets mapped to 1200000). 1568 + * 1569 + * Called from usbserial:serial_probe. 1570 + */ 1571 + static int ftdi_NDI_device_setup(struct usb_serial *serial) 1572 + { 1573 + struct usb_device *udev = serial->dev; 1574 + int latency = ndi_latency_timer; 1575 + int rv = 0; 1576 + char buf[1]; 1577 + 1578 + if (latency == 0) 1579 + latency = 1; 1580 + if (latency > 99) 1581 + latency = 99; 1582 + 1583 + dbg("%s setting NDI device latency to %d", __func__, latency); 1584 + dev_info(&udev->dev, "NDI device with a latency value of %d", latency); 1585 + 1586 + rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 1587 + FTDI_SIO_SET_LATENCY_TIMER_REQUEST, 1588 + FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, 1589 + latency, 0, buf, 0, WDR_TIMEOUT); 1590 + return 0; 1591 + } 1583 1592 1584 1593 /* 1585 1594 * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko ··· 2683 2626 module_param(product, ushort, 0); 2684 2627 MODULE_PARM_DESC(product, "User specified product ID"); 2685 2628 2629 + module_param(ndi_latency_timer, int, S_IRUGO | S_IWUSR); 2630 + MODULE_PARM_DESC(ndi_latency_timer, "NDI device latency timer override");
+9 -3
drivers/usb/serial/ftdi_sio.h
··· 740 740 #define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ 741 741 742 742 /* 743 + * NDI (www.ndigital.com) product ids 744 + */ 745 + #define FTDI_NDI_HUC_PID 0xDA70 /* NDI Host USB Converter */ 746 + #define FTDI_NDI_SPECTRA_SCU_PID 0xDA71 /* NDI Spectra SCU */ 747 + #define FTDI_NDI_FUTURE_2_PID 0xDA72 /* NDI future device #2 */ 748 + #define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */ 749 + #define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ 750 + 751 + /* 743 752 * Posiflex inc retail equipment (http://www.posiflex.com.tw) 744 753 */ 745 754 #define POSIFLEX_VID 0x0d3a /* Vendor ID */ ··· 860 851 */ 861 852 #define TML_VID 0x1B91 /* Vendor ID */ 862 853 #define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */ 863 - 864 - /* NDI Polaris System */ 865 - #define FTDI_NDI_HUC_PID 0xDA70 866 854 867 855 /* Propox devices */ 868 856 #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738