2005-04-17 06:20:36 +08:00
/*
* USB FTDI SIO driver
*
2010-05-06 05:44:17 +08:00
* Copyright ( C ) 2009 - 2010
* Johan Hovold ( jhovold @ gmail . com )
2006-10-14 06:57:58 +08:00
* Copyright ( C ) 1999 - 2001
* Greg Kroah - Hartman ( greg @ kroah . com )
2005-04-17 06:20:36 +08:00
* Bill Ryder ( bryder @ sgi . com )
* Copyright ( C ) 2002
* Kuba Ober ( kuba @ mareimbrium . org )
*
2006-10-14 06:57:58 +08:00
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
2005-04-17 06:20:36 +08:00
*
2008-07-22 18:11:23 +08:00
* See Documentation / usb / usb - serial . txt for more information on using this
* driver
2005-04-17 06:20:36 +08:00
*
* See http : //ftdi-usb-sio.sourceforge.net for upto date testing info
* and extra documentation
*
2002-04-10 03:14:34 +08:00
* Change entries from 2004 and earlier can be found in versions of this
* file in kernel versions prior to the 2.6 .24 release .
2005-04-17 06:20:36 +08:00
*
*/
/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
/* Thanx to FTDI for so kindly providing details of the protocol required */
/* to talk to the device */
2008-07-22 18:11:23 +08:00
/* Thanx to gkh and the rest of the usb dev group for all code I have
assimilated : - ) */
2005-04-17 06:20:36 +08:00
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/init.h>
# include <linux/slab.h>
# include <linux/tty.h>
# include <linux/tty_driver.h>
# include <linux/tty_flip.h>
# include <linux/module.h>
# include <linux/spinlock.h>
2010-02-02 23:18:28 +08:00
# include <linux/mutex.h>
2008-07-22 18:11:23 +08:00
# include <linux/uaccess.h>
2005-04-17 06:20:36 +08:00
# include <linux/usb.h>
# include <linux/serial.h>
2006-07-12 12:22:58 +08:00
# include <linux/usb/serial.h>
2005-04-17 06:20:36 +08:00
# include "ftdi_sio.h"
2009-12-17 04:45:10 +08:00
# include "ftdi_sio_ids.h"
2005-04-17 06:20:36 +08:00
/*
* Version Information
*/
2010-05-06 05:44:17 +08:00
# define DRIVER_VERSION "v1.6.0"
# define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>, Andreas Mohr, Johan Hovold <jhovold@gmail.com>"
2005-04-17 06:20:36 +08:00
# define DRIVER_DESC "USB FTDI Serial Converters Driver"
static int debug ;
2005-07-29 01:40:32 +08:00
static __u16 vendor = FTDI_VID ;
static __u16 product ;
2005-04-17 06:20:36 +08:00
2007-07-10 03:03:08 +08:00
struct ftdi_private {
2009-04-30 22:06:19 +08:00
struct kref kref ;
2010-05-18 01:33:41 +08:00
enum ftdi_chip_type chip_type ;
2008-07-22 18:11:23 +08:00
/* type of device, either SIO or FT8U232AM */
2007-07-10 03:03:08 +08:00
int baud_base ; /* baud base clock for divisor setting */
2008-07-22 18:11:23 +08:00
int custom_divisor ; /* custom_divisor kludge, this is for
baud_base ( different from what goes to the
chip ! ) */
2007-07-10 03:03:08 +08:00
__u16 last_set_data_urb_value ;
2008-07-22 18:11:23 +08:00
/* the last data state set - needed for doing
* a break
*/
2007-07-10 03:03:08 +08:00
int flags ; /* some ASYNC_xxxx flags are supported */
unsigned long last_dtr_rts ; /* saved modem control outputs */
2008-07-22 18:11:23 +08:00
wait_queue_head_t delta_msr_wait ; /* Used for TIOCMIWAIT */
2007-07-10 03:03:08 +08:00
char prev_status , diff_status ; /* Used for TIOCMIWAIT */
struct usb_serial_port * port ;
2009-04-09 22:03:09 +08:00
__u16 interface ; /* FT2232C, FT2232H or FT4232H port interface
( 0 for FT232 / 245 ) */
2007-07-10 03:03:08 +08:00
2008-07-22 18:11:23 +08:00
speed_t force_baud ; /* if non-zero, force the baud rate to
this value */
int force_rtscts ; /* if non-zero, force RTS-CTS to always
be enabled */
2007-07-10 03:03:08 +08:00
2009-06-11 20:55:34 +08:00
unsigned int latency ; /* latency setting in use */
2009-05-01 18:48:45 +08:00
unsigned short max_packet_size ;
2010-03-14 01:35:14 +08:00
struct mutex cfg_lock ; /* Avoid mess by parallel calls of config ioctl() and change_speed() */
2007-07-10 03:03:08 +08:00
} ;
2005-06-20 23:45:42 +08:00
/* struct ftdi_sio_quirk is used by devices requiring special attention. */
struct ftdi_sio_quirk {
2007-05-05 09:23:24 +08:00
int ( * probe ) ( struct usb_serial * ) ;
2008-07-22 18:11:23 +08:00
/* Special settings for probed ports. */
void ( * port_probe ) ( struct ftdi_private * ) ;
2005-06-20 23:45:42 +08:00
} ;
2008-07-22 18:11:23 +08:00
static int ftdi_jtag_probe ( struct usb_serial * serial ) ;
static int ftdi_mtxorb_hack_setup ( struct usb_serial * serial ) ;
2009-07-03 01:10:35 +08:00
static int ftdi_NDI_device_setup ( struct usb_serial * serial ) ;
2008-07-22 18:11:23 +08:00
static void ftdi_USB_UIRT_setup ( struct ftdi_private * priv ) ;
static void ftdi_HE_TIRA1_setup ( struct ftdi_private * priv ) ;
2005-06-20 23:45:42 +08:00
2008-01-01 22:08:35 +08:00
static struct ftdi_sio_quirk ftdi_jtag_quirk = {
. probe = ftdi_jtag_probe ,
2007-05-05 09:23:24 +08:00
} ;
2008-03-02 02:49:59 +08:00
static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = {
. probe = ftdi_mtxorb_hack_setup ,
} ;
2009-07-03 01:10:35 +08:00
static struct ftdi_sio_quirk ftdi_NDI_device_quirk = {
. probe = ftdi_NDI_device_setup ,
} ;
2005-06-20 23:45:42 +08:00
static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
2007-07-10 03:03:08 +08:00
. port_probe = ftdi_USB_UIRT_setup ,
2005-06-20 23:45:42 +08:00
} ;
static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
2007-07-10 03:03:08 +08:00
. port_probe = ftdi_HE_TIRA1_setup ,
2005-04-17 06:20:36 +08:00
} ;
/*
* The 8U 232 AM has the same API as the sio except for :
* - it can support MUCH higher baudrates ; up to :
* o 921600 for RS232 and 2000000 for RS422 / 485 at 48 MHz
* o 230400 at 12 MHz
* so . . 8U 232 AM ' s baudrate setting codes are different
* - it has a two byte status code .
* - it returns characters every 16 ms ( the FTDI does it every 40 ms )
*
* the bcdDevice value is used to differentiate FT232BM and FT245BM from
* the earlier FT8U232AM and FT8U232BM . For now , include all known VID / PID
* combinations in both tables .
2005-06-20 23:45:42 +08:00
* FIXME : perhaps bcdDevice can also identify 12 MHz FT8U232AM devices ,
* but I don ' t know if those ever went into mass production . [ Ian Abbott ]
2005-04-17 06:20:36 +08:00
*/
2010-01-17 18:45:38 +08:00
/*
* Device ID not listed ? Test via module params product / vendor or
* / sys / bus / usb / ftdi_sio / new_id , then send patch / report !
*/
2005-04-17 06:20:36 +08:00
static struct usb_device_id id_table_combined [ ] = {
2006-08-09 17:48:03 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_AMC232_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CANUSB_PID ) } ,
2008-12-04 23:09:59 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_CANDAPTER_PID ) } ,
2010-01-17 18:45:38 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_NXTCAM_PID ) } ,
2008-04-22 19:25:11 +08:00
{ 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 ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_SCS_DEVICE_3_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_SCS_DEVICE_4_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_SCS_DEVICE_5_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_SCS_DEVICE_6_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_SCS_DEVICE_7_PID ) } ,
2010-07-27 10:44:33 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_USINT_CAT_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_USINT_WKEY_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_USINT_RS232_PID ) } ,
2006-05-04 16:35:49 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ACTZWAVE_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_IRTRANS_PID ) } ,
2006-04-12 02:52:41 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_IPLUS_PID ) } ,
2007-06-22 09:34:23 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_IPLUS2_PID ) } ,
2006-10-20 15:43:53 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_DMX4ALL ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_SIO_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_8U232AM_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_8U232AM_ALT_PID ) } ,
2007-03-05 07:03:26 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_232RL_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_8U2232C_PID ) } ,
2009-04-09 22:03:09 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_4232H_PID ) } ,
2006-06-23 23:36:21 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_MICRO_CHAMELEON_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_RELAIS_PID ) } ,
2007-05-09 01:52:41 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_OPENDCC_PID ) } ,
2009-09-03 17:55:17 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_OPENDCC_SNIFFER_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_OPENDCC_THROTTLE_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_OPENDCC_GATEWAY_PID ) } ,
2010-09-28 18:27:43 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_OPENDCC_GBM_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( INTERBIOMETRICS_VID , INTERBIOMETRICS_IOBOARD_PID ) } ,
{ USB_DEVICE ( INTERBIOMETRICS_VID , INTERBIOMETRICS_MINI_IOBOARD_PID ) } ,
2008-12-07 15:46:04 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_SPROG_II ) } ,
2010-08-20 02:15:20 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_LENZ_LIUSB_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_XF_632_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_XF_634_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_XF_547_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_XF_633_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_XF_631_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_XF_635_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_XF_640_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_XF_642_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_DSS20_PID ) } ,
{ USB_DEVICE ( FTDI_NF_RIC_VID , FTDI_NF_RIC_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_VNHCPCUSB_D_PID ) } ,
2005-06-20 23:45:42 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_MTXORB_0_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_MTXORB_1_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_MTXORB_2_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_MTXORB_3_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_MTXORB_4_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_MTXORB_5_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_MTXORB_6_PID ) } ,
2009-06-20 04:14:42 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_R2000KU_TRUE_RNG ) } ,
2010-11-24 17:56:38 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_VARDAAN_PID ) } ,
2008-07-22 18:11:23 +08:00
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0100_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0101_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0102_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0103_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0104_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0105_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0106_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0107_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0108_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0109_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_010A_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_010B_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_010C_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_010D_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_010E_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_010F_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0110_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0111_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0112_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0113_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0114_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0115_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0116_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0117_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0118_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0119_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_011A_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_011B_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_011C_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_011D_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_011E_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_011F_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0120_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0121_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0122_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0123_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0124_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0125_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0126_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0127_PID ) ,
2008-03-02 02:49:59 +08:00
. driver_info = ( kernel_ulong_t ) & ftdi_mtxorb_hack_quirk } ,
2008-07-22 18:11:23 +08:00
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0128_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0129_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_012A_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_012B_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_012C_PID ) ,
2008-05-22 07:06:26 +08:00
. driver_info = ( kernel_ulong_t ) & ftdi_mtxorb_hack_quirk } ,
2008-07-22 18:11:23 +08:00
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_012D_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_012E_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_012F_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0130_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0131_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0132_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0133_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0134_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0135_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0136_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0137_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0138_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0139_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_013A_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_013B_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_013C_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_013D_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_013E_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_013F_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0140_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0141_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0142_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0143_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0144_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0145_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0146_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0147_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0148_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0149_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_014A_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_014B_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_014C_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_014D_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_014E_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_014F_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0150_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0151_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0152_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0153_PID ) ,
2008-05-22 07:06:26 +08:00
. driver_info = ( kernel_ulong_t ) & ftdi_mtxorb_hack_quirk } ,
2008-07-22 18:11:23 +08:00
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0154_PID ) ,
2008-05-22 07:06:26 +08:00
. driver_info = ( kernel_ulong_t ) & ftdi_mtxorb_hack_quirk } ,
2008-07-22 18:11:23 +08:00
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0155_PID ) ,
2008-05-22 07:06:26 +08:00
. driver_info = ( kernel_ulong_t ) & ftdi_mtxorb_hack_quirk } ,
2008-07-22 18:11:23 +08:00
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0156_PID ) ,
2008-05-22 07:06:26 +08:00
. driver_info = ( kernel_ulong_t ) & ftdi_mtxorb_hack_quirk } ,
2008-07-22 18:11:23 +08:00
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0157_PID ) ,
2008-05-22 07:06:26 +08:00
. driver_info = ( kernel_ulong_t ) & ftdi_mtxorb_hack_quirk } ,
2008-07-22 18:11:23 +08:00
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0158_PID ) ,
2008-05-22 07:06:26 +08:00
. driver_info = ( kernel_ulong_t ) & ftdi_mtxorb_hack_quirk } ,
2008-07-22 18:11:23 +08:00
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0159_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_015A_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_015B_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_015C_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_015D_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_015E_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_015F_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0160_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0161_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0162_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0163_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0164_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0165_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0166_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0167_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0168_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0169_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_016A_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_016B_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_016C_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_016D_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_016E_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_016F_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0170_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0171_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0172_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0173_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0174_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0175_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0176_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0177_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0178_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0179_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_017A_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_017B_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_017C_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_017D_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_017E_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_017F_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0180_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0181_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0182_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0183_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0184_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0185_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0186_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0187_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0188_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0189_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_018A_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_018B_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_018C_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_018D_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_018E_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_018F_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0190_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0191_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0192_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0193_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0194_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0195_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0196_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0197_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0198_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_0199_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_019A_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_019B_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_019C_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_019D_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_019E_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_019F_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01A0_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01A1_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01A2_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01A3_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01A4_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01A5_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01A6_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01A7_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01A8_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01A9_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01AA_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01AB_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01AC_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01AD_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01AE_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01AF_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01B0_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01B1_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01B2_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01B3_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01B4_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01B5_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01B6_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01B7_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01B8_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01B9_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01BA_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01BB_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01BC_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01BD_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01BE_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01BF_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01C0_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01C1_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01C2_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01C3_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01C4_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01C5_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01C6_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01C7_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01C8_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01C9_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01CA_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01CB_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01CC_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01CD_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01CE_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01CF_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01D0_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01D1_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01D2_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01D3_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01D4_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01D5_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01D6_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01D7_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01D8_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01D9_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01DA_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01DB_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01DC_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01DD_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01DE_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01DF_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01E0_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01E1_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01E2_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01E3_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01E4_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01E5_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01E6_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01E7_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01E8_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01E9_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01EA_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01EB_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01EC_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01ED_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01EE_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01EF_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01F0_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01F1_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01F2_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01F3_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01F4_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01F5_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01F6_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01F7_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01F8_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01F9_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01FA_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01FB_PID ) } ,
{ USB_DEVICE ( MTXORB_VID , MTXORB_FTDI_RANGE_01FC_PID ) } ,
{ 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 ) } ,
2005-06-20 23:45:42 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_PERLE_ULTRAPORT_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_PIEGROUP_PID ) } ,
2006-07-19 12:26:54 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_TNC_X_PID ) } ,
2007-03-26 09:08:35 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_USBX_707_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2101_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2102_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2103_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2104_PID ) } ,
2006-09-24 16:52:12 +08:00
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2106_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2201_1_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2201_2_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2202_1_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2202_2_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2203_1_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2203_2_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2401_1_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2401_2_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2401_3_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2401_4_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2402_1_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2402_2_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2402_3_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2402_4_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2403_1_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2403_2_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2403_3_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2403_4_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2801_1_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2801_2_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2801_3_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2801_4_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2801_5_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2801_6_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2801_7_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2801_8_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2802_1_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2802_2_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2802_3_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2802_4_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2802_5_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2802_6_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2802_7_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2802_8_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2803_1_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2803_2_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2803_3_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2803_4_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2803_5_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2803_6_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2803_7_PID ) } ,
{ USB_DEVICE ( SEALEVEL_VID , SEALEVEL_2803_8_PID ) } ,
{ USB_DEVICE ( IDTECH_VID , IDTECH_IDT1221U_PID ) } ,
{ USB_DEVICE ( OCT_VID , OCT_US101_PID ) } ,
2005-06-20 23:45:42 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_HE_TIRA1_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_HE_TIRA1_quirk } ,
{ USB_DEVICE ( FTDI_VID , FTDI_USB_UIRT_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_USB_UIRT_quirk } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( FTDI_VID , PROTEGO_SPECIAL_1 ) } ,
{ USB_DEVICE ( FTDI_VID , PROTEGO_R2X0 ) } ,
{ USB_DEVICE ( FTDI_VID , PROTEGO_SPECIAL_3 ) } ,
{ USB_DEVICE ( FTDI_VID , PROTEGO_SPECIAL_4 ) } ,
2005-06-20 23:45:42 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E808_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E809_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E80A_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E80B_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E80C_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E80D_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E80E_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E80F_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E888_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E889_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E88A_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E88B_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E88C_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E88D_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E88E_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_GUDEADS_E88F_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_UO100_PID ) } ,
2005-05-17 22:12:13 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_UM100_PID ) } ,
2005-08-02 21:01:27 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_UR100_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_ALC8500_PID ) } ,
2005-09-29 20:57:29 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_PYRAMID_PID ) } ,
2005-10-27 03:10:41 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_FHZ1000PC_PID ) } ,
2007-03-01 05:50:52 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_IBS_US485_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_IBS_PICPRO_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_IBS_PCMCIA_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_IBS_PK1_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_IBS_RS232MON_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_IBS_APP70_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_IBS_PEDO_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_IBS_PROD_PID ) } ,
2005-08-02 21:01:27 +08:00
/*
2010-01-17 18:45:38 +08:00
* ELV devices :
2005-08-02 21:01:27 +08:00
*/
2010-01-17 18:45:38 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_USR_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_MSM1_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_KL100_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_WS550_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_EC3000_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_WS888_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_TWS550_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_FEM_PID ) } ,
2007-12-26 01:32:08 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_CLI7000_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_PPS7330_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_TFM100_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_UDF77_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_UIO88_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_UAD8_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_UDA7_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_USI2_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_T1100_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_PCD200_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_ULA200_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_CSI8_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_EM1000DL_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_PCK100_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_RFP500_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_FS20SIG_PID ) } ,
2010-01-17 18:45:38 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_UTP8_PID ) } ,
2007-12-26 01:32:08 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_WS300PC_PID ) } ,
2010-01-17 18:45:38 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_WS444PC_PID ) } ,
2007-12-26 01:32:08 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_FHZ1300PC_PID ) } ,
2008-03-05 05:09:11 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_EM1010PC_PID ) } ,
2007-12-26 01:32:08 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_WS500_PID ) } ,
2008-07-28 21:48:46 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_HS485_PID ) } ,
2010-01-17 18:45:38 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_UMS100_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_TFD128_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_FM3RX_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ELV_WS777_PID ) } ,
2006-10-14 06:57:58 +08:00
{ USB_DEVICE ( FTDI_VID , LINX_SDMUSBQSS_PID ) } ,
{ USB_DEVICE ( FTDI_VID , LINX_MASTERDEVEL2_PID ) } ,
{ USB_DEVICE ( FTDI_VID , LINX_FUTURE_0_PID ) } ,
{ USB_DEVICE ( FTDI_VID , LINX_FUTURE_1_PID ) } ,
{ USB_DEVICE ( FTDI_VID , LINX_FUTURE_2_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CCSICDU20_0_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CCSICDU40_1_PID ) } ,
2006-11-29 05:35:12 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_CCSMACHX_2_PID ) } ,
2009-06-11 00:58:52 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_CCSLOAD_N_GO_3_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CCSICDU64_4_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CCSPRIME8_5_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( FTDI_VID , INSIDE_ACCESSO ) } ,
{ USB_DEVICE ( INTREPID_VID , INTREPID_VALUECAN_PID ) } ,
{ USB_DEVICE ( INTREPID_VID , INTREPID_NEOVI_PID ) } ,
{ USB_DEVICE ( FALCOM_VID , FALCOM_TWIST_PID ) } ,
2005-08-02 21:01:27 +08:00
{ USB_DEVICE ( FALCOM_VID , FALCOM_SAMBA_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_SUUNTO_SPORTS_PID ) } ,
2008-10-04 08:08:43 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_OCEANIC_PID ) } ,
2007-02-27 19:57:12 +08:00
{ USB_DEVICE ( TTI_VID , TTI_QL355P_PID ) } ,
2005-04-29 23:06:14 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_RM_CANVIEW_PID ) } ,
2010-02-22 10:03:11 +08:00
{ USB_DEVICE ( CONTEC_VID , CONTEC_COM1USBH_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( BANDB_VID , BANDB_USOTL4_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_USTL4_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_USO9ML2_PID ) } ,
2009-12-01 22:53:42 +08:00
{ USB_DEVICE ( BANDB_VID , BANDB_USOPTL4_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_USPTL4_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_USO9ML2DR_2_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_USO9ML2DR_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_USOPTL4DR2_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_USOPTL4DR_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_485USB9F_2W_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_485USB9F_4W_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_232USB9M_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_485USBTB_2W_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_485USBTB_4W_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_TTL5USB9M_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_TTL3USB9M_PID ) } ,
{ USB_DEVICE ( BANDB_VID , BANDB_ZZ_PROG1_USB_PID ) } ,
2005-04-17 06:20:36 +08:00
{ USB_DEVICE ( FTDI_VID , EVER_ECO_PRO_CDS ) } ,
2005-04-29 23:06:14 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_4N_GALAXY_DE_1_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_4N_GALAXY_DE_2_PID ) } ,
2005-08-02 21:01:27 +08:00
{ USB_DEVICE ( FTDI_VID , XSENS_CONVERTER_0_PID ) } ,
{ USB_DEVICE ( FTDI_VID , XSENS_CONVERTER_1_PID ) } ,
{ USB_DEVICE ( FTDI_VID , XSENS_CONVERTER_2_PID ) } ,
{ USB_DEVICE ( FTDI_VID , XSENS_CONVERTER_3_PID ) } ,
{ USB_DEVICE ( FTDI_VID , XSENS_CONVERTER_4_PID ) } ,
{ USB_DEVICE ( FTDI_VID , XSENS_CONVERTER_5_PID ) } ,
{ USB_DEVICE ( FTDI_VID , XSENS_CONVERTER_6_PID ) } ,
{ USB_DEVICE ( FTDI_VID , XSENS_CONVERTER_7_PID ) } ,
2005-04-29 23:06:14 +08:00
{ USB_DEVICE ( MOBILITY_VID , MOBILITY_USB_SERIAL_PID ) } ,
2005-06-20 23:45:42 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ACTIVE_ROBOTS_PID ) } ,
2006-02-27 22:05:32 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_MHAM_KW_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_MHAM_YS_PID ) } ,
2005-07-30 03:16:31 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_MHAM_Y6_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_MHAM_Y8_PID ) } ,
2006-02-27 22:05:32 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_MHAM_IC_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_MHAM_DB9_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_MHAM_RS232_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_MHAM_Y9_PID ) } ,
2005-12-14 00:18:47 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_TERATRONIK_VCP_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_TERATRONIK_D2XX_PID ) } ,
2005-07-30 03:16:31 +08:00
{ USB_DEVICE ( EVOLUTION_VID , EVOLUTION_ER1_PID ) } ,
2007-08-08 16:50:17 +08:00
{ USB_DEVICE ( EVOLUTION_VID , EVO_HYBRID_PID ) } ,
{ USB_DEVICE ( EVOLUTION_VID , EVO_RCM4_PID ) } ,
2005-09-24 03:06:50 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ARTEMIS_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_ATIK_ATK16_PID ) } ,
2006-01-09 21:12:40 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ATIK_ATK16C_PID ) } ,
2005-09-24 03:06:50 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ATIK_ATK16HR_PID ) } ,
2006-01-09 21:12:40 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ATIK_ATK16HRC_PID ) } ,
2007-12-26 10:29:33 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ATIK_ATK16IC_PID ) } ,
2005-11-24 07:45:23 +08:00
{ USB_DEVICE ( KOBIL_VID , KOBIL_CONV_B1_PID ) } ,
{ USB_DEVICE ( KOBIL_VID , KOBIL_CONV_KAAN_PID ) } ,
2005-12-09 14:30:59 +08:00
{ USB_DEVICE ( POSIFLEX_VID , POSIFLEX_PP7000_PID ) } ,
2006-01-06 00:20:37 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_TTUSB_PID ) } ,
2006-03-21 22:55:20 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ECLO_COM_1WIRE_PID ) } ,
2006-01-10 01:11:40 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_WESTREX_MODEL_777_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_WESTREX_MODEL_8900F_PID ) } ,
2006-01-03 21:30:31 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_PCDJ_DAC2_PID ) } ,
2006-04-10 12:05:09 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_RRCIRKITS_LOCOBUFFER_PID ) } ,
2006-04-12 22:20:35 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ASK_RDR400_PID ) } ,
2006-03-15 07:44:23 +08:00
{ USB_DEVICE ( ICOM_ID1_VID , ICOM_ID1_PID ) } ,
2006-05-04 18:34:25 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ACG_HFDUAL_PID ) } ,
2006-05-30 19:36:30 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_YEI_SERVOCENTER31_PID ) } ,
2006-06-18 06:09:15 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_THORLABS_PID ) } ,
2006-07-11 17:36:43 +08:00
{ USB_DEVICE ( TESTO_VID , TESTO_USB_INTERFACE_PID ) } ,
2006-09-06 18:15:02 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_GAMMA_SCOUT_PID ) } ,
2006-09-25 21:19:19 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_TACTRIX_OPENPORT_13M_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_TACTRIX_OPENPORT_13S_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_TACTRIX_OPENPORT_13U_PID ) } ,
2006-10-23 05:26:42 +08:00
{ USB_DEVICE ( ELEKTOR_VID , ELEKTOR_FT323R_PID ) } ,
2009-07-03 01:10:35 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_NDI_HUC_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_NDI_device_quirk } ,
{ USB_DEVICE ( FTDI_VID , FTDI_NDI_SPECTRA_SCU_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_NDI_device_quirk } ,
{ USB_DEVICE ( FTDI_VID , FTDI_NDI_FUTURE_2_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_NDI_device_quirk } ,
{ USB_DEVICE ( FTDI_VID , FTDI_NDI_FUTURE_3_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_NDI_device_quirk } ,
{ USB_DEVICE ( FTDI_VID , FTDI_NDI_AURORA_SCU_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_NDI_device_quirk } ,
2007-02-05 06:39:11 +08:00
{ USB_DEVICE ( TELLDUS_VID , TELLDUS_TELLSTICK_PID ) } ,
2010-07-21 21:39:22 +08:00
{ USB_DEVICE ( RTSYSTEMS_VID , RTSYSTEMS_SERIAL_VX7_PID ) } ,
2010-11-18 07:45:43 +08:00
{ USB_DEVICE ( RTSYSTEMS_VID , RTSYSTEMS_CT29B_PID ) } ,
2007-04-26 02:34:28 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_MAXSTREAM_PID ) } ,
2008-08-06 20:25:08 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_PHI_FISCO_PID ) } ,
2007-09-07 04:34:39 +08:00
{ USB_DEVICE ( TML_VID , TML_USB_SERIAL_PID ) } ,
2008-01-18 06:37:46 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_ELSTER_UNICOM_PID ) } ,
2008-03-10 18:38:55 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_PROPOX_JTAGCABLEII_PID ) } ,
2007-05-05 09:23:24 +08:00
{ USB_DEVICE ( OLIMEX_VID , OLIMEX_ARM_USB_OCD_PID ) ,
2008-01-01 22:08:35 +08:00
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
{ USB_DEVICE ( FIC_VID , FIC_NEO1973_DEBUG_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
{ USB_DEVICE ( FTDI_VID , FTDI_OOCDLINK_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
2008-07-30 22:53:41 +08:00
{ USB_DEVICE ( FTDI_VID , LMI_LM3S_DEVEL_BOARD_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
{ USB_DEVICE ( FTDI_VID , LMI_LM3S_EVAL_BOARD_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
2009-07-10 07:06:23 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_TURTELIZER_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
2008-05-16 23:13:56 +08:00
{ USB_DEVICE ( RATOC_VENDOR_ID , RATOC_PRODUCT_ID_USB60F ) } ,
2008-06-24 17:43:13 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_REU_TINY_PID ) } ,
2010-10-12 21:44:24 +08:00
/* Papouch devices based on FTDI chip */
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_SB485_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_AP485_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_SB422_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_SB485_2_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_AP485_2_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_SB422_2_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_SB485S_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_SB485C_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_LEC_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_SB232_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_TMU_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_IRAMP_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_DRAK5_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_QUIDO8x8_PID ) } ,
2008-09-16 21:46:50 +08:00
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_QUIDO4x4_PID ) } ,
2010-10-12 21:44:24 +08:00
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_QUIDO2x2_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_QUIDO10x1_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_QUIDO30x3_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_QUIDO60x3_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_QUIDO2x16_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_QUIDO3x32_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_DRAK6_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_UPSUSB_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_MU_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_SIMUKEY_PID ) } ,
2010-01-27 22:38:34 +08:00
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_AD4USB_PID ) } ,
2010-10-12 21:44:24 +08:00
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_GMUX_PID ) } ,
{ USB_DEVICE ( PAPOUCH_VID , PAPOUCH_GMSR_PID ) } ,
2008-09-23 06:00:09 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_DOMINTELL_DGQG_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_DOMINTELL_DUSB_PID ) } ,
2009-01-13 07:05:59 +08:00
{ USB_DEVICE ( ALTI2_VID , ALTI2_N3_PID ) } ,
2009-01-09 18:48:16 +08:00
{ USB_DEVICE ( FTDI_VID , DIEBOLD_BCS_SE923_PID ) } ,
2009-03-06 06:09:22 +08:00
{ USB_DEVICE ( ATMEL_VID , STK541_PID ) } ,
{ USB_DEVICE ( DE_VID , STB_PID ) } ,
{ USB_DEVICE ( DE_VID , WHT_PID ) } ,
2009-03-07 06:07:43 +08:00
{ USB_DEVICE ( ADI_VID , ADI_GNICE_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
2009-09-14 22:39:53 +08:00
{ USB_DEVICE ( ADI_VID , ADI_GNICEPLUS_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
2009-03-25 18:32:59 +08:00
{ USB_DEVICE ( JETI_VID , JETI_SPC1201_PID ) } ,
2009-04-24 10:38:12 +08:00
{ USB_DEVICE ( MARVELL_VID , MARVELL_SHEEVAPLUG_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
2009-05-13 16:05:48 +08:00
{ USB_DEVICE ( LARSENBRUSGAARD_VID , LB_ALTITRACK_PID ) } ,
2009-07-15 05:27:28 +08:00
{ USB_DEVICE ( GN_OTOMETRICS_VID , AURICAL_USB_PID ) } ,
2009-08-01 03:32:39 +08:00
{ USB_DEVICE ( BAYER_VID , BAYER_CONTOUR_CABLE_PID ) } ,
2009-08-07 19:56:49 +08:00
{ USB_DEVICE ( FTDI_VID , MARVELL_OPENRD_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
2009-08-27 20:15:50 +08:00
{ USB_DEVICE ( FTDI_VID , HAMEG_HO820_PID ) } ,
{ USB_DEVICE ( FTDI_VID , HAMEG_HO870_PID ) } ,
2010-02-13 02:23:18 +08:00
{ USB_DEVICE ( FTDI_VID , MJSG_GENERIC_PID ) } ,
{ USB_DEVICE ( FTDI_VID , MJSG_SR_RADIO_PID ) } ,
{ USB_DEVICE ( FTDI_VID , MJSG_HD_RADIO_PID ) } ,
{ USB_DEVICE ( FTDI_VID , MJSG_XM_RADIO_PID ) } ,
2010-07-01 16:49:55 +08:00
{ USB_DEVICE ( FTDI_VID , XVERVE_SIGNALYZER_ST_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
{ USB_DEVICE ( FTDI_VID , XVERVE_SIGNALYZER_SLITE_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
{ USB_DEVICE ( FTDI_VID , XVERVE_SIGNALYZER_SH2_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
{ USB_DEVICE ( FTDI_VID , XVERVE_SIGNALYZER_SH4_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
2010-07-24 21:50:52 +08:00
{ USB_DEVICE ( FTDI_VID , SEGWAY_RMP200_PID ) } ,
2010-09-14 12:35:40 +08:00
{ USB_DEVICE ( FTDI_VID , ACCESIO_COM4SM_PID ) } ,
2010-08-11 03:31:21 +08:00
{ USB_DEVICE ( IONICS_VID , IONICS_PLUGCOMPUTER_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
2010-09-02 18:39:49 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_CHAMSYS_24_MASTER_WING_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CHAMSYS_PC_WING_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CHAMSYS_USB_DMX_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CHAMSYS_MIDI_TIMECODE_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CHAMSYS_MINI_WING_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CHAMSYS_MAXI_WING_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CHAMSYS_MEDIA_WING_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_CHAMSYS_WING_PID ) } ,
2010-10-20 00:05:43 +08:00
{ USB_DEVICE ( FTDI_VID , FTDI_SCIENCESCOPE_LOGBOOKML_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_SCIENCESCOPE_LS_LOGBOOK_PID ) } ,
{ USB_DEVICE ( FTDI_VID , FTDI_SCIENCESCOPE_HS_LOGBOOK_PID ) } ,
2010-11-03 18:54:12 +08:00
{ USB_DEVICE ( QIHARDWARE_VID , MILKYMISTONE_JTAGSERIAL_PID ) ,
. driver_info = ( kernel_ulong_t ) & ftdi_jtag_quirk } ,
2005-07-29 01:40:32 +08:00
{ } , /* Optional parameter entry */
{ } /* Terminating entry */
2005-04-17 06:20:36 +08:00
} ;
2008-07-22 18:11:23 +08:00
MODULE_DEVICE_TABLE ( usb , id_table_combined ) ;
2005-04-17 06:20:36 +08:00
static struct usb_driver ftdi_driver = {
. name = " ftdi_sio " ,
. probe = usb_serial_probe ,
. disconnect = usb_serial_disconnect ,
. id_table = id_table_combined ,
2006-10-14 06:57:58 +08:00
. no_dynamic_id = 1 ,
2005-04-17 06:20:36 +08:00
} ;
2005-11-29 16:43:42 +08:00
static const char * ftdi_chip_name [ ] = {
2005-04-17 06:20:36 +08:00
[ SIO ] = " SIO " , /* the serial part of FT8U100AX */
[ FT8U232AM ] = " FT8U232AM " ,
[ FT232BM ] = " FT232BM " ,
[ FT2232C ] = " FT2232C " ,
2007-03-05 07:03:26 +08:00
[ FT232RL ] = " FT232RL " ,
2009-04-09 22:03:09 +08:00
[ FT2232H ] = " FT2232H " ,
[ FT4232H ] = " FT4232H "
2005-04-17 06:20:36 +08:00
} ;
/* Used for TIOCMIWAIT */
# define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
# define FTDI_STATUS_B1_MASK (FTDI_RS_BI)
/* End TIOCMIWAIT */
2008-02-07 08:06:07 +08:00
# define FTDI_IMPL_ASYNC_FLAGS = (ASYNC_SPD_HI | ASYNC_SPD_VHI \
| ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP )
2005-04-17 06:20:36 +08:00
/* function prototypes for a FTDI serial converter */
2008-07-22 18:11:23 +08:00
static int ftdi_sio_probe ( struct usb_serial * serial ,
const struct usb_device_id * id ) ;
static int ftdi_sio_port_probe ( struct usb_serial_port * port ) ;
static int ftdi_sio_port_remove ( struct usb_serial_port * port ) ;
2009-09-20 04:13:26 +08:00
static int ftdi_open ( struct tty_struct * tty , struct usb_serial_port * port ) ;
2009-06-11 19:26:29 +08:00
static void ftdi_close ( struct usb_serial_port * port ) ;
static void ftdi_dtr_rts ( struct usb_serial_port * port , int on ) ;
2010-03-18 06:06:00 +08:00
static void ftdi_process_read_urb ( struct urb * urb ) ;
2010-05-06 05:44:17 +08:00
static int ftdi_prepare_write_buffer ( struct usb_serial_port * port ,
2010-05-06 05:58:13 +08:00
void * dest , size_t size ) ;
2008-07-22 18:11:23 +08:00
static void ftdi_set_termios ( struct tty_struct * tty ,
struct usb_serial_port * port , struct ktermios * old ) ;
static int ftdi_tiocmget ( struct tty_struct * tty , struct file * file ) ;
static int ftdi_tiocmset ( struct tty_struct * tty , struct file * file ,
unsigned int set , unsigned int clear ) ;
static int ftdi_ioctl ( struct tty_struct * tty , struct file * file ,
unsigned int cmd , unsigned long arg ) ;
static void ftdi_break_ctl ( struct tty_struct * tty , int break_state ) ;
static unsigned short int ftdi_232am_baud_base_to_divisor ( int baud , int base ) ;
static unsigned short int ftdi_232am_baud_to_divisor ( int baud ) ;
static __u32 ftdi_232bm_baud_base_to_divisor ( int baud , int base ) ;
static __u32 ftdi_232bm_baud_to_divisor ( int baud ) ;
2009-04-09 22:03:09 +08:00
static __u32 ftdi_2232h_baud_base_to_divisor ( int baud , int base ) ;
static __u32 ftdi_2232h_baud_to_divisor ( int baud ) ;
2005-04-17 06:20:36 +08:00
2005-06-21 12:15:16 +08:00
static struct usb_serial_driver ftdi_sio_device = {
2005-06-21 12:15:16 +08:00
. driver = {
. owner = THIS_MODULE ,
2005-06-21 12:15:16 +08:00
. name = " ftdi_sio " ,
2005-06-21 12:15:16 +08:00
} ,
2005-06-21 12:15:16 +08:00
. description = " FTDI USB Serial Device " ,
2010-01-17 18:45:57 +08:00
. usb_driver = & ftdi_driver ,
2005-06-20 23:45:42 +08:00
. id_table = id_table_combined ,
2005-04-17 06:20:36 +08:00
. num_ports = 1 ,
2010-03-18 06:00:37 +08:00
. bulk_in_size = 512 ,
2010-05-06 05:58:13 +08:00
. bulk_out_size = 256 ,
2005-06-20 23:45:42 +08:00
. probe = ftdi_sio_probe ,
2007-03-01 02:10:50 +08:00
. port_probe = ftdi_sio_port_probe ,
. port_remove = ftdi_sio_port_remove ,
2005-04-17 06:20:36 +08:00
. open = ftdi_open ,
. close = ftdi_close ,
2009-06-11 19:26:29 +08:00
. dtr_rts = ftdi_dtr_rts ,
2010-03-18 06:06:00 +08:00
. throttle = usb_serial_generic_throttle ,
. unthrottle = usb_serial_generic_unthrottle ,
. process_read_urb = ftdi_process_read_urb ,
2010-05-06 05:44:17 +08:00
. prepare_write_buffer = ftdi_prepare_write_buffer ,
2010-01-17 18:45:57 +08:00
. tiocmget = ftdi_tiocmget ,
. tiocmset = ftdi_tiocmset ,
2005-04-17 06:20:36 +08:00
. ioctl = ftdi_ioctl ,
. set_termios = ftdi_set_termios ,
. break_ctl = ftdi_break_ctl ,
} ;
# define WDR_TIMEOUT 5000 /* default urb timeout */
2005-07-30 03:16:52 +08:00
# define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */
2005-04-17 06:20:36 +08:00
/* High and low are for DTR, RTS etc etc */
# define HIGH 1
# define LOW 0
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2007-05-05 09:23:24 +08:00
* Utility functions
2005-04-17 06:20:36 +08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
static unsigned short int ftdi_232am_baud_base_to_divisor ( int baud , int base )
{
unsigned short int divisor ;
2008-07-22 18:11:23 +08:00
/* divisor shifted 3 bits to the left */
int divisor3 = base / 2 / baud ;
if ( ( divisor3 & 0x7 ) = = 7 )
divisor3 + + ; /* round x.7/8 up to x+1 */
2005-04-17 06:20:36 +08:00
divisor = divisor3 > > 3 ;
divisor3 & = 0x7 ;
2008-07-22 18:11:23 +08:00
if ( divisor3 = = 1 )
divisor | = 0xc000 ;
else if ( divisor3 > = 4 )
divisor | = 0x4000 ;
else if ( divisor3 ! = 0 )
divisor | = 0x8000 ;
else if ( divisor = = 1 )
divisor = 0 ; /* special case for maximum baud rate */
2005-04-17 06:20:36 +08:00
return divisor ;
}
static unsigned short int ftdi_232am_baud_to_divisor ( int baud )
{
2008-07-22 18:11:23 +08:00
return ftdi_232am_baud_base_to_divisor ( baud , 48000000 ) ;
2005-04-17 06:20:36 +08:00
}
static __u32 ftdi_232bm_baud_base_to_divisor ( int baud , int base )
{
static const unsigned char divfrac [ 8 ] = { 0 , 3 , 2 , 4 , 1 , 5 , 6 , 7 } ;
__u32 divisor ;
2008-07-22 18:11:23 +08:00
/* divisor shifted 3 bits to the left */
int divisor3 = base / 2 / baud ;
2005-04-17 06:20:36 +08:00
divisor = divisor3 > > 3 ;
divisor | = ( __u32 ) divfrac [ divisor3 & 0x7 ] < < 14 ;
/* Deal with special cases for highest baud rates. */
2008-07-22 18:11:23 +08:00
if ( divisor = = 1 )
divisor = 0 ;
else if ( divisor = = 0x4001 )
divisor = 1 ;
2005-04-17 06:20:36 +08:00
return divisor ;
}
static __u32 ftdi_232bm_baud_to_divisor ( int baud )
{
2008-07-22 18:11:23 +08:00
return ftdi_232bm_baud_base_to_divisor ( baud , 48000000 ) ;
2005-04-17 06:20:36 +08:00
}
2009-04-09 22:03:09 +08:00
static __u32 ftdi_2232h_baud_base_to_divisor ( int baud , int base )
{
static const unsigned char divfrac [ 8 ] = { 0 , 3 , 2 , 4 , 1 , 5 , 6 , 7 } ;
__u32 divisor ;
int divisor3 ;
/* hi-speed baud rate is 10-bit sampling instead of 16-bit */
divisor3 = ( base / 10 / baud ) * 8 ;
divisor = divisor3 > > 3 ;
divisor | = ( __u32 ) divfrac [ divisor3 & 0x7 ] < < 14 ;
/* Deal with special cases for highest baud rates. */
if ( divisor = = 1 )
divisor = 0 ;
else if ( divisor = = 0x4001 )
divisor = 1 ;
/*
* Set this bit to turn off a divide by 2.5 on baud rate generator
* This enables baud rates up to 12 Mbaud but cannot reach below 1200
* baud with this bit set
*/
divisor | = 0x00020000 ;
return divisor ;
}
static __u32 ftdi_2232h_baud_to_divisor ( int baud )
{
return ftdi_2232h_baud_base_to_divisor ( baud , 120000000 ) ;
}
2005-07-30 03:16:41 +08:00
# define set_mctrl(port, set) update_mctrl((port), (set), 0)
# define clear_mctrl(port, clear) update_mctrl((port), 0, (clear))
2008-07-22 18:11:23 +08:00
static int update_mctrl ( struct usb_serial_port * port , unsigned int set ,
unsigned int clear )
2005-04-17 06:20:36 +08:00
{
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2005-07-30 03:16:41 +08:00
unsigned urb_value ;
2005-04-17 06:20:36 +08:00
int rv ;
2005-07-30 03:16:41 +08:00
if ( ( ( set | clear ) & ( TIOCM_DTR | TIOCM_RTS ) ) = = 0 ) {
2008-03-04 08:08:34 +08:00
dbg ( " %s - DTR|RTS not being set|cleared " , __func__ ) ;
2005-07-30 03:16:41 +08:00
return 0 ; /* no change */
}
2005-04-17 06:20:36 +08:00
2005-07-30 03:16:41 +08:00
clear & = ~ set ; /* 'set' takes precedence over 'clear' */
urb_value = 0 ;
if ( clear & TIOCM_DTR )
urb_value | = FTDI_SIO_SET_DTR_LOW ;
if ( clear & TIOCM_RTS )
urb_value | = FTDI_SIO_SET_RTS_LOW ;
if ( set & TIOCM_DTR )
urb_value | = FTDI_SIO_SET_DTR_HIGH ;
if ( set & TIOCM_RTS )
urb_value | = FTDI_SIO_SET_RTS_HIGH ;
2005-04-17 06:20:36 +08:00
rv = usb_control_msg ( port - > serial - > dev ,
usb_sndctrlpipe ( port - > serial - > dev , 0 ) ,
2006-10-14 06:57:58 +08:00
FTDI_SIO_SET_MODEM_CTRL_REQUEST ,
2005-04-17 06:20:36 +08:00
FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE ,
2005-07-30 03:16:41 +08:00
urb_value , priv - > interface ,
2009-12-24 19:42:09 +08:00
NULL , 0 , WDR_TIMEOUT ) ;
2005-07-30 03:16:41 +08:00
if ( rv < 0 ) {
2008-10-13 17:36:00 +08:00
dbg ( " %s Error from MODEM_CTRL urb: DTR %s, RTS %s " ,
2008-03-04 08:08:34 +08:00
__func__ ,
2005-07-30 03:16:41 +08:00
( set & TIOCM_DTR ) ? " HIGH " :
( clear & TIOCM_DTR ) ? " LOW " : " unchanged " ,
( set & TIOCM_RTS ) ? " HIGH " :
( clear & TIOCM_RTS ) ? " LOW " : " unchanged " ) ;
} else {
2008-03-04 08:08:34 +08:00
dbg ( " %s - DTR %s, RTS %s " , __func__ ,
2005-07-30 03:16:41 +08:00
( set & TIOCM_DTR ) ? " HIGH " :
( clear & TIOCM_DTR ) ? " LOW " : " unchanged " ,
( set & TIOCM_RTS ) ? " HIGH " :
( clear & TIOCM_RTS ) ? " LOW " : " unchanged " ) ;
2008-02-21 04:49:53 +08:00
/* FIXME: locking on last_dtr_rts */
2005-07-30 03:16:41 +08:00
priv - > last_dtr_rts = ( priv - > last_dtr_rts & ~ clear ) | set ;
}
2005-04-17 06:20:36 +08:00
return rv ;
}
2008-07-22 18:11:23 +08:00
static __u32 get_ftdi_divisor ( struct tty_struct * tty ,
struct usb_serial_port * port )
2010-03-18 06:06:09 +08:00
{
2005-04-17 06:20:36 +08:00
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
__u32 div_value = 0 ;
int div_okay = 1 ;
int baud ;
/*
2008-07-22 18:11:23 +08:00
* The logic involved in setting the baudrate can be cleanly split into
* 3 steps .
2005-04-17 06:20:36 +08:00
* 1. Standard baud rates are set in tty - > termios - > c_cflag
2008-07-22 18:11:23 +08:00
* 2. If these are not enough , you can set any speed using alt_speed as
* follows :
2005-04-17 06:20:36 +08:00
* - set tty - > termios - > c_cflag speed to B38400
* - set your real speed in tty - > alt_speed ; it gets ignored when
* alt_speed = = 0 , ( or )
2008-07-22 18:11:23 +08:00
* - call TIOCSSERIAL ioctl with ( struct serial_struct ) set as
* follows :
* flags & ASYNC_SPD_MASK = = ASYNC_SPD_ [ HI , VHI , SHI , WARP ] ,
* this just sets alt_speed to ( HI : 57600 , VHI : 115200 ,
* SHI : 230400 , WARP : 460800 )
2005-04-17 06:20:36 +08:00
* * * Steps 1 , 2 are done courtesy of tty_get_baud_rate
* 3. You can also set baud rate by setting custom divisor as follows
* - set tty - > termios - > c_cflag speed to B38400
2008-07-22 18:11:23 +08:00
* - call TIOCSSERIAL ioctl with ( struct serial_struct ) set as
* follows :
2005-04-17 06:20:36 +08:00
* o flags & ASYNC_SPD_MASK = = ASYNC_SPD_CUST
* o custom_divisor set to baud_base / your_new_baudrate
2008-07-22 18:11:23 +08:00
* * * Step 3 is done courtesy of code borrowed from serial . c
* I should really spend some time and separate + move this common
* code to serial . c , it is replicated in nearly every serial driver
* you see .
2005-04-17 06:20:36 +08:00
*/
2008-07-22 18:11:23 +08:00
/* 1. Get the baud rate from the tty settings, this observes
alt_speed hack */
2005-04-17 06:20:36 +08:00
2008-07-22 18:09:07 +08:00
baud = tty_get_baud_rate ( tty ) ;
2008-03-04 08:08:34 +08:00
dbg ( " %s - tty_get_baud_rate reports speed %d " , __func__ , baud ) ;
2005-04-17 06:20:36 +08:00
2008-07-22 18:11:23 +08:00
/* 2. Observe async-compatible custom_divisor hack, update baudrate
if needed */
2005-04-17 06:20:36 +08:00
if ( baud = = 38400 & &
( ( priv - > flags & ASYNC_SPD_MASK ) = = ASYNC_SPD_CUST ) & &
( priv - > custom_divisor ) ) {
baud = priv - > baud_base / priv - > custom_divisor ;
2008-07-22 18:11:23 +08:00
dbg ( " %s - custom divisor %d sets baud rate to %d " ,
__func__ , priv - > custom_divisor , baud ) ;
2005-04-17 06:20:36 +08:00
}
/* 3. Convert baudrate to device-specific divisor */
2008-07-22 18:11:23 +08:00
if ( ! baud )
baud = 9600 ;
switch ( priv - > chip_type ) {
2005-04-17 06:20:36 +08:00
case SIO : /* SIO chip */
2008-07-22 18:11:23 +08:00
switch ( baud ) {
2005-04-17 06:20:36 +08:00
case 300 : div_value = ftdi_sio_b300 ; break ;
case 600 : div_value = ftdi_sio_b600 ; break ;
case 1200 : div_value = ftdi_sio_b1200 ; break ;
case 2400 : div_value = ftdi_sio_b2400 ; break ;
case 4800 : div_value = ftdi_sio_b4800 ; break ;
case 9600 : div_value = ftdi_sio_b9600 ; break ;
case 19200 : div_value = ftdi_sio_b19200 ; break ;
case 38400 : div_value = ftdi_sio_b38400 ; break ;
case 57600 : div_value = ftdi_sio_b57600 ; break ;
case 115200 : div_value = ftdi_sio_b115200 ; break ;
} /* baud */
if ( div_value = = 0 ) {
2008-07-22 18:11:23 +08:00
dbg ( " %s - Baudrate (%d) requested is not supported " ,
__func__ , baud ) ;
2005-04-17 06:20:36 +08:00
div_value = ftdi_sio_b9600 ;
2007-10-18 16:24:25 +08:00
baud = 9600 ;
2005-04-17 06:20:36 +08:00
div_okay = 0 ;
}
break ;
case FT8U232AM : /* 8U232AM chip */
if ( baud < = 3000000 ) {
div_value = ftdi_232am_baud_to_divisor ( baud ) ;
} else {
2008-07-22 18:11:23 +08:00
dbg ( " %s - Baud rate too high! " , __func__ ) ;
2007-10-18 16:24:25 +08:00
baud = 9600 ;
2005-04-17 06:20:36 +08:00
div_value = ftdi_232am_baud_to_divisor ( 9600 ) ;
div_okay = 0 ;
}
break ;
case FT232BM : /* FT232BM chip */
case FT2232C : /* FT2232C chip */
2007-03-24 03:54:27 +08:00
case FT232RL :
2005-04-17 06:20:36 +08:00
if ( baud < = 3000000 ) {
2009-07-03 01:10:35 +08:00
__u16 product_id = le16_to_cpu (
port - > serial - > dev - > descriptor . idProduct ) ;
if ( ( ( FTDI_NDI_HUC_PID = = product_id ) | |
( FTDI_NDI_SPECTRA_SCU_PID = = product_id ) | |
( FTDI_NDI_FUTURE_2_PID = = product_id ) | |
( FTDI_NDI_FUTURE_3_PID = = product_id ) | |
( FTDI_NDI_AURORA_SCU_PID = = product_id ) ) & &
( baud = = 19200 ) ) {
baud = 1200000 ;
}
2005-04-17 06:20:36 +08:00
div_value = ftdi_232bm_baud_to_divisor ( baud ) ;
} else {
2008-07-22 18:11:23 +08:00
dbg ( " %s - Baud rate too high! " , __func__ ) ;
2005-04-17 06:20:36 +08:00
div_value = ftdi_232bm_baud_to_divisor ( 9600 ) ;
div_okay = 0 ;
2007-10-18 16:24:24 +08:00
baud = 9600 ;
2005-04-17 06:20:36 +08:00
}
break ;
2009-04-09 22:03:09 +08:00
case FT2232H : /* FT2232H chip */
case FT4232H : /* FT4232H chip */
if ( ( baud < = 12000000 ) & ( baud > = 1200 ) ) {
div_value = ftdi_2232h_baud_to_divisor ( baud ) ;
} else if ( baud < 1200 ) {
div_value = ftdi_232bm_baud_to_divisor ( baud ) ;
} else {
dbg ( " %s - Baud rate too high! " , __func__ ) ;
div_value = ftdi_232bm_baud_to_divisor ( 9600 ) ;
div_okay = 0 ;
baud = 9600 ;
}
break ;
2005-04-17 06:20:36 +08:00
} /* priv->chip_type */
if ( div_okay ) {
dbg ( " %s - Baud rate set to %d (divisor 0x%lX) on chip %s " ,
2008-03-04 08:08:34 +08:00
__func__ , baud , ( unsigned long ) div_value ,
2005-04-17 06:20:36 +08:00
ftdi_chip_name [ priv - > chip_type ] ) ;
}
2008-07-22 18:09:07 +08:00
tty_encode_baud_rate ( tty , baud , baud ) ;
2008-07-22 18:11:23 +08:00
return div_value ;
2005-04-17 06:20:36 +08:00
}
2008-07-22 18:09:07 +08:00
static int change_speed ( struct tty_struct * tty , struct usb_serial_port * port )
{
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2008-07-22 18:11:23 +08:00
__u16 urb_value ;
2008-07-22 18:09:07 +08:00
__u16 urb_index ;
__u32 urb_index_value ;
int rv ;
urb_index_value = get_ftdi_divisor ( tty , port ) ;
urb_value = ( __u16 ) urb_index_value ;
urb_index = ( __u16 ) ( urb_index_value > > 16 ) ;
if ( priv - > interface ) { /* FT2232C */
urb_index = ( __u16 ) ( ( urb_index < < 8 ) | priv - > interface ) ;
}
rv = usb_control_msg ( port - > serial - > dev ,
usb_sndctrlpipe ( port - > serial - > dev , 0 ) ,
FTDI_SIO_SET_BAUDRATE_REQUEST ,
FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE ,
urb_value , urb_index ,
2009-12-24 19:42:09 +08:00
NULL , 0 , WDR_SHORT_TIMEOUT ) ;
2008-07-22 18:09:07 +08:00
return rv ;
}
2009-06-11 20:55:34 +08:00
static int write_latency_timer ( struct usb_serial_port * port )
{
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
struct usb_device * udev = port - > serial - > dev ;
2009-12-24 19:42:11 +08:00
int rv ;
2009-06-11 20:55:34 +08:00
int l = priv - > latency ;
if ( priv - > flags & ASYNC_LOW_LATENCY )
l = 1 ;
dbg ( " %s: setting latency timer = %i " , __func__ , l ) ;
rv = usb_control_msg ( udev ,
usb_sndctrlpipe ( udev , 0 ) ,
FTDI_SIO_SET_LATENCY_TIMER_REQUEST ,
FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE ,
l , priv - > interface ,
2009-12-24 19:42:09 +08:00
NULL , 0 , WDR_TIMEOUT ) ;
2009-06-11 20:55:34 +08:00
if ( rv < 0 )
dev_err ( & port - > dev , " Unable to write latency timer: %i \n " , rv ) ;
return rv ;
}
static int read_latency_timer ( struct usb_serial_port * port )
{
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
struct usb_device * udev = port - > serial - > dev ;
2009-12-24 19:42:08 +08:00
unsigned char * buf ;
2009-12-24 19:42:11 +08:00
int rv ;
2009-06-11 20:55:34 +08:00
dbg ( " %s " , __func__ ) ;
2009-12-24 19:42:08 +08:00
buf = kmalloc ( 1 , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
2009-06-11 20:55:34 +08:00
rv = usb_control_msg ( udev ,
usb_rcvctrlpipe ( udev , 0 ) ,
FTDI_SIO_GET_LATENCY_TIMER_REQUEST ,
FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE ,
0 , priv - > interface ,
2009-12-24 19:42:08 +08:00
buf , 1 , WDR_TIMEOUT ) ;
2009-12-24 19:42:07 +08:00
if ( rv < 0 )
2009-06-11 20:55:34 +08:00
dev_err ( & port - > dev , " Unable to read latency timer: %i \n " , rv ) ;
2009-12-24 19:42:07 +08:00
else
2009-12-24 19:42:08 +08:00
priv - > latency = buf [ 0 ] ;
kfree ( buf ) ;
2009-11-23 04:25:20 +08:00
return rv ;
2009-06-11 20:55:34 +08:00
}
2005-04-17 06:20:36 +08:00
2008-07-22 18:11:23 +08:00
static int get_serial_info ( struct usb_serial_port * port ,
struct serial_struct __user * retinfo )
2005-04-17 06:20:36 +08:00
{
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
struct serial_struct tmp ;
if ( ! retinfo )
return - EFAULT ;
memset ( & tmp , 0 , sizeof ( tmp ) ) ;
tmp . flags = priv - > flags ;
tmp . baud_base = priv - > baud_base ;
tmp . custom_divisor = priv - > custom_divisor ;
if ( copy_to_user ( retinfo , & tmp , sizeof ( * retinfo ) ) )
return - EFAULT ;
return 0 ;
2010-03-18 06:06:09 +08:00
}
2005-04-17 06:20:36 +08:00
2008-07-22 18:09:07 +08:00
static int set_serial_info ( struct tty_struct * tty ,
2008-07-22 18:11:23 +08:00
struct usb_serial_port * port , struct serial_struct __user * newinfo )
2010-03-18 06:06:09 +08:00
{
2005-04-17 06:20:36 +08:00
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
struct serial_struct new_serial ;
struct ftdi_private old_priv ;
if ( copy_from_user ( & new_serial , newinfo , sizeof ( new_serial ) ) )
return - EFAULT ;
2009-01-02 21:48:56 +08:00
2010-02-02 23:18:28 +08:00
mutex_lock ( & priv - > cfg_lock ) ;
2008-07-22 18:11:23 +08:00
old_priv = * priv ;
2005-04-17 06:20:36 +08:00
/* Do error checking and permission checking */
if ( ! capable ( CAP_SYS_ADMIN ) ) {
if ( ( ( new_serial . flags & ~ ASYNC_USR_MASK ) ! =
2009-02-03 16:11:38 +08:00
( priv - > flags & ~ ASYNC_USR_MASK ) ) ) {
2010-02-02 23:18:28 +08:00
mutex_unlock ( & priv - > cfg_lock ) ;
2005-04-17 06:20:36 +08:00
return - EPERM ;
2009-02-03 16:11:38 +08:00
}
2005-04-17 06:20:36 +08:00
priv - > flags = ( ( priv - > flags & ~ ASYNC_USR_MASK ) |
( new_serial . flags & ASYNC_USR_MASK ) ) ;
priv - > custom_divisor = new_serial . custom_divisor ;
goto check_and_exit ;
}
if ( ( new_serial . baud_base ! = priv - > baud_base ) & &
2009-01-02 21:48:56 +08:00
( new_serial . baud_base < 9600 ) ) {
2010-02-02 23:18:28 +08:00
mutex_unlock ( & priv - > cfg_lock ) ;
2005-04-17 06:20:36 +08:00
return - EINVAL ;
2009-01-02 21:48:56 +08:00
}
2005-04-17 06:20:36 +08:00
/* Make the changes - these are privileged changes! */
priv - > flags = ( ( priv - > flags & ~ ASYNC_FLAGS ) |
2008-07-22 18:11:23 +08:00
( new_serial . flags & ASYNC_FLAGS ) ) ;
2005-04-17 06:20:36 +08:00
priv - > custom_divisor = new_serial . custom_divisor ;
2009-06-11 20:55:34 +08:00
write_latency_timer ( port ) ;
2005-04-17 06:20:36 +08:00
check_and_exit :
if ( ( old_priv . flags & ASYNC_SPD_MASK ) ! =
( priv - > flags & ASYNC_SPD_MASK ) ) {
if ( ( priv - > flags & ASYNC_SPD_MASK ) = = ASYNC_SPD_HI )
2008-07-22 18:09:07 +08:00
tty - > alt_speed = 57600 ;
2005-04-17 06:20:36 +08:00
else if ( ( priv - > flags & ASYNC_SPD_MASK ) = = ASYNC_SPD_VHI )
2008-07-22 18:09:07 +08:00
tty - > alt_speed = 115200 ;
2005-04-17 06:20:36 +08:00
else if ( ( priv - > flags & ASYNC_SPD_MASK ) = = ASYNC_SPD_SHI )
2008-07-22 18:09:07 +08:00
tty - > alt_speed = 230400 ;
2005-04-17 06:20:36 +08:00
else if ( ( priv - > flags & ASYNC_SPD_MASK ) = = ASYNC_SPD_WARP )
2008-07-22 18:09:07 +08:00
tty - > alt_speed = 460800 ;
2005-04-17 06:20:36 +08:00
else
2008-07-22 18:09:07 +08:00
tty - > alt_speed = 0 ;
2005-04-17 06:20:36 +08:00
}
if ( ( ( old_priv . flags & ASYNC_SPD_MASK ) ! =
( priv - > flags & ASYNC_SPD_MASK ) ) | |
( ( ( priv - > flags & ASYNC_SPD_MASK ) = = ASYNC_SPD_CUST ) & &
( old_priv . custom_divisor ! = priv - > custom_divisor ) ) ) {
2008-07-22 18:09:07 +08:00
change_speed ( tty , port ) ;
2010-03-14 01:35:14 +08:00
mutex_unlock ( & priv - > cfg_lock ) ;
2005-04-17 06:20:36 +08:00
}
2009-01-02 21:48:56 +08:00
else
2010-02-02 23:18:28 +08:00
mutex_unlock ( & priv - > cfg_lock ) ;
2008-07-22 18:09:07 +08:00
return 0 ;
2010-03-18 06:06:09 +08:00
}
2005-04-17 06:20:36 +08:00
2005-06-20 23:45:42 +08:00
/* Determine type of FTDI chip based on USB config and descriptor. */
static void ftdi_determine_type ( struct usb_serial_port * port )
{
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
struct usb_serial * serial = port - > serial ;
struct usb_device * udev = serial - > dev ;
unsigned version ;
unsigned interfaces ;
/* Assume it is not the original SIO device for now. */
2005-09-12 19:23:25 +08:00
priv - > baud_base = 48000000 / 2 ;
2005-06-20 23:45:42 +08:00
version = le16_to_cpu ( udev - > descriptor . bcdDevice ) ;
interfaces = udev - > actconfig - > desc . bNumInterfaces ;
2008-03-04 08:08:34 +08:00
dbg ( " %s: bcdDevice = 0x%x, bNumInterfaces = %u " , __func__ ,
2005-06-20 23:45:42 +08:00
version , interfaces ) ;
if ( interfaces > 1 ) {
int inter ;
2009-04-09 22:03:09 +08:00
/* Multiple interfaces.*/
if ( version = = 0x0800 ) {
priv - > chip_type = FT4232H ;
/* Hi-speed - baud clock runs at 120MHz */
priv - > baud_base = 120000000 / 2 ;
} else if ( version = = 0x0700 ) {
priv - > chip_type = FT2232H ;
/* Hi-speed - baud clock runs at 120MHz */
priv - > baud_base = 120000000 / 2 ;
} else
priv - > chip_type = FT2232C ;
2005-06-20 23:45:42 +08:00
/* Determine interface code. */
inter = serial - > interface - > altsetting - > desc . bInterfaceNumber ;
2009-04-09 22:03:09 +08:00
if ( inter = = 0 ) {
priv - > interface = INTERFACE_A ;
} else if ( inter = = 1 ) {
priv - > interface = INTERFACE_B ;
} else if ( inter = = 2 ) {
priv - > interface = INTERFACE_C ;
} else if ( inter = = 3 ) {
priv - > interface = INTERFACE_D ;
}
2005-06-20 23:45:42 +08:00
/* BM-type devices have a bug where bcdDevice gets set
* to 0x200 when iSerialNumber is 0. */
if ( version < 0x500 ) {
dbg ( " %s: something fishy - bcdDevice too low for multi-interface device " ,
2008-03-04 08:08:34 +08:00
__func__ ) ;
2005-06-20 23:45:42 +08:00
}
} else if ( version < 0x200 ) {
2010-01-17 18:45:57 +08:00
/* Old device. Assume it's the original SIO. */
2005-06-20 23:45:42 +08:00
priv - > chip_type = SIO ;
priv - > baud_base = 12000000 / 16 ;
} else if ( version < 0x400 ) {
2010-01-17 18:45:57 +08:00
/* Assume it's an FT8U232AM (or FT8U245AM) */
2005-06-20 23:45:42 +08:00
/* (It might be a BM because of the iSerialNumber bug,
* but it will still work as an AM device . ) */
priv - > chip_type = FT8U232AM ;
2007-03-24 03:54:27 +08:00
} else if ( version < 0x600 ) {
2010-01-17 18:45:57 +08:00
/* Assume it's an FT232BM (or FT245BM) */
2005-06-20 23:45:42 +08:00
priv - > chip_type = FT232BM ;
2007-03-24 03:54:27 +08:00
} else {
2010-01-17 18:45:57 +08:00
/* Assume it's an FT232R */
2007-03-24 03:54:27 +08:00
priv - > chip_type = FT232RL ;
2005-06-20 23:45:42 +08:00
}
2008-08-19 04:21:04 +08:00
dev_info ( & udev - > dev , " Detected %s \n " , ftdi_chip_name [ priv - > chip_type ] ) ;
2005-06-20 23:45:42 +08:00
}
2009-05-01 18:48:45 +08:00
/* Determine the maximum packet size for the device. This depends on the chip
* type and the USB host capabilities . The value should be obtained from the
* device descriptor as the chip will use the appropriate values for the host . */
static void ftdi_set_max_packet_size ( struct usb_serial_port * port )
{
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
struct usb_serial * serial = port - > serial ;
struct usb_device * udev = serial - > dev ;
struct usb_interface * interface = serial - > interface ;
struct usb_endpoint_descriptor * ep_desc = & interface - > cur_altsetting - > endpoint [ 1 ] . desc ;
unsigned num_endpoints ;
2009-12-24 19:42:11 +08:00
int i ;
2009-05-01 18:48:45 +08:00
num_endpoints = interface - > cur_altsetting - > desc . bNumEndpoints ;
dev_info ( & udev - > dev , " Number of endpoints %d \n " , num_endpoints ) ;
/* 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
* value of 64 for wMaxPacketSize */
for ( i = 0 ; i < num_endpoints ; i + + ) {
dev_info ( & udev - > dev , " Endpoint %d MaxPacketSize %d \n " , i + 1 ,
interface - > cur_altsetting - > endpoint [ i ] . desc . wMaxPacketSize ) ;
ep_desc = & interface - > cur_altsetting - > endpoint [ i ] . desc ;
if ( ep_desc - > wMaxPacketSize = = 0 ) {
ep_desc - > wMaxPacketSize = cpu_to_le16 ( 0x40 ) ;
dev_info ( & udev - > dev , " Overriding wMaxPacketSize on endpoint %d \n " , i ) ;
}
}
/* set max packet size based on descriptor */
2010-08-18 22:14:37 +08:00
priv - > max_packet_size = le16_to_cpu ( ep_desc - > wMaxPacketSize ) ;
2009-05-01 18:48:45 +08:00
dev_info ( & udev - > dev , " Setting MaxPacketSize %d \n " , priv - > max_packet_size ) ;
}
2005-04-17 06:20:36 +08:00
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Sysfs Attribute
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2008-07-22 18:11:23 +08:00
static ssize_t show_latency_timer ( struct device * dev ,
struct device_attribute * attr , char * buf )
2005-04-17 06:20:36 +08:00
{
struct usb_serial_port * port = to_usb_serial_port ( dev ) ;
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2009-06-11 20:55:34 +08:00
if ( priv - > flags & ASYNC_LOW_LATENCY )
return sprintf ( buf , " 1 \n " ) ;
else
return sprintf ( buf , " %i \n " , priv - > latency ) ;
2005-04-17 06:20:36 +08:00
}
2009-06-11 20:55:34 +08:00
2005-04-17 06:20:36 +08:00
/* Write a new value of the latency timer, in units of milliseconds. */
2008-07-22 18:11:23 +08:00
static ssize_t store_latency_timer ( struct device * dev ,
struct device_attribute * attr , const char * valbuf ,
size_t count )
2005-04-17 06:20:36 +08:00
{
struct usb_serial_port * port = to_usb_serial_port ( dev ) ;
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
int v = simple_strtoul ( valbuf , NULL , 10 ) ;
2009-12-24 19:42:11 +08:00
int rv ;
2006-10-14 06:57:58 +08:00
2009-06-11 20:55:34 +08:00
priv - > latency = v ;
rv = write_latency_timer ( port ) ;
if ( rv < 0 )
2005-04-17 06:20:36 +08:00
return - EIO ;
return count ;
}
/* Write an event character directly to the FTDI register. The ASCII
value is in the low 8 bits , with the enable bit in the 9 th bit . */
2008-07-22 18:11:23 +08:00
static ssize_t store_event_char ( struct device * dev ,
struct device_attribute * attr , const char * valbuf , size_t count )
2005-04-17 06:20:36 +08:00
{
struct usb_serial_port * port = to_usb_serial_port ( dev ) ;
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2007-03-01 02:10:50 +08:00
struct usb_device * udev = port - > serial - > dev ;
2005-04-17 06:20:36 +08:00
int v = simple_strtoul ( valbuf , NULL , 10 ) ;
2009-12-24 19:42:11 +08:00
int rv ;
2006-10-14 06:57:58 +08:00
2008-03-04 08:08:34 +08:00
dbg ( " %s: setting event char = %i " , __func__ , v ) ;
2006-10-14 06:57:58 +08:00
2005-04-17 06:20:36 +08:00
rv = usb_control_msg ( udev ,
usb_sndctrlpipe ( udev , 0 ) ,
FTDI_SIO_SET_EVENT_CHAR_REQUEST ,
FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE ,
2006-10-14 06:57:58 +08:00
v , priv - > interface ,
2009-12-24 19:42:09 +08:00
NULL , 0 , WDR_TIMEOUT ) ;
2005-04-17 06:20:36 +08:00
if ( rv < 0 ) {
dbg ( " Unable to write event character: %i " , rv ) ;
return - EIO ;
}
2006-10-14 06:57:58 +08:00
2005-04-17 06:20:36 +08:00
return count ;
}
2008-07-22 18:11:23 +08:00
static DEVICE_ATTR ( latency_timer , S_IWUSR | S_IRUGO , show_latency_timer ,
store_latency_timer ) ;
2005-04-17 06:20:36 +08:00
static DEVICE_ATTR ( event_char , S_IWUSR , NULL , store_event_char ) ;
2007-03-01 02:10:50 +08:00
static int create_sysfs_attrs ( struct usb_serial_port * port )
2006-08-29 02:43:25 +08:00
{
2007-03-01 02:10:50 +08:00
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2006-08-29 02:43:25 +08:00
int retval = 0 ;
2005-04-17 06:20:36 +08:00
2008-07-22 18:11:23 +08:00
dbg ( " %s " , __func__ ) ;
2006-08-29 02:43:25 +08:00
2005-04-17 06:20:36 +08:00
/* XXX I've no idea if the original SIO supports the event_char
* sysfs parameter , so I ' m playing it safe . */
if ( priv - > chip_type ! = SIO ) {
dbg ( " sysfs attributes for %s " , ftdi_chip_name [ priv - > chip_type ] ) ;
2007-03-01 02:10:50 +08:00
retval = device_create_file ( & port - > dev , & dev_attr_event_char ) ;
2006-08-29 02:43:25 +08:00
if ( ( ! retval ) & &
2007-05-10 02:53:04 +08:00
( priv - > chip_type = = FT232BM | |
priv - > chip_type = = FT2232C | |
2009-04-09 22:03:09 +08:00
priv - > chip_type = = FT232RL | |
priv - > chip_type = = FT2232H | |
priv - > chip_type = = FT4232H ) ) {
2007-03-01 02:10:50 +08:00
retval = device_create_file ( & port - > dev ,
2006-08-29 02:43:25 +08:00
& dev_attr_latency_timer ) ;
2005-04-17 06:20:36 +08:00
}
}
2006-08-29 02:43:25 +08:00
return retval ;
2005-04-17 06:20:36 +08:00
}
2007-03-01 02:10:50 +08:00
static void remove_sysfs_attrs ( struct usb_serial_port * port )
2005-04-17 06:20:36 +08:00
{
2007-03-01 02:10:50 +08:00
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2005-04-17 06:20:36 +08:00
2008-07-22 18:11:23 +08:00
dbg ( " %s " , __func__ ) ;
2005-04-17 06:20:36 +08:00
/* XXX see create_sysfs_attrs */
if ( priv - > chip_type ! = SIO ) {
2007-03-01 02:10:50 +08:00
device_remove_file ( & port - > dev , & dev_attr_event_char ) ;
2007-08-22 02:08:56 +08:00
if ( priv - > chip_type = = FT232BM | |
priv - > chip_type = = FT2232C | |
2009-04-09 22:03:09 +08:00
priv - > chip_type = = FT232RL | |
priv - > chip_type = = FT2232H | |
priv - > chip_type = = FT4232H ) {
2007-03-01 02:10:50 +08:00
device_remove_file ( & port - > dev , & dev_attr_latency_timer ) ;
2005-04-17 06:20:36 +08:00
}
}
2006-10-14 06:57:58 +08:00
2005-04-17 06:20:36 +08:00
}
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* FTDI driver specific functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2005-06-20 23:45:42 +08:00
/* Probe function to check for special devices */
2008-07-22 18:11:23 +08:00
static int ftdi_sio_probe ( struct usb_serial * serial ,
const struct usb_device_id * id )
2005-06-20 23:45:42 +08:00
{
2008-07-22 18:11:23 +08:00
struct ftdi_sio_quirk * quirk =
( struct ftdi_sio_quirk * ) id - > driver_info ;
2007-05-05 09:23:24 +08:00
if ( quirk & & quirk - > probe ) {
int ret = quirk - > probe ( serial ) ;
if ( ret ! = 0 )
return ret ;
}
2005-06-20 23:45:42 +08:00
usb_set_serial_data ( serial , ( void * ) id - > driver_info ) ;
2007-05-05 09:23:24 +08:00
return 0 ;
2005-06-20 23:45:42 +08:00
}
2007-03-01 02:10:50 +08:00
static int ftdi_sio_port_probe ( struct usb_serial_port * port )
2005-04-17 06:20:36 +08:00
{
struct ftdi_private * priv ;
2007-07-10 03:03:08 +08:00
struct ftdi_sio_quirk * quirk = usb_get_serial_data ( port - > serial ) ;
2006-08-29 02:43:25 +08:00
2008-07-22 18:11:23 +08:00
dbg ( " %s " , __func__ ) ;
2005-04-17 06:20:36 +08:00
2006-02-28 04:29:43 +08:00
priv = kzalloc ( sizeof ( struct ftdi_private ) , GFP_KERNEL ) ;
2008-07-22 18:11:23 +08:00
if ( ! priv ) {
2008-08-21 07:56:34 +08:00
dev_err ( & port - > dev , " %s- kmalloc(%Zd) failed. \n " , __func__ ,
2008-07-22 18:11:23 +08:00
sizeof ( struct ftdi_private ) ) ;
2005-04-17 06:20:36 +08:00
return - ENOMEM ;
}
2009-04-30 22:06:19 +08:00
kref_init ( & priv - > kref ) ;
2010-02-02 23:18:28 +08:00
mutex_init ( & priv - > cfg_lock ) ;
2008-07-22 18:11:23 +08:00
init_waitqueue_head ( & priv - > delta_msr_wait ) ;
2009-11-23 00:25:08 +08:00
2005-04-17 06:20:36 +08:00
priv - > flags = ASYNC_LOW_LATENCY ;
2007-07-10 03:03:08 +08:00
if ( quirk & & quirk - > port_probe )
quirk - > port_probe ( priv ) ;
2006-11-22 22:57:56 +08:00
priv - > port = port ;
2007-03-01 02:10:50 +08:00
usb_set_serial_port_data ( port , priv ) ;
2005-04-17 06:20:36 +08:00
2008-07-22 18:11:23 +08:00
ftdi_determine_type ( port ) ;
2009-05-01 18:48:45 +08:00
ftdi_set_max_packet_size ( port ) ;
2009-11-23 04:25:20 +08:00
if ( read_latency_timer ( port ) < 0 )
priv - > latency = 16 ;
2010-10-12 02:23:36 +08:00
write_latency_timer ( port ) ;
2007-03-01 02:10:50 +08:00
create_sysfs_attrs ( port ) ;
return 0 ;
}
2005-04-17 06:20:36 +08:00
2005-06-20 23:45:42 +08:00
/* Setup for the USB-UIRT device, which requires hardwired
* baudrate ( 38400 gets mapped to 312500 ) */
2005-04-17 06:20:36 +08:00
/* Called from usbserial:serial_probe */
2008-07-22 18:11:23 +08:00
static void ftdi_USB_UIRT_setup ( struct ftdi_private * priv )
2005-06-20 23:45:42 +08:00
{
2008-07-22 18:11:23 +08:00
dbg ( " %s " , __func__ ) ;
2005-04-17 06:20:36 +08:00
priv - > flags | = ASYNC_SPD_CUST ;
priv - > custom_divisor = 77 ;
2007-10-18 16:24:24 +08:00
priv - > force_baud = 38400 ;
2010-03-18 06:06:09 +08:00
}
2005-04-17 06:20:36 +08:00
2005-06-20 23:45:42 +08:00
/* Setup for the HE-TIRA1 device, which requires hardwired
* baudrate ( 38400 gets mapped to 100000 ) and RTS - CTS enabled . */
2008-07-22 18:11:23 +08:00
static void ftdi_HE_TIRA1_setup ( struct ftdi_private * priv )
2005-06-20 23:45:42 +08:00
{
2008-07-22 18:11:23 +08:00
dbg ( " %s " , __func__ ) ;
2005-04-17 06:20:36 +08:00
priv - > flags | = ASYNC_SPD_CUST ;
priv - > custom_divisor = 240 ;
2007-10-18 16:24:24 +08:00
priv - > force_baud = 38400 ;
2005-04-17 06:20:36 +08:00
priv - > force_rtscts = 1 ;
2010-03-18 06:06:09 +08:00
}
2005-04-17 06:20:36 +08:00
2009-07-03 01:10:35 +08:00
/*
* Module parameter to control latency timer for NDI FTDI - based USB devices .
* If this value is not set in modprobe . conf . local its value will be set to 1 ms .
*/
static int ndi_latency_timer = 1 ;
/* Setup for the NDI FTDI-based USB devices, which requires hardwired
* baudrate ( 19200 gets mapped to 1200000 ) .
*
* Called from usbserial : serial_probe .
*/
static int ftdi_NDI_device_setup ( struct usb_serial * serial )
{
struct usb_device * udev = serial - > dev ;
int latency = ndi_latency_timer ;
if ( latency = = 0 )
latency = 1 ;
if ( latency > 99 )
latency = 99 ;
dbg ( " %s setting NDI device latency to %d " , __func__ , latency ) ;
dev_info ( & udev - > dev , " NDI device with a latency value of %d " , latency ) ;
2009-12-24 19:42:11 +08:00
/* FIXME: errors are not returned */
usb_control_msg ( udev , usb_sndctrlpipe ( udev , 0 ) ,
2009-07-03 01:10:35 +08:00
FTDI_SIO_SET_LATENCY_TIMER_REQUEST ,
FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE ,
2009-12-24 19:42:09 +08:00
latency , 0 , NULL , 0 , WDR_TIMEOUT ) ;
2009-07-03 01:10:35 +08:00
return 0 ;
}
2007-05-05 09:23:24 +08:00
/*
2008-01-01 22:08:35 +08:00
* First port on JTAG adaptors such as Olimex arm - usb - ocd or the FIC / OpenMoko
* Neo1973 Debug Board is reserved for JTAG interface and can be accessed from
* userspace using openocd .
2007-05-05 09:23:24 +08:00
*/
2008-01-01 22:08:35 +08:00
static int ftdi_jtag_probe ( struct usb_serial * serial )
2007-05-05 09:23:24 +08:00
{
struct usb_device * udev = serial - > dev ;
struct usb_interface * interface = serial - > interface ;
2008-07-22 18:11:23 +08:00
dbg ( " %s " , __func__ ) ;
2007-05-05 09:23:24 +08:00
if ( interface = = udev - > actconfig - > interface [ 0 ] ) {
2008-08-19 04:21:04 +08:00
dev_info ( & udev - > dev ,
" Ignoring serial port reserved for JTAG \n " ) ;
2007-05-05 09:23:24 +08:00
return - ENODEV ;
}
return 0 ;
}
2005-04-17 06:20:36 +08:00
2008-03-02 02:49:59 +08:00
/*
* The Matrix Orbital VK204 - 25 - USB has an invalid IN endpoint .
* We have to correct it if we want to read from it .
*/
static int ftdi_mtxorb_hack_setup ( struct usb_serial * serial )
{
struct usb_host_endpoint * ep = serial - > dev - > ep_in [ 1 ] ;
struct usb_endpoint_descriptor * ep_desc = & ep - > desc ;
if ( ep - > enabled & & ep_desc - > wMaxPacketSize = = 0 ) {
2008-04-28 14:00:16 +08:00
ep_desc - > wMaxPacketSize = cpu_to_le16 ( 0x40 ) ;
2008-08-19 04:21:04 +08:00
dev_info ( & serial - > dev - > dev ,
" Fixing invalid wMaxPacketSize on read pipe \n " ) ;
2008-03-02 02:49:59 +08:00
}
return 0 ;
}
2009-04-30 22:06:19 +08:00
static void ftdi_sio_priv_release ( struct kref * k )
{
struct ftdi_private * priv = container_of ( k , struct ftdi_private , kref ) ;
kfree ( priv ) ;
}
2007-03-01 02:10:50 +08:00
static int ftdi_sio_port_remove ( struct usb_serial_port * port )
{
2005-04-17 06:20:36 +08:00
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2008-03-04 08:08:34 +08:00
dbg ( " %s " , __func__ ) ;
2005-04-17 06:20:36 +08:00
2007-03-01 02:10:50 +08:00
remove_sysfs_attrs ( port ) ;
2006-10-14 06:57:58 +08:00
2009-05-18 20:07:35 +08:00
kref_put ( & priv - > kref , ftdi_sio_priv_release ) ;
2005-04-17 06:20:36 +08:00
2007-03-01 02:10:50 +08:00
return 0 ;
}
2005-04-17 06:20:36 +08:00
2009-09-20 04:13:26 +08:00
static int ftdi_open ( struct tty_struct * tty , struct usb_serial_port * port )
2010-03-18 06:06:09 +08:00
{
2005-04-17 06:20:36 +08:00
struct usb_device * dev = port - > serial - > dev ;
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2009-12-24 19:42:11 +08:00
int result ;
2005-04-17 06:20:36 +08:00
2008-03-04 08:08:34 +08:00
dbg ( " %s " , __func__ ) ;
2005-04-17 06:20:36 +08:00
/* No error checking for this (will get errors later anyway) */
/* See ftdi_sio.h for description of what is reset */
usb_control_msg ( dev , usb_sndctrlpipe ( dev , 0 ) ,
2006-10-14 06:57:58 +08:00
FTDI_SIO_RESET_REQUEST , FTDI_SIO_RESET_REQUEST_TYPE ,
FTDI_SIO_RESET_SIO ,
2009-12-24 19:42:09 +08:00
priv - > interface , NULL , 0 , WDR_TIMEOUT ) ;
2005-04-17 06:20:36 +08:00
/* Termios defaults are set by usb_serial_init. We don't change
2008-12-06 00:34:46 +08:00
port - > tty - > termios - this would lose speed settings , etc .
2005-04-17 06:20:36 +08:00
This is same behaviour as serial . c / rs_open ( ) - Kuba */
/* ftdi_set_termios will send usb control messages */
2008-07-22 18:09:07 +08:00
if ( tty )
ftdi_set_termios ( tty , port , tty - > termios ) ;
2005-04-17 06:20:36 +08:00
/* Start reading from the device */
2010-03-18 06:06:00 +08:00
result = usb_serial_generic_open ( tty , port ) ;
2009-10-08 02:05:07 +08:00
if ( ! result )
2009-04-30 22:06:19 +08:00
kref_get ( & priv - > kref ) ;
2005-04-17 06:20:36 +08:00
return result ;
2010-03-18 06:06:09 +08:00
}
2005-04-17 06:20:36 +08:00
2009-06-11 19:26:29 +08:00
static void ftdi_dtr_rts ( struct usb_serial_port * port , int on )
{
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
mutex_lock ( & port - > serial - > disc_mutex ) ;
if ( ! port - > serial - > disconnected ) {
/* Disable flow control */
if ( ! on & & usb_control_msg ( port - > serial - > dev ,
usb_sndctrlpipe ( port - > serial - > dev , 0 ) ,
FTDI_SIO_SET_FLOW_CTRL_REQUEST ,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE ,
2009-12-24 19:42:09 +08:00
0 , priv - > interface , NULL , 0 ,
2009-06-11 19:26:29 +08:00
WDR_TIMEOUT ) < 0 ) {
dev_err ( & port - > dev , " error from flowcontrol urb \n " ) ;
}
/* drop RTS and DTR */
if ( on )
set_mctrl ( port , TIOCM_DTR | TIOCM_RTS ) ;
else
clear_mctrl ( port , TIOCM_DTR | TIOCM_RTS ) ;
}
mutex_unlock ( & port - > serial - > disc_mutex ) ;
}
2005-04-17 06:20:36 +08:00
2006-10-14 06:57:58 +08:00
/*
2005-04-17 06:20:36 +08:00
* usbserial : __serial_close only calls ftdi_close if the point is open
*
* This only gets called when it is the last close
*/
2009-06-11 19:26:29 +08:00
static void ftdi_close ( struct usb_serial_port * port )
2010-03-18 06:06:09 +08:00
{
2005-04-17 06:20:36 +08:00
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2008-03-04 08:08:34 +08:00
dbg ( " %s " , __func__ ) ;
2005-04-17 06:20:36 +08:00
2010-05-06 05:58:13 +08:00
usb_serial_generic_close ( port ) ;
2009-04-30 22:06:19 +08:00
kref_put ( & priv - > kref , ftdi_sio_priv_release ) ;
2010-03-18 06:06:09 +08:00
}
2006-10-14 06:57:58 +08:00
2005-04-17 06:20:36 +08:00
/* The SIO requires the first byte to have:
* B0 1
* B1 0
* B2 . .7 length of message excluding byte 0
*
* The new devices do not require this byte
*/
2010-05-06 05:44:17 +08:00
static int ftdi_prepare_write_buffer ( struct usb_serial_port * port ,
2010-05-06 05:58:13 +08:00
void * dest , size_t size )
2010-03-18 06:06:09 +08:00
{
2010-05-06 05:44:17 +08:00
struct ftdi_private * priv ;
2010-05-06 05:58:13 +08:00
int count ;
unsigned long flags ;
2005-04-17 06:20:36 +08:00
2010-05-06 05:44:17 +08:00
priv = usb_get_serial_port_data ( port ) ;
2006-10-14 06:57:58 +08:00
2010-05-06 05:45:01 +08:00
if ( priv - > chip_type = = SIO ) {
2010-05-06 05:58:13 +08:00
unsigned char * buffer = dest ;
int i , len , c ;
count = 0 ;
spin_lock_irqsave ( & port - > lock , flags ) ;
for ( i = 0 ; i < size - 1 ; i + = priv - > max_packet_size ) {
len = min_t ( int , size - i , priv - > max_packet_size ) - 1 ;
c = kfifo_out ( & port - > write_fifo , & buffer [ i + 1 ] , len ) ;
if ( ! c )
break ;
2010-05-19 06:01:41 +08:00
buffer [ i ] = ( c < < 2 ) + 1 ;
2010-05-06 05:58:13 +08:00
count + = c + 1 ;
2005-04-17 06:20:36 +08:00
}
2010-05-06 05:58:13 +08:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2005-04-17 06:20:36 +08:00
} else {
2010-05-06 05:58:13 +08:00
count = kfifo_out_locked ( & port - > write_fifo , dest , size ,
& port - > lock ) ;
2005-04-17 06:20:36 +08:00
}
2007-03-23 21:30:16 +08:00
return count ;
2010-03-18 06:06:09 +08:00
}
2005-04-17 06:20:36 +08:00
2010-05-08 21:19:24 +08:00
# define FTDI_RS_ERR_MASK (FTDI_RS_BI | FTDI_RS_PE | FTDI_RS_FE | FTDI_RS_OE)
2009-10-08 02:05:07 +08:00
static int ftdi_process_packet ( struct tty_struct * tty ,
struct usb_serial_port * port , struct ftdi_private * priv ,
char * packet , int len )
2008-07-22 18:09:07 +08:00
{
2005-04-17 06:20:36 +08:00
int i ;
2009-10-08 02:05:07 +08:00
char status ;
char flag ;
char * ch ;
2005-04-17 06:20:36 +08:00
2008-03-04 08:08:34 +08:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2005-04-17 06:20:36 +08:00
2009-10-08 02:05:07 +08:00
if ( len < 2 ) {
dbg ( " malformed packet " ) ;
return 0 ;
2005-04-17 06:20:36 +08:00
}
2009-10-08 02:05:07 +08:00
/* Compare new line status to the old one, signal if different/
N . B . packet may be processed more than once , but differences
are only processed once . */
status = packet [ 0 ] & FTDI_STATUS_B0_MASK ;
if ( status ! = priv - > prev_status ) {
priv - > diff_status | = status ^ priv - > prev_status ;
wake_up_interruptible ( & priv - > delta_msr_wait ) ;
priv - > prev_status = status ;
2005-04-17 06:20:36 +08:00
}
2009-10-08 02:05:07 +08:00
flag = TTY_NORMAL ;
2010-05-08 21:19:24 +08:00
if ( packet [ 1 ] & FTDI_RS_ERR_MASK ) {
/* Break takes precedence over parity, which takes precedence
* over framing errors */
if ( packet [ 1 ] & FTDI_RS_BI ) {
flag = TTY_BREAK ;
usb_serial_handle_break ( port ) ;
} else if ( packet [ 1 ] & FTDI_RS_PE ) {
flag = TTY_PARITY ;
} else if ( packet [ 1 ] & FTDI_RS_FE ) {
flag = TTY_FRAME ;
}
/* Overrun is special, not associated with a char */
if ( packet [ 1 ] & FTDI_RS_OE )
tty_insert_flip_char ( tty , 0 , TTY_OVERRUN ) ;
2005-06-02 17:34:11 +08:00
}
2005-04-17 06:20:36 +08:00
2009-10-08 02:05:07 +08:00
len - = 2 ;
if ( ! len )
return 0 ; /* status only */
ch = packet + 2 ;
2010-05-08 21:19:06 +08:00
if ( port - > port . console & & port - > sysrq ) {
2009-10-08 02:05:07 +08:00
for ( i = 0 ; i < len ; i + + , ch + + ) {
2010-08-18 12:15:47 +08:00
if ( ! usb_serial_handle_sysrq_char ( port , * ch ) )
2009-10-08 02:05:07 +08:00
tty_insert_flip_char ( tty , * ch , flag ) ;
2005-06-02 17:34:11 +08:00
}
2010-05-08 21:19:06 +08:00
} else {
tty_insert_flip_string_fixed_flag ( tty , ch , flag , len ) ;
2009-10-08 02:05:07 +08:00
}
2010-05-08 21:19:06 +08:00
2009-10-08 02:05:07 +08:00
return len ;
}
2005-06-02 17:34:11 +08:00
2010-03-18 06:06:00 +08:00
static void ftdi_process_read_urb ( struct urb * urb )
2009-10-08 02:05:07 +08:00
{
2010-03-18 06:06:00 +08:00
struct usb_serial_port * port = urb - > context ;
2009-10-08 02:05:07 +08:00
struct tty_struct * tty ;
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
char * data = ( char * ) urb - > transfer_buffer ;
int i ;
int len ;
int count = 0 ;
2005-04-17 06:20:36 +08:00
2009-10-08 02:05:07 +08:00
tty = tty_port_tty_get ( & port - > port ) ;
if ( ! tty )
return ;
2005-04-17 06:20:36 +08:00
2009-10-08 02:05:07 +08:00
for ( i = 0 ; i < urb - > actual_length ; i + = priv - > max_packet_size ) {
len = min_t ( int , urb - > actual_length - i , priv - > max_packet_size ) ;
count + = ftdi_process_packet ( tty , port , priv , & data [ i ] , len ) ;
}
2005-04-17 06:20:36 +08:00
2009-10-08 02:05:07 +08:00
if ( count )
2005-04-17 06:20:36 +08:00
tty_flip_buffer_push ( tty ) ;
2009-10-08 02:05:07 +08:00
tty_kref_put ( tty ) ;
}
2005-04-17 06:20:36 +08:00
2008-07-22 18:09:07 +08:00
static void ftdi_break_ctl ( struct tty_struct * tty , int break_state )
2005-04-17 06:20:36 +08:00
{
2008-07-22 18:09:07 +08:00
struct usb_serial_port * port = tty - > driver_data ;
2005-04-17 06:20:36 +08:00
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2009-12-24 19:42:11 +08:00
__u16 urb_value ;
2006-10-14 06:57:58 +08:00
2005-04-17 06:20:36 +08:00
/* break_state = -1 to turn on break, and 0 to turn off break */
/* see drivers/char/tty_io.c to see it used */
/* last_set_data_urb_value NEVER has the break bit set in it */
2008-07-22 18:11:23 +08:00
if ( break_state )
2005-04-17 06:20:36 +08:00
urb_value = priv - > last_set_data_urb_value | FTDI_SIO_SET_BREAK ;
2008-07-22 18:11:23 +08:00
else
2006-10-14 06:57:58 +08:00
urb_value = priv - > last_set_data_urb_value ;
2008-07-22 18:11:23 +08:00
if ( usb_control_msg ( port - > serial - > dev ,
usb_sndctrlpipe ( port - > serial - > dev , 0 ) ,
FTDI_SIO_SET_DATA_REQUEST ,
FTDI_SIO_SET_DATA_REQUEST_TYPE ,
urb_value , priv - > interface ,
2009-12-24 19:42:09 +08:00
NULL , 0 , WDR_TIMEOUT ) < 0 ) {
2008-08-21 07:56:34 +08:00
dev_err ( & port - > dev , " %s FAILED to enable/disable break state "
" (state was %d) \n " , __func__ , break_state ) ;
2006-10-14 06:57:58 +08:00
}
2005-04-17 06:20:36 +08:00
2008-07-22 18:11:23 +08:00
dbg ( " %s break state is %d - urb is %d " , __func__ ,
break_state , urb_value ) ;
2006-10-14 06:57:58 +08:00
2005-04-17 06:20:36 +08:00
}
/* old_termios contains the original termios settings and tty->termios contains
* the new setting to be used
* WARNING : set_termios calls this with old_termios in kernel space
*/
2008-07-22 18:09:07 +08:00
static void ftdi_set_termios ( struct tty_struct * tty ,
struct usb_serial_port * port , struct ktermios * old_termios )
2010-03-18 06:06:09 +08:00
{
2005-04-17 06:20:36 +08:00
struct usb_device * dev = port - > serial - > dev ;
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2008-07-22 18:09:07 +08:00
struct ktermios * termios = tty - > termios ;
2007-10-18 16:24:24 +08:00
unsigned int cflag = termios - > c_cflag ;
2005-04-17 06:20:36 +08:00
__u16 urb_value ; /* will hold the new flags */
2006-10-14 06:57:58 +08:00
2008-07-22 18:11:23 +08:00
/* Added for xon/xoff support */
2007-10-18 16:24:24 +08:00
unsigned int iflag = termios - > c_iflag ;
2005-04-17 06:20:36 +08:00
unsigned char vstop ;
unsigned char vstart ;
2006-10-14 06:57:58 +08:00
2008-03-04 08:08:34 +08:00
dbg ( " %s " , __func__ ) ;
2005-04-17 06:20:36 +08:00
2008-07-22 18:11:23 +08:00
/* Force baud rate if this device requires it, unless it is set to
B0 . */
2007-10-18 16:24:24 +08:00
if ( priv - > force_baud & & ( ( termios - > c_cflag & CBAUD ) ! = B0 ) ) {
2008-03-04 08:08:34 +08:00
dbg ( " %s: forcing baud rate for this device " , __func__ ) ;
2008-07-22 18:09:07 +08:00
tty_encode_baud_rate ( tty , priv - > force_baud ,
2007-10-18 16:24:25 +08:00
priv - > force_baud ) ;
2005-04-17 06:20:36 +08:00
}
/* Force RTS-CTS if this device requires it. */
if ( priv - > force_rtscts ) {
2008-03-04 08:08:34 +08:00
dbg ( " %s: forcing rtscts for this device " , __func__ ) ;
2007-10-18 16:24:24 +08:00
termios - > c_cflag | = CRTSCTS ;
2005-04-17 06:20:36 +08:00
}
2007-10-18 16:24:24 +08:00
cflag = termios - > c_cflag ;
2005-04-17 06:20:36 +08:00
2006-10-14 06:57:58 +08:00
/* FIXME -For this cut I don't care if the line is really changing or
not - so just do the change regardless - should be able to
2005-04-17 06:20:36 +08:00
compare old_termios and tty - > termios */
2006-10-14 06:57:58 +08:00
/* NOTE These routines can get interrupted by
2008-07-22 18:11:23 +08:00
ftdi_sio_read_bulk_callback - need to examine what this means -
don ' t see any problems yet */
2006-10-14 06:57:58 +08:00
2005-04-17 06:20:36 +08:00
/* Set number of data bits, parity, stop bits */
2006-10-14 06:57:58 +08:00
2005-04-17 06:20:36 +08:00
urb_value = 0 ;
urb_value | = ( cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 :
FTDI_SIO_SET_DATA_STOP_BITS_1 ) ;
2009-10-06 01:58:56 +08:00
if ( cflag & PARENB ) {
if ( cflag & CMSPAR )
urb_value | = cflag & PARODD ?
FTDI_SIO_SET_DATA_PARITY_MARK :
FTDI_SIO_SET_DATA_PARITY_SPACE ;
else
urb_value | = cflag & PARODD ?
FTDI_SIO_SET_DATA_PARITY_ODD :
FTDI_SIO_SET_DATA_PARITY_EVEN ;
} else {
urb_value | = FTDI_SIO_SET_DATA_PARITY_NONE ;
}
2005-04-17 06:20:36 +08:00
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 :
2009-11-24 17:39:10 +08:00
dev_err ( & port - > dev , " CSIZE was set but not CS7-CS8 \n " ) ;
2005-04-17 06:20:36 +08:00
}
}
2008-07-22 18:11:23 +08:00
/* This is needed by the break command since it uses the same command
- but is or ' ed with this value */
2005-04-17 06:20:36 +08:00
priv - > last_set_data_urb_value = urb_value ;
2006-10-14 06:57:58 +08:00
2005-04-17 06:20:36 +08:00
if ( usb_control_msg ( dev , usb_sndctrlpipe ( dev , 0 ) ,
2006-10-14 06:57:58 +08:00
FTDI_SIO_SET_DATA_REQUEST ,
2005-04-17 06:20:36 +08:00
FTDI_SIO_SET_DATA_REQUEST_TYPE ,
urb_value , priv - > interface ,
2009-12-24 19:42:09 +08:00
NULL , 0 , WDR_SHORT_TIMEOUT ) < 0 ) {
2008-08-21 07:56:34 +08:00
dev_err ( & port - > dev , " %s FAILED to set "
" databits/stopbits/parity \n " , __func__ ) ;
2006-10-14 06:57:58 +08:00
}
2005-04-17 06:20:36 +08:00
/* Now do the baudrate */
2008-07-22 18:11:23 +08:00
if ( ( cflag & CBAUD ) = = B0 ) {
2005-04-17 06:20:36 +08:00
/* Disable flow control */
if ( usb_control_msg ( dev , usb_sndctrlpipe ( dev , 0 ) ,
2006-10-14 06:57:58 +08:00
FTDI_SIO_SET_FLOW_CTRL_REQUEST ,
2005-04-17 06:20:36 +08:00
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE ,
2006-10-14 06:57:58 +08:00
0 , priv - > interface ,
2009-12-24 19:42:09 +08:00
NULL , 0 , WDR_TIMEOUT ) < 0 ) {
2008-08-21 07:56:34 +08:00
dev_err ( & port - > dev ,
" %s error from disable flowcontrol urb \n " ,
__func__ ) ;
2006-10-14 06:57:58 +08:00
}
2005-04-17 06:20:36 +08:00
/* Drop RTS and DTR */
2005-07-30 03:16:41 +08:00
clear_mctrl ( port , TIOCM_DTR | TIOCM_RTS ) ;
2005-04-17 06:20:36 +08:00
} else {
/* set the baudrate determined before */
2010-03-14 01:35:14 +08:00
mutex_lock ( & priv - > cfg_lock ) ;
2008-07-22 18:11:23 +08:00
if ( change_speed ( tty , port ) )
2008-08-21 07:56:34 +08:00
dev_err ( & port - > dev , " %s urb failed to set baudrate \n " ,
__func__ ) ;
2010-03-14 01:35:14 +08:00
mutex_unlock ( & priv - > cfg_lock ) ;
2005-09-22 15:48:49 +08:00
/* Ensure RTS and DTR are raised when baudrate changed from 0 */
2008-07-22 18:11:23 +08:00
if ( ! old_termios | | ( old_termios - > c_cflag & CBAUD ) = = B0 )
2005-09-22 15:48:49 +08:00
set_mctrl ( port , TIOCM_DTR | TIOCM_RTS ) ;
2005-04-17 06:20:36 +08:00
}
/* Set flow control */
/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
if ( cflag & CRTSCTS ) {
2008-03-04 08:08:34 +08:00
dbg ( " %s Setting to CRTSCTS flow control " , __func__ ) ;
2006-10-14 06:57:58 +08:00
if ( usb_control_msg ( dev ,
2005-04-17 06:20:36 +08:00
usb_sndctrlpipe ( dev , 0 ) ,
2006-10-14 06:57:58 +08:00
FTDI_SIO_SET_FLOW_CTRL_REQUEST ,
2005-04-17 06:20:36 +08:00
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE ,
0 , ( FTDI_SIO_RTS_CTS_HS | priv - > interface ) ,
2009-12-24 19:42:09 +08:00
NULL , 0 , WDR_TIMEOUT ) < 0 ) {
2008-08-21 07:56:34 +08:00
dev_err ( & port - > dev ,
" urb failed to set to rts/cts flow control \n " ) ;
2006-10-14 06:57:58 +08:00
}
} else {
2005-04-17 06:20:36 +08:00
/*
* Xon / Xoff code
*
2008-07-22 18:11:23 +08:00
* Check the IXOFF status in the iflag component of the
* termios structure . If IXOFF is not set , the pre - xon / xoff
* code is executed .
*/
2005-04-17 06:20:36 +08:00
if ( iflag & IXOFF ) {
2008-07-22 18:11:23 +08:00
dbg ( " %s request to enable xonxoff iflag=%04x " ,
__func__ , iflag ) ;
/* Try to enable the XON/XOFF on the ftdi_sio
* Set the vstart and vstop - - could have been done up
* above where a lot of other dereferencing is done but
* that would be very inefficient as vstart and vstop
* are not always needed .
*/
2007-10-18 16:24:24 +08:00
vstart = termios - > c_cc [ VSTART ] ;
vstop = termios - > c_cc [ VSTOP ] ;
2008-07-22 18:11:23 +08:00
urb_value = ( vstop < < 8 ) | ( vstart ) ;
2005-04-17 06:20:36 +08:00
if ( usb_control_msg ( dev ,
usb_sndctrlpipe ( dev , 0 ) ,
FTDI_SIO_SET_FLOW_CTRL_REQUEST ,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE ,
urb_value , ( FTDI_SIO_XON_XOFF_HS
| priv - > interface ) ,
2009-12-24 19:42:09 +08:00
NULL , 0 , WDR_TIMEOUT ) < 0 ) {
2008-08-21 07:56:34 +08:00
dev_err ( & port - > dev , " urb failed to set to "
" xon/xoff flow control \n " ) ;
2005-04-17 06:20:36 +08:00
}
} else {
2008-07-22 18:11:23 +08:00
/* else clause to only run if cflag ! CRTSCTS and iflag
* ! XOFF . CHECKME Assuming XON / XOFF handled by tty
* stack - not by device */
2008-03-04 08:08:34 +08:00
dbg ( " %s Turning off hardware flow control " , __func__ ) ;
2006-10-14 06:57:58 +08:00
if ( usb_control_msg ( dev ,
2005-04-17 06:20:36 +08:00
usb_sndctrlpipe ( dev , 0 ) ,
2006-10-14 06:57:58 +08:00
FTDI_SIO_SET_FLOW_CTRL_REQUEST ,
2005-04-17 06:20:36 +08:00
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE ,
2006-10-14 06:57:58 +08:00
0 , priv - > interface ,
2009-12-24 19:42:09 +08:00
NULL , 0 , WDR_TIMEOUT ) < 0 ) {
2008-08-21 07:56:34 +08:00
dev_err ( & port - > dev ,
" urb failed to clear flow control \n " ) ;
2006-10-14 06:57:58 +08:00
}
2005-04-17 06:20:36 +08:00
}
2006-10-14 06:57:58 +08:00
2005-04-17 06:20:36 +08:00
}
2008-07-22 18:09:07 +08:00
}
2005-04-17 06:20:36 +08:00
2008-07-22 18:09:07 +08:00
static int ftdi_tiocmget ( struct tty_struct * tty , struct file * file )
2005-04-17 06:20:36 +08:00
{
2008-07-22 18:09:07 +08:00
struct usb_serial_port * port = tty - > driver_data ;
2005-04-17 06:20:36 +08:00
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2009-12-24 19:42:09 +08:00
unsigned char * buf ;
2009-12-24 19:42:10 +08:00
int len ;
2005-04-17 06:20:36 +08:00
int ret ;
2008-03-04 08:08:34 +08:00
dbg ( " %s TIOCMGET " , __func__ ) ;
2009-12-24 19:42:09 +08:00
buf = kmalloc ( 2 , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
2009-12-24 19:42:10 +08:00
/*
* The 8U 232 AM returns a two byte value ( the SIO a 1 byte value ) in
* the same format as the data returned from the in point .
*/
2005-04-17 06:20:36 +08:00
switch ( priv - > chip_type ) {
case SIO :
2009-12-24 19:42:10 +08:00
len = 1 ;
2005-04-17 06:20:36 +08:00
break ;
case FT8U232AM :
case FT232BM :
case FT2232C :
2007-08-22 02:08:56 +08:00
case FT232RL :
2009-04-09 22:03:09 +08:00
case FT2232H :
case FT4232H :
2009-12-24 19:42:10 +08:00
len = 2 ;
2005-04-17 06:20:36 +08:00
break ;
default :
2009-12-24 19:42:09 +08:00
ret = - EFAULT ;
goto out ;
2005-04-17 06:20:36 +08:00
}
2006-10-14 06:57:58 +08:00
2009-12-24 19:42:10 +08:00
ret = usb_control_msg ( port - > serial - > dev ,
usb_rcvctrlpipe ( port - > serial - > dev , 0 ) ,
FTDI_SIO_GET_MODEM_STATUS_REQUEST ,
FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE ,
0 , priv - > interface ,
buf , len , WDR_TIMEOUT ) ;
if ( ret < 0 )
goto out ;
2009-12-24 19:42:09 +08:00
ret = ( buf [ 0 ] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0 ) |
2005-04-17 06:20:36 +08:00
( buf [ 0 ] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0 ) |
( buf [ 0 ] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0 ) |
( buf [ 0 ] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0 ) |
2006-10-14 06:57:58 +08:00
priv - > last_dtr_rts ;
2009-12-24 19:42:09 +08:00
out :
kfree ( buf ) ;
return ret ;
2005-04-17 06:20:36 +08:00
}
2008-07-22 18:11:23 +08:00
static int ftdi_tiocmset ( struct tty_struct * tty , struct file * file ,
2008-07-22 18:09:07 +08:00
unsigned int set , unsigned int clear )
2005-04-17 06:20:36 +08:00
{
2008-07-22 18:09:07 +08:00
struct usb_serial_port * port = tty - > driver_data ;
2008-03-04 08:08:34 +08:00
dbg ( " %s TIOCMSET " , __func__ ) ;
2005-07-30 03:16:41 +08:00
return update_mctrl ( port , set , clear ) ;
2005-04-17 06:20:36 +08:00
}
2008-07-22 18:11:23 +08:00
static int ftdi_ioctl ( struct tty_struct * tty , struct file * file ,
unsigned int cmd , unsigned long arg )
2005-04-17 06:20:36 +08:00
{
2008-07-22 18:09:07 +08:00
struct usb_serial_port * port = tty - > driver_data ;
2005-04-17 06:20:36 +08:00
struct ftdi_private * priv = usb_get_serial_port_data ( port ) ;
2008-03-04 08:08:34 +08:00
dbg ( " %s cmd 0x%04x " , __func__ , cmd ) ;
2005-04-17 06:20:36 +08:00
/* Based on code from acm.c and others */
switch ( cmd ) {
case TIOCGSERIAL : /* gets serial port data */
2008-07-22 18:11:23 +08:00
return get_serial_info ( port ,
( struct serial_struct __user * ) arg ) ;
2005-04-17 06:20:36 +08:00
case TIOCSSERIAL : /* sets serial port data */
2008-07-22 18:11:23 +08:00
return set_serial_info ( tty , port ,
( struct serial_struct __user * ) arg ) ;
2005-04-17 06:20:36 +08:00
/*
* Wait for any of the 4 modem inputs ( DCD , RI , DSR , CTS ) to change
* - mask passed in arg for lines of interest
* ( use | ' ed TIOCM_RNG / DSR / CD / CTS for masking )
* Caller should use TIOCGICOUNT to see which one it was .
2010-09-17 01:21:40 +08:00
* ( except that the driver doesn ' t support it ! )
2005-04-17 06:20:36 +08:00
*
* This code is borrowed from linux / drivers / char / serial . c
*/
case TIOCMIWAIT :
while ( priv ! = NULL ) {
interruptible_sleep_on ( & priv - > delta_msr_wait ) ;
/* see if a signal did it */
if ( signal_pending ( current ) )
return - ERESTARTSYS ;
else {
char diff = priv - > diff_status ;
2008-07-22 18:11:23 +08:00
if ( diff = = 0 )
2005-04-17 06:20:36 +08:00
return - EIO ; /* no change => error */
/* Consume all events */
priv - > diff_status = 0 ;
2008-07-22 18:11:23 +08:00
/* Return 0 if caller wanted to know about
these bits */
if ( ( ( arg & TIOCM_RNG ) & & ( diff & FTDI_RS0_RI ) ) | |
( ( arg & TIOCM_DSR ) & & ( diff & FTDI_RS0_DSR ) ) | |
( ( arg & TIOCM_CD ) & & ( diff & FTDI_RS0_RLSD ) ) | |
( ( arg & TIOCM_CTS ) & & ( diff & FTDI_RS0_CTS ) ) ) {
2005-04-17 06:20:36 +08:00
return 0 ;
}
/*
2008-07-22 18:11:23 +08:00
* Otherwise caller can ' t care less about what
* happened , and so we continue to wait for more
* events .
2005-04-17 06:20:36 +08:00
*/
}
}
2008-07-22 18:09:07 +08:00
return 0 ;
2005-04-17 06:20:36 +08:00
default :
break ;
}
2008-07-22 18:11:23 +08:00
/* This is not necessarily an error - turns out the higher layers
* will do some ioctls themselves ( see comment above )
2005-04-17 06:20:36 +08:00
*/
2008-03-04 08:08:34 +08:00
dbg ( " %s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h " , __func__ , cmd ) ;
2008-07-22 18:09:07 +08:00
return - ENOIOCTLCMD ;
}
2005-04-17 06:20:36 +08:00
2008-07-22 18:11:23 +08:00
static int __init ftdi_init ( void )
2005-04-17 06:20:36 +08:00
{
int retval ;
2008-03-04 08:08:34 +08:00
dbg ( " %s " , __func__ ) ;
2005-07-29 01:40:32 +08:00
if ( vendor > 0 & & product > 0 ) {
/* Add user specified VID/PID to reserved element of table. */
int i ;
for ( i = 0 ; id_table_combined [ i ] . idVendor ; i + + )
;
id_table_combined [ i ] . match_flags = USB_DEVICE_ID_MATCH_DEVICE ;
id_table_combined [ i ] . idVendor = vendor ;
id_table_combined [ i ] . idProduct = product ;
}
2005-06-20 23:45:42 +08:00
retval = usb_serial_register ( & ftdi_sio_device ) ;
2005-04-17 06:20:36 +08:00
if ( retval )
2005-06-20 23:45:42 +08:00
goto failed_sio_register ;
2005-04-17 06:20:36 +08:00
retval = usb_register ( & ftdi_driver ) ;
2006-10-14 06:57:58 +08:00
if ( retval )
2005-04-17 06:20:36 +08:00
goto failed_usb_register ;
2008-08-19 04:21:04 +08:00
printk ( KERN_INFO KBUILD_MODNAME " : " DRIVER_VERSION " : "
DRIVER_DESC " \n " ) ;
2005-04-17 06:20:36 +08:00
return 0 ;
failed_usb_register :
2005-06-20 23:45:42 +08:00
usb_serial_deregister ( & ftdi_sio_device ) ;
failed_sio_register :
2005-04-17 06:20:36 +08:00
return retval ;
}
2008-07-22 18:11:23 +08:00
static void __exit ftdi_exit ( void )
2005-04-17 06:20:36 +08:00
{
2008-03-04 08:08:34 +08:00
dbg ( " %s " , __func__ ) ;
2005-04-17 06:20:36 +08:00
2008-07-22 18:11:23 +08:00
usb_deregister ( & ftdi_driver ) ;
usb_serial_deregister ( & ftdi_sio_device ) ;
2005-04-17 06:20:36 +08:00
}
module_init ( ftdi_init ) ;
module_exit ( ftdi_exit ) ;
2008-07-22 18:11:23 +08:00
MODULE_AUTHOR ( DRIVER_AUTHOR ) ;
MODULE_DESCRIPTION ( DRIVER_DESC ) ;
2005-04-17 06:20:36 +08:00
MODULE_LICENSE ( " GPL " ) ;
module_param ( debug , bool , S_IRUGO | S_IWUSR ) ;
MODULE_PARM_DESC ( debug , " Debug enabled or not " ) ;
2005-07-29 01:40:32 +08:00
module_param ( vendor , ushort , 0 ) ;
MODULE_PARM_DESC ( vendor , " User specified vendor ID (default= "
__MODULE_STRING ( FTDI_VID ) " ) " ) ;
module_param ( product , ushort , 0 ) ;
2008-09-10 22:18:46 +08:00
MODULE_PARM_DESC ( product , " User specified product ID " ) ;
2005-04-17 06:20:36 +08:00
2009-07-03 01:10:35 +08:00
module_param ( ndi_latency_timer , int , S_IRUGO | S_IWUSR ) ;
MODULE_PARM_DESC ( ndi_latency_timer , " NDI device latency timer override " ) ;