162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * USB FTDI SIO driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2009 - 2013 662306a36Sopenharmony_ci * Johan Hovold (jhovold@gmail.com) 762306a36Sopenharmony_ci * Copyright (C) 1999 - 2001 862306a36Sopenharmony_ci * Greg Kroah-Hartman (greg@kroah.com) 962306a36Sopenharmony_ci * Bill Ryder (bryder@sgi.com) 1062306a36Sopenharmony_ci * Copyright (C) 2002 1162306a36Sopenharmony_ci * Kuba Ober (kuba@mareimbrium.org) 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * See Documentation/usb/usb-serial.rst for more information on using this 1462306a36Sopenharmony_ci * driver 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * See http://ftdi-usb-sio.sourceforge.net for up to date testing info 1762306a36Sopenharmony_ci * and extra documentation 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * Change entries from 2004 and earlier can be found in versions of this 2062306a36Sopenharmony_ci * file in kernel versions prior to the 2.6.24 release. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */ 2562306a36Sopenharmony_ci/* Thanx to FTDI for so kindly providing details of the protocol required */ 2662306a36Sopenharmony_ci/* to talk to the device */ 2762306a36Sopenharmony_ci/* Thanx to gkh and the rest of the usb dev group for all code I have 2862306a36Sopenharmony_ci assimilated :-) */ 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#include <linux/kernel.h> 3162306a36Sopenharmony_ci#include <linux/errno.h> 3262306a36Sopenharmony_ci#include <linux/slab.h> 3362306a36Sopenharmony_ci#include <linux/tty.h> 3462306a36Sopenharmony_ci#include <linux/tty_driver.h> 3562306a36Sopenharmony_ci#include <linux/tty_flip.h> 3662306a36Sopenharmony_ci#include <linux/module.h> 3762306a36Sopenharmony_ci#include <linux/spinlock.h> 3862306a36Sopenharmony_ci#include <linux/mutex.h> 3962306a36Sopenharmony_ci#include <linux/uaccess.h> 4062306a36Sopenharmony_ci#include <linux/usb.h> 4162306a36Sopenharmony_ci#include <linux/serial.h> 4262306a36Sopenharmony_ci#include <linux/gpio/driver.h> 4362306a36Sopenharmony_ci#include <linux/usb/serial.h> 4462306a36Sopenharmony_ci#include "ftdi_sio.h" 4562306a36Sopenharmony_ci#include "ftdi_sio_ids.h" 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#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>" 4862306a36Sopenharmony_ci#define DRIVER_DESC "USB FTDI Serial Converters Driver" 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cienum ftdi_chip_type { 5162306a36Sopenharmony_ci SIO, 5262306a36Sopenharmony_ci FT232A, 5362306a36Sopenharmony_ci FT232B, 5462306a36Sopenharmony_ci FT2232C, 5562306a36Sopenharmony_ci FT232R, 5662306a36Sopenharmony_ci FT232H, 5762306a36Sopenharmony_ci FT2232H, 5862306a36Sopenharmony_ci FT4232H, 5962306a36Sopenharmony_ci FT4232HA, 6062306a36Sopenharmony_ci FT232HP, 6162306a36Sopenharmony_ci FT233HP, 6262306a36Sopenharmony_ci FT2232HP, 6362306a36Sopenharmony_ci FT2233HP, 6462306a36Sopenharmony_ci FT4232HP, 6562306a36Sopenharmony_ci FT4233HP, 6662306a36Sopenharmony_ci FTX, 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistruct ftdi_private { 7062306a36Sopenharmony_ci enum ftdi_chip_type chip_type; 7162306a36Sopenharmony_ci int baud_base; /* baud base clock for divisor setting */ 7262306a36Sopenharmony_ci int custom_divisor; /* custom_divisor kludge, this is for 7362306a36Sopenharmony_ci baud_base (different from what goes to the 7462306a36Sopenharmony_ci chip!) */ 7562306a36Sopenharmony_ci u16 last_set_data_value; /* the last data state set - needed for doing 7662306a36Sopenharmony_ci * a break 7762306a36Sopenharmony_ci */ 7862306a36Sopenharmony_ci int flags; /* some ASYNC_xxxx flags are supported */ 7962306a36Sopenharmony_ci unsigned long last_dtr_rts; /* saved modem control outputs */ 8062306a36Sopenharmony_ci char prev_status; /* Used for TIOCMIWAIT */ 8162306a36Sopenharmony_ci char transmit_empty; /* If transmitter is empty or not */ 8262306a36Sopenharmony_ci u16 channel; /* channel index, or 0 for legacy types */ 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci speed_t force_baud; /* if non-zero, force the baud rate to 8562306a36Sopenharmony_ci this value */ 8662306a36Sopenharmony_ci int force_rtscts; /* if non-zero, force RTS-CTS to always 8762306a36Sopenharmony_ci be enabled */ 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci unsigned int latency; /* latency setting in use */ 9062306a36Sopenharmony_ci unsigned short max_packet_size; 9162306a36Sopenharmony_ci struct mutex cfg_lock; /* Avoid mess by parallel calls of config ioctl() and change_speed() */ 9262306a36Sopenharmony_ci#ifdef CONFIG_GPIOLIB 9362306a36Sopenharmony_ci struct gpio_chip gc; 9462306a36Sopenharmony_ci struct mutex gpio_lock; /* protects GPIO state */ 9562306a36Sopenharmony_ci bool gpio_registered; /* is the gpiochip in kernel registered */ 9662306a36Sopenharmony_ci bool gpio_used; /* true if the user requested a gpio */ 9762306a36Sopenharmony_ci u8 gpio_altfunc; /* which pins are in gpio mode */ 9862306a36Sopenharmony_ci u8 gpio_output; /* pin directions cache */ 9962306a36Sopenharmony_ci u8 gpio_value; /* pin value for outputs */ 10062306a36Sopenharmony_ci#endif 10162306a36Sopenharmony_ci}; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistruct ftdi_quirk { 10462306a36Sopenharmony_ci int (*probe)(struct usb_serial *); 10562306a36Sopenharmony_ci /* Special settings for probed ports. */ 10662306a36Sopenharmony_ci void (*port_probe)(struct ftdi_private *); 10762306a36Sopenharmony_ci}; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic int ftdi_jtag_probe(struct usb_serial *serial); 11062306a36Sopenharmony_cistatic int ftdi_NDI_device_setup(struct usb_serial *serial); 11162306a36Sopenharmony_cistatic int ftdi_stmclite_probe(struct usb_serial *serial); 11262306a36Sopenharmony_cistatic int ftdi_8u2232c_probe(struct usb_serial *serial); 11362306a36Sopenharmony_cistatic void ftdi_USB_UIRT_setup(struct ftdi_private *priv); 11462306a36Sopenharmony_cistatic void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic const struct ftdi_quirk ftdi_jtag_quirk = { 11762306a36Sopenharmony_ci .probe = ftdi_jtag_probe, 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic const struct ftdi_quirk ftdi_NDI_device_quirk = { 12162306a36Sopenharmony_ci .probe = ftdi_NDI_device_setup, 12262306a36Sopenharmony_ci}; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic const struct ftdi_quirk ftdi_USB_UIRT_quirk = { 12562306a36Sopenharmony_ci .port_probe = ftdi_USB_UIRT_setup, 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic const struct ftdi_quirk ftdi_HE_TIRA1_quirk = { 12962306a36Sopenharmony_ci .port_probe = ftdi_HE_TIRA1_setup, 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic const struct ftdi_quirk ftdi_stmclite_quirk = { 13362306a36Sopenharmony_ci .probe = ftdi_stmclite_probe, 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic const struct ftdi_quirk ftdi_8u2232c_quirk = { 13762306a36Sopenharmony_ci .probe = ftdi_8u2232c_probe, 13862306a36Sopenharmony_ci}; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci/* 14162306a36Sopenharmony_ci * The 8U232AM has the same API as the sio except for: 14262306a36Sopenharmony_ci * - it can support MUCH higher baudrates; up to: 14362306a36Sopenharmony_ci * o 921600 for RS232 and 2000000 for RS422/485 at 48MHz 14462306a36Sopenharmony_ci * o 230400 at 12MHz 14562306a36Sopenharmony_ci * so .. 8U232AM's baudrate setting codes are different 14662306a36Sopenharmony_ci * - it has a two byte status code. 14762306a36Sopenharmony_ci * - it returns characters every 16ms (the FTDI does it every 40ms) 14862306a36Sopenharmony_ci * 14962306a36Sopenharmony_ci * the bcdDevice value is used to differentiate FT232BM and FT245BM from 15062306a36Sopenharmony_ci * the earlier FT8U232AM and FT8U232BM. For now, include all known VID/PID 15162306a36Sopenharmony_ci * combinations in both tables. 15262306a36Sopenharmony_ci * FIXME: perhaps bcdDevice can also identify 12MHz FT8U232AM devices, 15362306a36Sopenharmony_ci * but I don't know if those ever went into mass production. [Ian Abbott] 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci/* 15962306a36Sopenharmony_ci * Device ID not listed? Test it using 16062306a36Sopenharmony_ci * /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report. 16162306a36Sopenharmony_ci */ 16262306a36Sopenharmony_cistatic const struct usb_device_id id_table_combined[] = { 16362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_BRICK_PID) }, 16462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) }, 16562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) }, 16662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) }, 16762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, 16862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, 16962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, 17062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_BM_ATOM_NANO_PID) }, 17162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) }, 17262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_EV3CON_PID) }, 17362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) }, 17462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) }, 17562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) }, 17662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_3_PID) }, 17762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_4_PID) }, 17862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) }, 17962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) }, 18062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) }, 18162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_USINT_CAT_PID) }, 18262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_USINT_WKEY_PID) }, 18362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_USINT_RS232_PID) }, 18462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, 18562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, 18662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, 18762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IPLUS2_PID) }, 18862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_DMX4ALL) }, 18962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, 19062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, 19162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, 19262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, 19362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) , 19462306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk }, 19562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) }, 19662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_232H_PID) }, 19762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_FTX_PID) }, 19862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_FT2233HP_PID) }, 19962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_FT4233HP_PID) }, 20062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_FT2232HP_PID) }, 20162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_FT4232HP_PID) }, 20262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_FT233HP_PID) }, 20362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_FT232HP_PID) }, 20462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_FT4232HA_PID) }, 20562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, 20662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, 20762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, 20862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_SNIFFER_PID) }, 20962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) }, 21062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) }, 21162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) }, 21262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_BOOST_PID) }, 21362306a36Sopenharmony_ci { USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) }, 21462306a36Sopenharmony_ci { USB_DEVICE(NEWPORT_VID, NEWPORT_CONEX_CC_PID) }, 21562306a36Sopenharmony_ci { USB_DEVICE(NEWPORT_VID, NEWPORT_CONEX_AGP_PID) }, 21662306a36Sopenharmony_ci { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, 21762306a36Sopenharmony_ci { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, 21862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, 21962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_LP101_PID) }, 22062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_P200X_PID) }, 22162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) }, 22262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, 22362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, 22462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) }, 22562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_XF_633_PID) }, 22662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_XF_631_PID) }, 22762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_XF_635_PID) }, 22862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_XF_640_PID) }, 22962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_XF_642_PID) }, 23062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) }, 23162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_URBAN_0_PID) }, 23262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_URBAN_1_PID) }, 23362306a36Sopenharmony_ci { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, 23462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) }, 23562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MTXORB_0_PID) }, 23662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MTXORB_1_PID) }, 23762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MTXORB_2_PID) }, 23862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MTXORB_3_PID) }, 23962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) }, 24062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, 24162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, 24262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) }, 24362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) }, 24462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_AUTO_M3_OP_COM_V2_PID) }, 24562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, 24662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, 24762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, 24862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0103_PID) }, 24962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0104_PID) }, 25062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0105_PID) }, 25162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0106_PID) }, 25262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0107_PID) }, 25362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0108_PID) }, 25462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0109_PID) }, 25562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010A_PID) }, 25662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010B_PID) }, 25762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010C_PID) }, 25862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010D_PID) }, 25962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010E_PID) }, 26062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010F_PID) }, 26162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0110_PID) }, 26262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0111_PID) }, 26362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0112_PID) }, 26462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0113_PID) }, 26562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0114_PID) }, 26662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0115_PID) }, 26762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0116_PID) }, 26862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0117_PID) }, 26962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0118_PID) }, 27062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0119_PID) }, 27162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011A_PID) }, 27262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011B_PID) }, 27362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011C_PID) }, 27462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011D_PID) }, 27562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011E_PID) }, 27662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011F_PID) }, 27762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0120_PID) }, 27862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0121_PID) }, 27962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0122_PID) }, 28062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0123_PID) }, 28162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0124_PID) }, 28262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0125_PID) }, 28362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0126_PID) }, 28462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0127_PID) }, 28562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0128_PID) }, 28662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0129_PID) }, 28762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012A_PID) }, 28862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012B_PID) }, 28962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012C_PID) }, 29062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012D_PID) }, 29162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012E_PID) }, 29262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012F_PID) }, 29362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0130_PID) }, 29462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0131_PID) }, 29562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0132_PID) }, 29662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0133_PID) }, 29762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0134_PID) }, 29862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0135_PID) }, 29962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0136_PID) }, 30062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0137_PID) }, 30162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0138_PID) }, 30262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0139_PID) }, 30362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013A_PID) }, 30462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013B_PID) }, 30562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013C_PID) }, 30662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013D_PID) }, 30762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013E_PID) }, 30862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013F_PID) }, 30962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0140_PID) }, 31062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0141_PID) }, 31162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0142_PID) }, 31262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0143_PID) }, 31362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0144_PID) }, 31462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0145_PID) }, 31562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0146_PID) }, 31662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0147_PID) }, 31762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0148_PID) }, 31862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0149_PID) }, 31962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014A_PID) }, 32062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014B_PID) }, 32162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014C_PID) }, 32262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014D_PID) }, 32362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014E_PID) }, 32462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014F_PID) }, 32562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0150_PID) }, 32662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0151_PID) }, 32762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0152_PID) }, 32862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0153_PID) }, 32962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0154_PID) }, 33062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0155_PID) }, 33162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0156_PID) }, 33262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0157_PID) }, 33362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0158_PID) }, 33462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0159_PID) }, 33562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015A_PID) }, 33662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015B_PID) }, 33762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015C_PID) }, 33862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015D_PID) }, 33962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015E_PID) }, 34062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015F_PID) }, 34162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0160_PID) }, 34262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0161_PID) }, 34362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0162_PID) }, 34462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0163_PID) }, 34562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0164_PID) }, 34662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0165_PID) }, 34762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0166_PID) }, 34862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0167_PID) }, 34962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0168_PID) }, 35062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0169_PID) }, 35162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016A_PID) }, 35262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016B_PID) }, 35362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016C_PID) }, 35462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016D_PID) }, 35562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016E_PID) }, 35662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016F_PID) }, 35762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0170_PID) }, 35862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0171_PID) }, 35962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0172_PID) }, 36062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0173_PID) }, 36162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0174_PID) }, 36262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0175_PID) }, 36362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0176_PID) }, 36462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0177_PID) }, 36562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0178_PID) }, 36662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0179_PID) }, 36762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017A_PID) }, 36862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017B_PID) }, 36962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017C_PID) }, 37062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017D_PID) }, 37162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017E_PID) }, 37262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017F_PID) }, 37362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0180_PID) }, 37462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0181_PID) }, 37562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0182_PID) }, 37662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0183_PID) }, 37762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0184_PID) }, 37862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0185_PID) }, 37962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0186_PID) }, 38062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0187_PID) }, 38162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0188_PID) }, 38262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0189_PID) }, 38362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018A_PID) }, 38462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018B_PID) }, 38562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018C_PID) }, 38662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018D_PID) }, 38762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018E_PID) }, 38862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018F_PID) }, 38962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0190_PID) }, 39062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0191_PID) }, 39162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0192_PID) }, 39262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0193_PID) }, 39362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0194_PID) }, 39462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0195_PID) }, 39562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0196_PID) }, 39662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0197_PID) }, 39762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0198_PID) }, 39862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0199_PID) }, 39962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019A_PID) }, 40062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019B_PID) }, 40162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019C_PID) }, 40262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019D_PID) }, 40362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019E_PID) }, 40462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019F_PID) }, 40562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A0_PID) }, 40662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A1_PID) }, 40762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A2_PID) }, 40862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A3_PID) }, 40962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A4_PID) }, 41062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A5_PID) }, 41162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A6_PID) }, 41262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A7_PID) }, 41362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A8_PID) }, 41462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A9_PID) }, 41562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AA_PID) }, 41662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AB_PID) }, 41762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AC_PID) }, 41862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AD_PID) }, 41962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AE_PID) }, 42062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AF_PID) }, 42162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B0_PID) }, 42262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B1_PID) }, 42362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B2_PID) }, 42462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B3_PID) }, 42562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B4_PID) }, 42662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B5_PID) }, 42762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B6_PID) }, 42862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B7_PID) }, 42962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B8_PID) }, 43062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B9_PID) }, 43162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BA_PID) }, 43262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BB_PID) }, 43362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BC_PID) }, 43462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BD_PID) }, 43562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BE_PID) }, 43662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BF_PID) }, 43762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C0_PID) }, 43862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C1_PID) }, 43962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C2_PID) }, 44062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C3_PID) }, 44162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C4_PID) }, 44262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C5_PID) }, 44362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C6_PID) }, 44462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C7_PID) }, 44562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C8_PID) }, 44662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C9_PID) }, 44762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CA_PID) }, 44862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CB_PID) }, 44962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CC_PID) }, 45062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CD_PID) }, 45162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CE_PID) }, 45262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CF_PID) }, 45362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D0_PID) }, 45462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D1_PID) }, 45562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D2_PID) }, 45662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D3_PID) }, 45762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D4_PID) }, 45862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D5_PID) }, 45962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D6_PID) }, 46062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D7_PID) }, 46162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D8_PID) }, 46262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D9_PID) }, 46362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DA_PID) }, 46462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DB_PID) }, 46562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DC_PID) }, 46662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DD_PID) }, 46762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DE_PID) }, 46862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DF_PID) }, 46962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E0_PID) }, 47062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E1_PID) }, 47162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E2_PID) }, 47262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E3_PID) }, 47362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E4_PID) }, 47462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E5_PID) }, 47562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E6_PID) }, 47662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E7_PID) }, 47762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E8_PID) }, 47862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E9_PID) }, 47962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EA_PID) }, 48062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EB_PID) }, 48162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EC_PID) }, 48262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01ED_PID) }, 48362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EE_PID) }, 48462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EF_PID) }, 48562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F0_PID) }, 48662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F1_PID) }, 48762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F2_PID) }, 48862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F3_PID) }, 48962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F4_PID) }, 49062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F5_PID) }, 49162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F6_PID) }, 49262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F7_PID) }, 49362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F8_PID) }, 49462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F9_PID) }, 49562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FA_PID) }, 49662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FB_PID) }, 49762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FC_PID) }, 49862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) }, 49962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) }, 50062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) }, 50162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_4701_PID) }, 50262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9300_PID) }, 50362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9301_PID) }, 50462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9302_PID) }, 50562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9303_PID) }, 50662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9304_PID) }, 50762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9305_PID) }, 50862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9306_PID) }, 50962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9307_PID) }, 51062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9308_PID) }, 51162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9309_PID) }, 51262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930A_PID) }, 51362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930B_PID) }, 51462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930C_PID) }, 51562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930D_PID) }, 51662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930E_PID) }, 51762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930F_PID) }, 51862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9310_PID) }, 51962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9311_PID) }, 52062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9312_PID) }, 52162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9313_PID) }, 52262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9314_PID) }, 52362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9315_PID) }, 52462306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9316_PID) }, 52562306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9317_PID) }, 52662306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9318_PID) }, 52762306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9319_PID) }, 52862306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931A_PID) }, 52962306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931B_PID) }, 53062306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931C_PID) }, 53162306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931D_PID) }, 53262306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931E_PID) }, 53362306a36Sopenharmony_ci { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931F_PID) }, 53462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, 53562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, 53662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, 53762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_USBX_707_PID) }, 53862306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, 53962306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, 54062306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, 54162306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) }, 54262306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2106_PID) }, 54362306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) }, 54462306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) }, 54562306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) }, 54662306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_2_PID) }, 54762306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_1_PID) }, 54862306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_2_PID) }, 54962306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_1_PID) }, 55062306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_2_PID) }, 55162306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_3_PID) }, 55262306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_4_PID) }, 55362306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_1_PID) }, 55462306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_2_PID) }, 55562306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_3_PID) }, 55662306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_4_PID) }, 55762306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_1_PID) }, 55862306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_2_PID) }, 55962306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_3_PID) }, 56062306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_4_PID) }, 56162306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_1_PID) }, 56262306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_2_PID) }, 56362306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_3_PID) }, 56462306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_4_PID) }, 56562306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_5_PID) }, 56662306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_6_PID) }, 56762306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_7_PID) }, 56862306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_8_PID) }, 56962306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_1_PID) }, 57062306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_2_PID) }, 57162306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_3_PID) }, 57262306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_4_PID) }, 57362306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_5_PID) }, 57462306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_6_PID) }, 57562306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_7_PID) }, 57662306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_8_PID) }, 57762306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_1_PID) }, 57862306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_2_PID) }, 57962306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_3_PID) }, 58062306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_4_PID) }, 58162306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_5_PID) }, 58262306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) }, 58362306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) }, 58462306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, 58562306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) }, 58662306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) }, 58762306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) }, 58862306a36Sopenharmony_ci { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) }, 58962306a36Sopenharmony_ci { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, 59062306a36Sopenharmony_ci { USB_DEVICE(OCT_VID, OCT_US101_PID) }, 59162306a36Sopenharmony_ci { USB_DEVICE(OCT_VID, OCT_DK201_PID) }, 59262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID), 59362306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_HE_TIRA1_quirk }, 59462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID), 59562306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_USB_UIRT_quirk }, 59662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_1) }, 59762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, PROTEGO_R2X0) }, 59862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) }, 59962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) }, 60062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E808_PID) }, 60162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E809_PID) }, 60262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80A_PID) }, 60362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80B_PID) }, 60462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80C_PID) }, 60562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80D_PID) }, 60662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80E_PID) }, 60762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80F_PID) }, 60862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E888_PID) }, 60962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E889_PID) }, 61062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88A_PID) }, 61162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88B_PID) }, 61262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88C_PID) }, 61362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88D_PID) }, 61462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88E_PID) }, 61562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88F_PID) }, 61662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) }, 61762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) }, 61862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_UR100_PID) }, 61962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) }, 62062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) }, 62162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, 62262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IBS_US485_PID) }, 62362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IBS_PICPRO_PID) }, 62462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IBS_PCMCIA_PID) }, 62562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IBS_PK1_PID) }, 62662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IBS_RS232MON_PID) }, 62762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) }, 62862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, 62962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, 63062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) }, 63162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID), 63262306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 63362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID), 63462306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 63562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLX_PLUS_PID) }, 63662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_NT_ORION_IO_PID) }, 63762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONMX_PID) }, 63862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) }, 63962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX_PID) }, 64062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2_PID) }, 64162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2WI_PID) }, 64262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX3_PID) }, 64362306a36Sopenharmony_ci /* 64462306a36Sopenharmony_ci * ELV devices: 64562306a36Sopenharmony_ci */ 64662306a36Sopenharmony_ci { USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) }, 64762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) }, 64862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) }, 64962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) }, 65062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_WS550_PID) }, 65162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_EC3000_PID) }, 65262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_WS888_PID) }, 65362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_TWS550_PID) }, 65462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_FEM_PID) }, 65562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) }, 65662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) }, 65762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) }, 65862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) }, 65962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) }, 66062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) }, 66162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) }, 66262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) }, 66362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, 66462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, 66562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, 66662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, 66762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, 66862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, 66962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) }, 67062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) }, 67162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_UTP8_PID) }, 67262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) }, 67362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_WS444PC_PID) }, 67462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) }, 67562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1010PC_PID) }, 67662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) }, 67762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_HS485_PID) }, 67862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_UMS100_PID) }, 67962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_TFD128_PID) }, 68062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_FM3RX_PID) }, 68162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELV_WS777_PID) }, 68262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_PALMSENS_PID) }, 68362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_IVIUM_XSTAT_PID) }, 68462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) }, 68562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) }, 68662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) }, 68762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, LINX_FUTURE_1_PID) }, 68862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) }, 68962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, 69062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, 69162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) }, 69262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CCSLOAD_N_GO_3_PID) }, 69362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CCSICDU64_4_PID) }, 69462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CCSPRIME8_5_PID) }, 69562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) }, 69662306a36Sopenharmony_ci { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) }, 69762306a36Sopenharmony_ci { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, 69862306a36Sopenharmony_ci { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, 69962306a36Sopenharmony_ci { USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) }, 70062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, 70162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) }, 70262306a36Sopenharmony_ci { USB_DEVICE(TTI_VID, TTI_QL355P_PID) }, 70362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, 70462306a36Sopenharmony_ci { USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) }, 70562306a36Sopenharmony_ci { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, 70662306a36Sopenharmony_ci { USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) }, 70762306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, 70862306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, 70962306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, 71062306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_USOPTL4_PID) }, 71162306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_USPTL4_PID) }, 71262306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_2_PID) }, 71362306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_PID) }, 71462306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR2_PID) }, 71562306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR_PID) }, 71662306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_485USB9F_2W_PID) }, 71762306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_485USB9F_4W_PID) }, 71862306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_232USB9M_PID) }, 71962306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_485USBTB_2W_PID) }, 72062306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_485USBTB_4W_PID) }, 72162306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_TTL5USB9M_PID) }, 72262306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_TTL3USB9M_PID) }, 72362306a36Sopenharmony_ci { USB_DEVICE(BANDB_VID, BANDB_ZZ_PROG1_USB_PID) }, 72462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, 72562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) }, 72662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, 72762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_3_PID) }, 72862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) }, 72962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) }, 73062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) }, 73162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_3_PID) }, 73262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_4_PID) }, 73362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, 73462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, 73562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, 73662306a36Sopenharmony_ci { USB_DEVICE(XSENS_VID, XSENS_AWINDA_DONGLE_PID) }, 73762306a36Sopenharmony_ci { USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) }, 73862306a36Sopenharmony_ci { USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) }, 73962306a36Sopenharmony_ci { USB_DEVICE(XSENS_VID, XSENS_MTDEVBOARD_PID) }, 74062306a36Sopenharmony_ci { USB_DEVICE(XSENS_VID, XSENS_MTIUSBCONVERTER_PID) }, 74162306a36Sopenharmony_ci { USB_DEVICE(XSENS_VID, XSENS_MTW_PID) }, 74262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) }, 74362306a36Sopenharmony_ci { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, 74462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, 74562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) }, 74662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MHAM_YS_PID) }, 74762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) }, 74862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) }, 74962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MHAM_IC_PID) }, 75062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MHAM_DB9_PID) }, 75162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MHAM_RS232_PID) }, 75262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y9_PID) }, 75362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) }, 75462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) }, 75562306a36Sopenharmony_ci { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, 75662306a36Sopenharmony_ci { USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) }, 75762306a36Sopenharmony_ci { USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) }, 75862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) }, 75962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, 76062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) }, 76162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) }, 76262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HRC_PID) }, 76362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16IC_PID) }, 76462306a36Sopenharmony_ci { USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) }, 76562306a36Sopenharmony_ci { USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) }, 76662306a36Sopenharmony_ci { USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) }, 76762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) }, 76862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ECLO_COM_1WIRE_PID) }, 76962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) }, 77062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) }, 77162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, 77262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, 77362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, 77462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) }, 77562306a36Sopenharmony_ci { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) }, 77662306a36Sopenharmony_ci { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) }, 77762306a36Sopenharmony_ci { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) }, 77862306a36Sopenharmony_ci { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C2_PID) }, 77962306a36Sopenharmony_ci { USB_DEVICE(ICOM_VID, ICOM_ID_RP2D_PID) }, 78062306a36Sopenharmony_ci { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VT_PID) }, 78162306a36Sopenharmony_ci { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VR_PID) }, 78262306a36Sopenharmony_ci { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVT_PID) }, 78362306a36Sopenharmony_ci { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVR_PID) }, 78462306a36Sopenharmony_ci { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVT_PID) }, 78562306a36Sopenharmony_ci { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVR_PID) }, 78662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, 78762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, 78862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, 78962306a36Sopenharmony_ci { USB_DEVICE(TESTO_VID, TESTO_1_PID) }, 79062306a36Sopenharmony_ci { USB_DEVICE(TESTO_VID, TESTO_3_PID) }, 79162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) }, 79262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) }, 79362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, 79462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, 79562306a36Sopenharmony_ci { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, 79662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID), 79762306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, 79862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_NDI_SPECTRA_SCU_PID), 79962306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, 80062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_2_PID), 80162306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, 80262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_3_PID), 80362306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, 80462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID), 80562306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, 80662306a36Sopenharmony_ci { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, 80762306a36Sopenharmony_ci { USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) }, 80862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, RTSYSTEMS_USB_VX8_PID) }, 80962306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) }, 81062306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) }, 81162306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) }, 81262306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57B_PID) }, 81362306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29A_PID) }, 81462306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29B_PID) }, 81562306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29F_PID) }, 81662306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_62B_PID) }, 81762306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S01_PID) }, 81862306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_63_PID) }, 81962306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29C_PID) }, 82062306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_81B_PID) }, 82162306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_82B_PID) }, 82262306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K5D_PID) }, 82362306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K4Y_PID) }, 82462306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K5G_PID) }, 82562306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S05_PID) }, 82662306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_60_PID) }, 82762306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_61_PID) }, 82862306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_62_PID) }, 82962306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_63B_PID) }, 83062306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_64_PID) }, 83162306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_65_PID) }, 83262306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_92_PID) }, 83362306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_92D_PID) }, 83462306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_W5R_PID) }, 83562306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_A5R_PID) }, 83662306a36Sopenharmony_ci { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_PW1_PID) }, 83762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, 83862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, 83962306a36Sopenharmony_ci { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, 84062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, 84162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, 84262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, 84362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID), 84462306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 84562306a36Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID, 1) }, 84662306a36Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID, 1) }, 84762306a36Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_PID, 1) }, 84862306a36Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_H_PID, 1) }, 84962306a36Sopenharmony_ci { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID), 85062306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 85162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID), 85262306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 85362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, LMI_LM3S_DEVEL_BOARD_PID), 85462306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 85562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID), 85662306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 85762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, LMI_LM3S_ICDI_BOARD_PID), 85862306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 85962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID), 86062306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 86162306a36Sopenharmony_ci { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, 86262306a36Sopenharmony_ci { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) }, 86362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci /* Papouch devices based on FTDI chip */ 86662306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_PID) }, 86762306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_PID) }, 86862306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_PID) }, 86962306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_2_PID) }, 87062306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_2_PID) }, 87162306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_2_PID) }, 87262306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485S_PID) }, 87362306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485C_PID) }, 87462306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_LEC_PID) }, 87562306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB232_PID) }, 87662306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, 87762306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_IRAMP_PID) }, 87862306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK5_PID) }, 87962306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO8x8_PID) }, 88062306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, 88162306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x2_PID) }, 88262306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO10x1_PID) }, 88362306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO30x3_PID) }, 88462306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO60x3_PID) }, 88562306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x16_PID) }, 88662306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO3x32_PID) }, 88762306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK6_PID) }, 88862306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_UPSUSB_PID) }, 88962306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_MU_PID) }, 89062306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SIMUKEY_PID) }, 89162306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AD4USB_PID) }, 89262306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMUX_PID) }, 89362306a36Sopenharmony_ci { USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMSR_PID) }, 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) }, 89662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, 89762306a36Sopenharmony_ci { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, 89862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, 89962306a36Sopenharmony_ci { USB_DEVICE(ATMEL_VID, STK541_PID) }, 90062306a36Sopenharmony_ci { USB_DEVICE(DE_VID, STB_PID) }, 90162306a36Sopenharmony_ci { USB_DEVICE(DE_VID, WHT_PID) }, 90262306a36Sopenharmony_ci { USB_DEVICE(ADI_VID, ADI_GNICE_PID), 90362306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 90462306a36Sopenharmony_ci { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), 90562306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 90662306a36Sopenharmony_ci { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID, 90762306a36Sopenharmony_ci USB_CLASS_VENDOR_SPEC, 90862306a36Sopenharmony_ci USB_SUBCLASS_VENDOR_SPEC, 0x00) }, 90962306a36Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(ACTEL_VID, MICROSEMI_ARROW_SF2PLUS_BOARD_PID, 2) }, 91062306a36Sopenharmony_ci { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, 91162306a36Sopenharmony_ci { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), 91262306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 91362306a36Sopenharmony_ci { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, 91462306a36Sopenharmony_ci { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, 91562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, PI_C865_PID) }, 91662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, PI_C857_PID) }, 91762306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_C866_PID) }, 91862306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_C663_PID) }, 91962306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_C725_PID) }, 92062306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_E517_PID) }, 92162306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_C863_PID) }, 92262306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_E861_PID) }, 92362306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_C867_PID) }, 92462306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_E609_PID) }, 92562306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_E709_PID) }, 92662306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_100F_PID) }, 92762306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_1011_PID) }, 92862306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_1012_PID) }, 92962306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_1013_PID) }, 93062306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_1014_PID) }, 93162306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_1015_PID) }, 93262306a36Sopenharmony_ci { USB_DEVICE(PI_VID, PI_1016_PID) }, 93362306a36Sopenharmony_ci { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, 93462306a36Sopenharmony_ci { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, 93562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), 93662306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 93762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID), 93862306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 93962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) }, 94062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) }, 94162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) }, 94262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) }, 94362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, MJSG_GENERIC_PID) }, 94462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) }, 94562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, MJSG_HD_RADIO_PID) }, 94662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, MJSG_XM_RADIO_PID) }, 94762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_ST_PID), 94862306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 94962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SLITE_PID), 95062306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 95162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH2_PID), 95262306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 95362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID), 95462306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 95562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) }, 95662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, ACCESIO_COM4SM_PID) }, 95762306a36Sopenharmony_ci { USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID), 95862306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 95962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) }, 96062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_PC_WING_PID) }, 96162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_USB_DMX_PID) }, 96262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MIDI_TIMECODE_PID) }, 96362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MINI_WING_PID) }, 96462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) }, 96562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) }, 96662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) }, 96762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) }, 96862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) }, 96962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, 97062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) }, 97162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_FHE_PID) }, 97262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) }, 97362306a36Sopenharmony_ci { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID), 97462306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 97562306a36Sopenharmony_ci { USB_DEVICE(ST_VID, ST_STMCLT_2232_PID), 97662306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 97762306a36Sopenharmony_ci { USB_DEVICE(ST_VID, ST_STMCLT_4232_PID), 97862306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk }, 97962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_RF_R106) }, 98062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), 98162306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 98262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, 98362306a36Sopenharmony_ci /* Crucible Devices */ 98462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, 98562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) }, 98662306a36Sopenharmony_ci /* Cressi Devices */ 98762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) }, 98862306a36Sopenharmony_ci /* Brainboxes Devices */ 98962306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_001_PID) }, 99062306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_012_PID) }, 99162306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_023_PID) }, 99262306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_034_PID) }, 99362306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_101_PID) }, 99462306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_159_PID) }, 99562306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_1_PID) }, 99662306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_2_PID) }, 99762306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_3_PID) }, 99862306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_4_PID) }, 99962306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_5_PID) }, 100062306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_6_PID) }, 100162306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_7_PID) }, 100262306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_8_PID) }, 100362306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_235_PID) }, 100462306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_257_PID) }, 100562306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_1_PID) }, 100662306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_2_PID) }, 100762306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_3_PID) }, 100862306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_4_PID) }, 100962306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_313_PID) }, 101062306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_320_PID) }, 101162306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_324_PID) }, 101262306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_1_PID) }, 101362306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_2_PID) }, 101462306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_357_PID) }, 101562306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_1_PID) }, 101662306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_2_PID) }, 101762306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_3_PID) }, 101862306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_1_PID) }, 101962306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_2_PID) }, 102062306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_1_PID) }, 102162306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) }, 102262306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) }, 102362306a36Sopenharmony_ci { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) }, 102462306a36Sopenharmony_ci /* ekey Devices */ 102562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) }, 102662306a36Sopenharmony_ci /* Infineon Devices */ 102762306a36Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_TC1798_PID, 1) }, 102862306a36Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_TC2X7_PID, 1) }, 102962306a36Sopenharmony_ci /* GE Healthcare devices */ 103062306a36Sopenharmony_ci { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) }, 103162306a36Sopenharmony_ci /* Active Research (Actisense) devices */ 103262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, ACTISENSE_NDC_PID) }, 103362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, ACTISENSE_USG_PID) }, 103462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, ACTISENSE_NGT_PID) }, 103562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, ACTISENSE_NGW_PID) }, 103662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, ACTISENSE_UID_PID) }, 103762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, ACTISENSE_USA_PID) }, 103862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, ACTISENSE_NGX_PID) }, 103962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, ACTISENSE_D9AF_PID) }, 104062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, CHETCO_SEAGAUGE_PID) }, 104162306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, CHETCO_SEASWITCH_PID) }, 104262306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_NMEA2000_PID) }, 104362306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ETHERNET_PID) }, 104462306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_WIFI_PID) }, 104562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) }, 104662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) }, 104762306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) }, 104862306a36Sopenharmony_ci /* Belimo Automation devices */ 104962306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, BELIMO_ZTH_PID) }, 105062306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, BELIMO_ZIP_PID) }, 105162306a36Sopenharmony_ci /* ICP DAS I-756xU devices */ 105262306a36Sopenharmony_ci { USB_DEVICE(ICPDAS_VID, ICPDAS_I7560U_PID) }, 105362306a36Sopenharmony_ci { USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) }, 105462306a36Sopenharmony_ci { USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) }, 105562306a36Sopenharmony_ci { USB_DEVICE(WICED_VID, WICED_USB20706V2_PID) }, 105662306a36Sopenharmony_ci { USB_DEVICE(TI_VID, TI_CC3200_LAUNCHPAD_PID), 105762306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 105862306a36Sopenharmony_ci { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_BT_USB_PID) }, 105962306a36Sopenharmony_ci { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_WL_USB_PID) }, 106062306a36Sopenharmony_ci { USB_DEVICE(AIRBUS_DS_VID, AIRBUS_DS_P8GR) }, 106162306a36Sopenharmony_ci /* EZPrototypes devices */ 106262306a36Sopenharmony_ci { USB_DEVICE(EZPROTOTYPES_VID, HJELMSLUND_USB485_ISO_PID) }, 106362306a36Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(UNJO_VID, UNJO_ISODEBUG_V1_PID, 1) }, 106462306a36Sopenharmony_ci /* Sienna devices */ 106562306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_SIENNA_PID) }, 106662306a36Sopenharmony_ci { USB_DEVICE(ECHELON_VID, ECHELON_U20_PID) }, 106762306a36Sopenharmony_ci /* IDS GmbH devices */ 106862306a36Sopenharmony_ci { USB_DEVICE(IDS_VID, IDS_SI31A_PID) }, 106962306a36Sopenharmony_ci { USB_DEVICE(IDS_VID, IDS_CM31A_PID) }, 107062306a36Sopenharmony_ci /* Omron devices */ 107162306a36Sopenharmony_ci { USB_DEVICE(OMRON_VID, OMRON_CS1W_CIF31_PID) }, 107262306a36Sopenharmony_ci /* U-Blox devices */ 107362306a36Sopenharmony_ci { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ZED_PID) }, 107462306a36Sopenharmony_ci { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) }, 107562306a36Sopenharmony_ci /* FreeCalypso USB adapters */ 107662306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_BUF_PID), 107762306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 107862306a36Sopenharmony_ci { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_UNBUF_PID), 107962306a36Sopenharmony_ci .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 108062306a36Sopenharmony_ci /* GMC devices */ 108162306a36Sopenharmony_ci { USB_DEVICE(GMC_VID, GMC_Z216C_PID) }, 108262306a36Sopenharmony_ci { } /* Terminating entry */ 108362306a36Sopenharmony_ci}; 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, id_table_combined); 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_cistatic const char *ftdi_chip_name[] = { 108862306a36Sopenharmony_ci [SIO] = "SIO", /* the serial part of FT8U100AX */ 108962306a36Sopenharmony_ci [FT232A] = "FT232A", 109062306a36Sopenharmony_ci [FT232B] = "FT232B", 109162306a36Sopenharmony_ci [FT2232C] = "FT2232C/D", 109262306a36Sopenharmony_ci [FT232R] = "FT232R", 109362306a36Sopenharmony_ci [FT232H] = "FT232H", 109462306a36Sopenharmony_ci [FT2232H] = "FT2232H", 109562306a36Sopenharmony_ci [FT4232H] = "FT4232H", 109662306a36Sopenharmony_ci [FT4232HA] = "FT4232HA", 109762306a36Sopenharmony_ci [FT232HP] = "FT232HP", 109862306a36Sopenharmony_ci [FT233HP] = "FT233HP", 109962306a36Sopenharmony_ci [FT2232HP] = "FT2232HP", 110062306a36Sopenharmony_ci [FT2233HP] = "FT2233HP", 110162306a36Sopenharmony_ci [FT4232HP] = "FT4232HP", 110262306a36Sopenharmony_ci [FT4233HP] = "FT4233HP", 110362306a36Sopenharmony_ci [FTX] = "FT-X", 110462306a36Sopenharmony_ci}; 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci/* Used for TIOCMIWAIT */ 110862306a36Sopenharmony_ci#define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD) 110962306a36Sopenharmony_ci#define FTDI_STATUS_B1_MASK (FTDI_RS_BI) 111062306a36Sopenharmony_ci/* End TIOCMIWAIT */ 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_cistatic void ftdi_set_termios(struct tty_struct *tty, 111362306a36Sopenharmony_ci struct usb_serial_port *port, 111462306a36Sopenharmony_ci const struct ktermios *old_termios); 111562306a36Sopenharmony_cistatic int ftdi_get_modem_status(struct usb_serial_port *port, 111662306a36Sopenharmony_ci unsigned char status[2]); 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci#define WDR_TIMEOUT 5000 /* default urb timeout */ 111962306a36Sopenharmony_ci#define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */ 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci/* 112262306a36Sopenharmony_ci * *************************************************************************** 112362306a36Sopenharmony_ci * Utility functions 112462306a36Sopenharmony_ci * *************************************************************************** 112562306a36Sopenharmony_ci */ 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_cistatic unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) 112862306a36Sopenharmony_ci{ 112962306a36Sopenharmony_ci unsigned short int divisor; 113062306a36Sopenharmony_ci /* divisor shifted 3 bits to the left */ 113162306a36Sopenharmony_ci int divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); 113262306a36Sopenharmony_ci if ((divisor3 & 0x7) == 7) 113362306a36Sopenharmony_ci divisor3++; /* round x.7/8 up to x+1 */ 113462306a36Sopenharmony_ci divisor = divisor3 >> 3; 113562306a36Sopenharmony_ci divisor3 &= 0x7; 113662306a36Sopenharmony_ci if (divisor3 == 1) 113762306a36Sopenharmony_ci divisor |= 0xc000; /* +0.125 */ 113862306a36Sopenharmony_ci else if (divisor3 >= 4) 113962306a36Sopenharmony_ci divisor |= 0x4000; /* +0.5 */ 114062306a36Sopenharmony_ci else if (divisor3 != 0) 114162306a36Sopenharmony_ci divisor |= 0x8000; /* +0.25 */ 114262306a36Sopenharmony_ci else if (divisor == 1) 114362306a36Sopenharmony_ci divisor = 0; /* special case for maximum baud rate */ 114462306a36Sopenharmony_ci return divisor; 114562306a36Sopenharmony_ci} 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_cistatic unsigned short int ftdi_232am_baud_to_divisor(int baud) 114862306a36Sopenharmony_ci{ 114962306a36Sopenharmony_ci return ftdi_232am_baud_base_to_divisor(baud, 48000000); 115062306a36Sopenharmony_ci} 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_cistatic u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) 115362306a36Sopenharmony_ci{ 115462306a36Sopenharmony_ci static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; 115562306a36Sopenharmony_ci u32 divisor; 115662306a36Sopenharmony_ci /* divisor shifted 3 bits to the left */ 115762306a36Sopenharmony_ci int divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); 115862306a36Sopenharmony_ci divisor = divisor3 >> 3; 115962306a36Sopenharmony_ci divisor |= (u32)divfrac[divisor3 & 0x7] << 14; 116062306a36Sopenharmony_ci /* Deal with special cases for highest baud rates. */ 116162306a36Sopenharmony_ci if (divisor == 1) /* 1.0 */ 116262306a36Sopenharmony_ci divisor = 0; 116362306a36Sopenharmony_ci else if (divisor == 0x4001) /* 1.5 */ 116462306a36Sopenharmony_ci divisor = 1; 116562306a36Sopenharmony_ci return divisor; 116662306a36Sopenharmony_ci} 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_cistatic u32 ftdi_232bm_baud_to_divisor(int baud) 116962306a36Sopenharmony_ci{ 117062306a36Sopenharmony_ci return ftdi_232bm_baud_base_to_divisor(baud, 48000000); 117162306a36Sopenharmony_ci} 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_cistatic u32 ftdi_2232h_baud_base_to_divisor(int baud, int base) 117462306a36Sopenharmony_ci{ 117562306a36Sopenharmony_ci static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; 117662306a36Sopenharmony_ci u32 divisor; 117762306a36Sopenharmony_ci int divisor3; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ 118062306a36Sopenharmony_ci divisor3 = DIV_ROUND_CLOSEST(8 * base, 10 * baud); 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci divisor = divisor3 >> 3; 118362306a36Sopenharmony_ci divisor |= (u32)divfrac[divisor3 & 0x7] << 14; 118462306a36Sopenharmony_ci /* Deal with special cases for highest baud rates. */ 118562306a36Sopenharmony_ci if (divisor == 1) /* 1.0 */ 118662306a36Sopenharmony_ci divisor = 0; 118762306a36Sopenharmony_ci else if (divisor == 0x4001) /* 1.5 */ 118862306a36Sopenharmony_ci divisor = 1; 118962306a36Sopenharmony_ci /* 119062306a36Sopenharmony_ci * Set this bit to turn off a divide by 2.5 on baud rate generator 119162306a36Sopenharmony_ci * This enables baud rates up to 12Mbaud but cannot reach below 1200 119262306a36Sopenharmony_ci * baud with this bit set 119362306a36Sopenharmony_ci */ 119462306a36Sopenharmony_ci divisor |= 0x00020000; 119562306a36Sopenharmony_ci return divisor; 119662306a36Sopenharmony_ci} 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_cistatic u32 ftdi_2232h_baud_to_divisor(int baud) 119962306a36Sopenharmony_ci{ 120062306a36Sopenharmony_ci return ftdi_2232h_baud_base_to_divisor(baud, 120000000); 120162306a36Sopenharmony_ci} 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci#define set_mctrl(port, set) update_mctrl((port), (set), 0) 120462306a36Sopenharmony_ci#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear)) 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_cistatic int update_mctrl(struct usb_serial_port *port, unsigned int set, 120762306a36Sopenharmony_ci unsigned int clear) 120862306a36Sopenharmony_ci{ 120962306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 121062306a36Sopenharmony_ci struct device *dev = &port->dev; 121162306a36Sopenharmony_ci unsigned value; 121262306a36Sopenharmony_ci int rv; 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { 121562306a36Sopenharmony_ci dev_dbg(dev, "%s - DTR|RTS not being set|cleared\n", __func__); 121662306a36Sopenharmony_ci return 0; /* no change */ 121762306a36Sopenharmony_ci } 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci clear &= ~set; /* 'set' takes precedence over 'clear' */ 122062306a36Sopenharmony_ci value = 0; 122162306a36Sopenharmony_ci if (clear & TIOCM_DTR) 122262306a36Sopenharmony_ci value |= FTDI_SIO_SET_DTR_LOW; 122362306a36Sopenharmony_ci if (clear & TIOCM_RTS) 122462306a36Sopenharmony_ci value |= FTDI_SIO_SET_RTS_LOW; 122562306a36Sopenharmony_ci if (set & TIOCM_DTR) 122662306a36Sopenharmony_ci value |= FTDI_SIO_SET_DTR_HIGH; 122762306a36Sopenharmony_ci if (set & TIOCM_RTS) 122862306a36Sopenharmony_ci value |= FTDI_SIO_SET_RTS_HIGH; 122962306a36Sopenharmony_ci rv = usb_control_msg(port->serial->dev, 123062306a36Sopenharmony_ci usb_sndctrlpipe(port->serial->dev, 0), 123162306a36Sopenharmony_ci FTDI_SIO_SET_MODEM_CTRL_REQUEST, 123262306a36Sopenharmony_ci FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, 123362306a36Sopenharmony_ci value, priv->channel, 123462306a36Sopenharmony_ci NULL, 0, WDR_TIMEOUT); 123562306a36Sopenharmony_ci if (rv < 0) { 123662306a36Sopenharmony_ci dev_dbg(dev, "%s Error from MODEM_CTRL urb: DTR %s, RTS %s\n", 123762306a36Sopenharmony_ci __func__, 123862306a36Sopenharmony_ci (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", 123962306a36Sopenharmony_ci (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged"); 124062306a36Sopenharmony_ci rv = usb_translate_errors(rv); 124162306a36Sopenharmony_ci } else { 124262306a36Sopenharmony_ci dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__, 124362306a36Sopenharmony_ci (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", 124462306a36Sopenharmony_ci (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged"); 124562306a36Sopenharmony_ci /* FIXME: locking on last_dtr_rts */ 124662306a36Sopenharmony_ci priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set; 124762306a36Sopenharmony_ci } 124862306a36Sopenharmony_ci return rv; 124962306a36Sopenharmony_ci} 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_cistatic u32 get_ftdi_divisor(struct tty_struct *tty, 125362306a36Sopenharmony_ci struct usb_serial_port *port) 125462306a36Sopenharmony_ci{ 125562306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 125662306a36Sopenharmony_ci struct device *dev = &port->dev; 125762306a36Sopenharmony_ci u32 div_value = 0; 125862306a36Sopenharmony_ci int div_okay = 1; 125962306a36Sopenharmony_ci int baud; 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci baud = tty_get_baud_rate(tty); 126262306a36Sopenharmony_ci dev_dbg(dev, "%s - tty_get_baud_rate reports speed %d\n", __func__, baud); 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci /* 126562306a36Sopenharmony_ci * Observe deprecated async-compatible custom_divisor hack, update 126662306a36Sopenharmony_ci * baudrate if needed. 126762306a36Sopenharmony_ci */ 126862306a36Sopenharmony_ci if (baud == 38400 && 126962306a36Sopenharmony_ci ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && 127062306a36Sopenharmony_ci (priv->custom_divisor)) { 127162306a36Sopenharmony_ci baud = priv->baud_base / priv->custom_divisor; 127262306a36Sopenharmony_ci dev_dbg(dev, "%s - custom divisor %d sets baud rate to %d\n", 127362306a36Sopenharmony_ci __func__, priv->custom_divisor, baud); 127462306a36Sopenharmony_ci } 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci if (!baud) 127762306a36Sopenharmony_ci baud = 9600; 127862306a36Sopenharmony_ci switch (priv->chip_type) { 127962306a36Sopenharmony_ci case SIO: 128062306a36Sopenharmony_ci switch (baud) { 128162306a36Sopenharmony_ci case 300: div_value = ftdi_sio_b300; break; 128262306a36Sopenharmony_ci case 600: div_value = ftdi_sio_b600; break; 128362306a36Sopenharmony_ci case 1200: div_value = ftdi_sio_b1200; break; 128462306a36Sopenharmony_ci case 2400: div_value = ftdi_sio_b2400; break; 128562306a36Sopenharmony_ci case 4800: div_value = ftdi_sio_b4800; break; 128662306a36Sopenharmony_ci case 9600: div_value = ftdi_sio_b9600; break; 128762306a36Sopenharmony_ci case 19200: div_value = ftdi_sio_b19200; break; 128862306a36Sopenharmony_ci case 38400: div_value = ftdi_sio_b38400; break; 128962306a36Sopenharmony_ci case 57600: div_value = ftdi_sio_b57600; break; 129062306a36Sopenharmony_ci case 115200: div_value = ftdi_sio_b115200; break; 129162306a36Sopenharmony_ci default: 129262306a36Sopenharmony_ci dev_dbg(dev, "%s - Baudrate (%d) requested is not supported\n", 129362306a36Sopenharmony_ci __func__, baud); 129462306a36Sopenharmony_ci div_value = ftdi_sio_b9600; 129562306a36Sopenharmony_ci baud = 9600; 129662306a36Sopenharmony_ci div_okay = 0; 129762306a36Sopenharmony_ci } 129862306a36Sopenharmony_ci break; 129962306a36Sopenharmony_ci case FT232A: 130062306a36Sopenharmony_ci if (baud <= 3000000) { 130162306a36Sopenharmony_ci div_value = ftdi_232am_baud_to_divisor(baud); 130262306a36Sopenharmony_ci } else { 130362306a36Sopenharmony_ci dev_dbg(dev, "%s - Baud rate too high!\n", __func__); 130462306a36Sopenharmony_ci baud = 9600; 130562306a36Sopenharmony_ci div_value = ftdi_232am_baud_to_divisor(9600); 130662306a36Sopenharmony_ci div_okay = 0; 130762306a36Sopenharmony_ci } 130862306a36Sopenharmony_ci break; 130962306a36Sopenharmony_ci case FT232B: 131062306a36Sopenharmony_ci case FT2232C: 131162306a36Sopenharmony_ci case FT232R: 131262306a36Sopenharmony_ci case FTX: 131362306a36Sopenharmony_ci if (baud <= 3000000) { 131462306a36Sopenharmony_ci u16 product_id = le16_to_cpu( 131562306a36Sopenharmony_ci port->serial->dev->descriptor.idProduct); 131662306a36Sopenharmony_ci if (((product_id == FTDI_NDI_HUC_PID) || 131762306a36Sopenharmony_ci (product_id == FTDI_NDI_SPECTRA_SCU_PID) || 131862306a36Sopenharmony_ci (product_id == FTDI_NDI_FUTURE_2_PID) || 131962306a36Sopenharmony_ci (product_id == FTDI_NDI_FUTURE_3_PID) || 132062306a36Sopenharmony_ci (product_id == FTDI_NDI_AURORA_SCU_PID)) && 132162306a36Sopenharmony_ci (baud == 19200)) { 132262306a36Sopenharmony_ci baud = 1200000; 132362306a36Sopenharmony_ci } 132462306a36Sopenharmony_ci div_value = ftdi_232bm_baud_to_divisor(baud); 132562306a36Sopenharmony_ci } else { 132662306a36Sopenharmony_ci dev_dbg(dev, "%s - Baud rate too high!\n", __func__); 132762306a36Sopenharmony_ci div_value = ftdi_232bm_baud_to_divisor(9600); 132862306a36Sopenharmony_ci div_okay = 0; 132962306a36Sopenharmony_ci baud = 9600; 133062306a36Sopenharmony_ci } 133162306a36Sopenharmony_ci break; 133262306a36Sopenharmony_ci default: 133362306a36Sopenharmony_ci if ((baud <= 12000000) && (baud >= 1200)) { 133462306a36Sopenharmony_ci div_value = ftdi_2232h_baud_to_divisor(baud); 133562306a36Sopenharmony_ci } else if (baud < 1200) { 133662306a36Sopenharmony_ci div_value = ftdi_232bm_baud_to_divisor(baud); 133762306a36Sopenharmony_ci } else { 133862306a36Sopenharmony_ci dev_dbg(dev, "%s - Baud rate too high!\n", __func__); 133962306a36Sopenharmony_ci div_value = ftdi_232bm_baud_to_divisor(9600); 134062306a36Sopenharmony_ci div_okay = 0; 134162306a36Sopenharmony_ci baud = 9600; 134262306a36Sopenharmony_ci } 134362306a36Sopenharmony_ci break; 134462306a36Sopenharmony_ci } 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci if (div_okay) { 134762306a36Sopenharmony_ci dev_dbg(dev, "%s - Baud rate set to %d (divisor 0x%lX) on chip %s\n", 134862306a36Sopenharmony_ci __func__, baud, (unsigned long)div_value, 134962306a36Sopenharmony_ci ftdi_chip_name[priv->chip_type]); 135062306a36Sopenharmony_ci } 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci tty_encode_baud_rate(tty, baud, baud); 135362306a36Sopenharmony_ci return div_value; 135462306a36Sopenharmony_ci} 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_cistatic int change_speed(struct tty_struct *tty, struct usb_serial_port *port) 135762306a36Sopenharmony_ci{ 135862306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 135962306a36Sopenharmony_ci u16 value; 136062306a36Sopenharmony_ci u16 index; 136162306a36Sopenharmony_ci u32 index_value; 136262306a36Sopenharmony_ci int rv; 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci index_value = get_ftdi_divisor(tty, port); 136562306a36Sopenharmony_ci value = (u16)index_value; 136662306a36Sopenharmony_ci index = (u16)(index_value >> 16); 136762306a36Sopenharmony_ci if (priv->channel) 136862306a36Sopenharmony_ci index = (u16)((index << 8) | priv->channel); 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci rv = usb_control_msg(port->serial->dev, 137162306a36Sopenharmony_ci usb_sndctrlpipe(port->serial->dev, 0), 137262306a36Sopenharmony_ci FTDI_SIO_SET_BAUDRATE_REQUEST, 137362306a36Sopenharmony_ci FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, 137462306a36Sopenharmony_ci value, index, 137562306a36Sopenharmony_ci NULL, 0, WDR_SHORT_TIMEOUT); 137662306a36Sopenharmony_ci return rv; 137762306a36Sopenharmony_ci} 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_cistatic int write_latency_timer(struct usb_serial_port *port) 138062306a36Sopenharmony_ci{ 138162306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 138262306a36Sopenharmony_ci struct usb_device *udev = port->serial->dev; 138362306a36Sopenharmony_ci int rv; 138462306a36Sopenharmony_ci int l = priv->latency; 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci if (priv->chip_type == SIO || priv->chip_type == FT232A) 138762306a36Sopenharmony_ci return -EINVAL; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci if (priv->flags & ASYNC_LOW_LATENCY) 139062306a36Sopenharmony_ci l = 1; 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci dev_dbg(&port->dev, "%s: setting latency timer = %i\n", __func__, l); 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci rv = usb_control_msg(udev, 139562306a36Sopenharmony_ci usb_sndctrlpipe(udev, 0), 139662306a36Sopenharmony_ci FTDI_SIO_SET_LATENCY_TIMER_REQUEST, 139762306a36Sopenharmony_ci FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, 139862306a36Sopenharmony_ci l, priv->channel, 139962306a36Sopenharmony_ci NULL, 0, WDR_TIMEOUT); 140062306a36Sopenharmony_ci if (rv < 0) 140162306a36Sopenharmony_ci dev_err(&port->dev, "Unable to write latency timer: %i\n", rv); 140262306a36Sopenharmony_ci return rv; 140362306a36Sopenharmony_ci} 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_cistatic int _read_latency_timer(struct usb_serial_port *port) 140662306a36Sopenharmony_ci{ 140762306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 140862306a36Sopenharmony_ci struct usb_device *udev = port->serial->dev; 140962306a36Sopenharmony_ci u8 buf; 141062306a36Sopenharmony_ci int rv; 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci rv = usb_control_msg_recv(udev, 0, FTDI_SIO_GET_LATENCY_TIMER_REQUEST, 141362306a36Sopenharmony_ci FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, 0, 141462306a36Sopenharmony_ci priv->channel, &buf, 1, WDR_TIMEOUT, 141562306a36Sopenharmony_ci GFP_KERNEL); 141662306a36Sopenharmony_ci if (rv == 0) 141762306a36Sopenharmony_ci rv = buf; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci return rv; 142062306a36Sopenharmony_ci} 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_cistatic int read_latency_timer(struct usb_serial_port *port) 142362306a36Sopenharmony_ci{ 142462306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 142562306a36Sopenharmony_ci int rv; 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_ci if (priv->chip_type == SIO || priv->chip_type == FT232A) 142862306a36Sopenharmony_ci return -EINVAL; 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci rv = _read_latency_timer(port); 143162306a36Sopenharmony_ci if (rv < 0) { 143262306a36Sopenharmony_ci dev_err(&port->dev, "Unable to read latency timer: %i\n", rv); 143362306a36Sopenharmony_ci return rv; 143462306a36Sopenharmony_ci } 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci priv->latency = rv; 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci return 0; 143962306a36Sopenharmony_ci} 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_cistatic void get_serial_info(struct tty_struct *tty, struct serial_struct *ss) 144262306a36Sopenharmony_ci{ 144362306a36Sopenharmony_ci struct usb_serial_port *port = tty->driver_data; 144462306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 144562306a36Sopenharmony_ci 144662306a36Sopenharmony_ci ss->flags = priv->flags; 144762306a36Sopenharmony_ci ss->baud_base = priv->baud_base; 144862306a36Sopenharmony_ci ss->custom_divisor = priv->custom_divisor; 144962306a36Sopenharmony_ci} 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_cistatic int set_serial_info(struct tty_struct *tty, struct serial_struct *ss) 145262306a36Sopenharmony_ci{ 145362306a36Sopenharmony_ci struct usb_serial_port *port = tty->driver_data; 145462306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 145562306a36Sopenharmony_ci int old_flags, old_divisor; 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_ci mutex_lock(&priv->cfg_lock); 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) { 146062306a36Sopenharmony_ci if ((ss->flags ^ priv->flags) & ~ASYNC_USR_MASK) { 146162306a36Sopenharmony_ci mutex_unlock(&priv->cfg_lock); 146262306a36Sopenharmony_ci return -EPERM; 146362306a36Sopenharmony_ci } 146462306a36Sopenharmony_ci } 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci old_flags = priv->flags; 146762306a36Sopenharmony_ci old_divisor = priv->custom_divisor; 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci priv->flags = ss->flags & ASYNC_FLAGS; 147062306a36Sopenharmony_ci priv->custom_divisor = ss->custom_divisor; 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci write_latency_timer(port); 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci if ((priv->flags ^ old_flags) & ASYNC_SPD_MASK || 147562306a36Sopenharmony_ci ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && 147662306a36Sopenharmony_ci priv->custom_divisor != old_divisor)) { 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci /* warn about deprecation unless clearing */ 147962306a36Sopenharmony_ci if (priv->flags & ASYNC_SPD_MASK) 148062306a36Sopenharmony_ci dev_warn_ratelimited(&port->dev, "use of SPD flags is deprecated\n"); 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci change_speed(tty, port); 148362306a36Sopenharmony_ci } 148462306a36Sopenharmony_ci mutex_unlock(&priv->cfg_lock); 148562306a36Sopenharmony_ci return 0; 148662306a36Sopenharmony_ci} 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_cistatic int get_lsr_info(struct usb_serial_port *port, 148962306a36Sopenharmony_ci unsigned int __user *retinfo) 149062306a36Sopenharmony_ci{ 149162306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 149262306a36Sopenharmony_ci unsigned int result = 0; 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci if (priv->transmit_empty) 149562306a36Sopenharmony_ci result = TIOCSER_TEMT; 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci if (copy_to_user(retinfo, &result, sizeof(unsigned int))) 149862306a36Sopenharmony_ci return -EFAULT; 149962306a36Sopenharmony_ci return 0; 150062306a36Sopenharmony_ci} 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_cistatic int ftdi_determine_type(struct usb_serial_port *port) 150362306a36Sopenharmony_ci{ 150462306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 150562306a36Sopenharmony_ci struct usb_serial *serial = port->serial; 150662306a36Sopenharmony_ci struct usb_device *udev = serial->dev; 150762306a36Sopenharmony_ci unsigned int version, ifnum; 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci version = le16_to_cpu(udev->descriptor.bcdDevice); 151062306a36Sopenharmony_ci ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci /* Assume Hi-Speed type */ 151362306a36Sopenharmony_ci priv->baud_base = 120000000 / 2; 151462306a36Sopenharmony_ci priv->channel = CHANNEL_A + ifnum; 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci switch (version) { 151762306a36Sopenharmony_ci case 0x200: 151862306a36Sopenharmony_ci priv->chip_type = FT232A; 151962306a36Sopenharmony_ci priv->baud_base = 48000000 / 2; 152062306a36Sopenharmony_ci priv->channel = 0; 152162306a36Sopenharmony_ci /* 152262306a36Sopenharmony_ci * FT232B devices have a bug where bcdDevice gets set to 0x200 152362306a36Sopenharmony_ci * when iSerialNumber is 0. Assume it is an FT232B in case the 152462306a36Sopenharmony_ci * latency timer is readable. 152562306a36Sopenharmony_ci */ 152662306a36Sopenharmony_ci if (udev->descriptor.iSerialNumber == 0 && 152762306a36Sopenharmony_ci _read_latency_timer(port) >= 0) { 152862306a36Sopenharmony_ci priv->chip_type = FT232B; 152962306a36Sopenharmony_ci } 153062306a36Sopenharmony_ci break; 153162306a36Sopenharmony_ci case 0x400: 153262306a36Sopenharmony_ci priv->chip_type = FT232B; 153362306a36Sopenharmony_ci priv->baud_base = 48000000 / 2; 153462306a36Sopenharmony_ci priv->channel = 0; 153562306a36Sopenharmony_ci break; 153662306a36Sopenharmony_ci case 0x500: 153762306a36Sopenharmony_ci priv->chip_type = FT2232C; 153862306a36Sopenharmony_ci priv->baud_base = 48000000 / 2; 153962306a36Sopenharmony_ci break; 154062306a36Sopenharmony_ci case 0x600: 154162306a36Sopenharmony_ci priv->chip_type = FT232R; 154262306a36Sopenharmony_ci priv->baud_base = 48000000 / 2; 154362306a36Sopenharmony_ci priv->channel = 0; 154462306a36Sopenharmony_ci break; 154562306a36Sopenharmony_ci case 0x700: 154662306a36Sopenharmony_ci priv->chip_type = FT2232H; 154762306a36Sopenharmony_ci break; 154862306a36Sopenharmony_ci case 0x800: 154962306a36Sopenharmony_ci priv->chip_type = FT4232H; 155062306a36Sopenharmony_ci break; 155162306a36Sopenharmony_ci case 0x900: 155262306a36Sopenharmony_ci priv->chip_type = FT232H; 155362306a36Sopenharmony_ci break; 155462306a36Sopenharmony_ci case 0x1000: 155562306a36Sopenharmony_ci priv->chip_type = FTX; 155662306a36Sopenharmony_ci priv->baud_base = 48000000 / 2; 155762306a36Sopenharmony_ci break; 155862306a36Sopenharmony_ci case 0x2800: 155962306a36Sopenharmony_ci priv->chip_type = FT2233HP; 156062306a36Sopenharmony_ci break; 156162306a36Sopenharmony_ci case 0x2900: 156262306a36Sopenharmony_ci priv->chip_type = FT4233HP; 156362306a36Sopenharmony_ci break; 156462306a36Sopenharmony_ci case 0x3000: 156562306a36Sopenharmony_ci priv->chip_type = FT2232HP; 156662306a36Sopenharmony_ci break; 156762306a36Sopenharmony_ci case 0x3100: 156862306a36Sopenharmony_ci priv->chip_type = FT4232HP; 156962306a36Sopenharmony_ci break; 157062306a36Sopenharmony_ci case 0x3200: 157162306a36Sopenharmony_ci priv->chip_type = FT233HP; 157262306a36Sopenharmony_ci break; 157362306a36Sopenharmony_ci case 0x3300: 157462306a36Sopenharmony_ci priv->chip_type = FT232HP; 157562306a36Sopenharmony_ci break; 157662306a36Sopenharmony_ci case 0x3600: 157762306a36Sopenharmony_ci priv->chip_type = FT4232HA; 157862306a36Sopenharmony_ci break; 157962306a36Sopenharmony_ci default: 158062306a36Sopenharmony_ci if (version < 0x200) { 158162306a36Sopenharmony_ci priv->chip_type = SIO; 158262306a36Sopenharmony_ci priv->baud_base = 12000000 / 16; 158362306a36Sopenharmony_ci priv->channel = 0; 158462306a36Sopenharmony_ci } else { 158562306a36Sopenharmony_ci dev_err(&port->dev, "unknown device type: 0x%02x\n", version); 158662306a36Sopenharmony_ci return -ENODEV; 158762306a36Sopenharmony_ci } 158862306a36Sopenharmony_ci } 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]); 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci return 0; 159362306a36Sopenharmony_ci} 159462306a36Sopenharmony_ci 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_ci/* 159762306a36Sopenharmony_ci * Determine the maximum packet size for the device. This depends on the chip 159862306a36Sopenharmony_ci * type and the USB host capabilities. The value should be obtained from the 159962306a36Sopenharmony_ci * device descriptor as the chip will use the appropriate values for the host. 160062306a36Sopenharmony_ci */ 160162306a36Sopenharmony_cistatic void ftdi_set_max_packet_size(struct usb_serial_port *port) 160262306a36Sopenharmony_ci{ 160362306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 160462306a36Sopenharmony_ci struct usb_interface *interface = port->serial->interface; 160562306a36Sopenharmony_ci struct usb_endpoint_descriptor *ep_desc; 160662306a36Sopenharmony_ci unsigned num_endpoints; 160762306a36Sopenharmony_ci unsigned i; 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci num_endpoints = interface->cur_altsetting->desc.bNumEndpoints; 161062306a36Sopenharmony_ci if (!num_endpoints) 161162306a36Sopenharmony_ci return; 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ci /* 161462306a36Sopenharmony_ci * NOTE: Some customers have programmed FT232R/FT245R devices 161562306a36Sopenharmony_ci * with an endpoint size of 0 - not good. In this case, we 161662306a36Sopenharmony_ci * want to override the endpoint descriptor setting and use a 161762306a36Sopenharmony_ci * value of 64 for wMaxPacketSize. 161862306a36Sopenharmony_ci */ 161962306a36Sopenharmony_ci for (i = 0; i < num_endpoints; i++) { 162062306a36Sopenharmony_ci ep_desc = &interface->cur_altsetting->endpoint[i].desc; 162162306a36Sopenharmony_ci if (!ep_desc->wMaxPacketSize) { 162262306a36Sopenharmony_ci ep_desc->wMaxPacketSize = cpu_to_le16(0x40); 162362306a36Sopenharmony_ci dev_warn(&port->dev, "Overriding wMaxPacketSize on endpoint %d\n", 162462306a36Sopenharmony_ci usb_endpoint_num(ep_desc)); 162562306a36Sopenharmony_ci } 162662306a36Sopenharmony_ci } 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci /* Set max packet size based on last descriptor. */ 162962306a36Sopenharmony_ci priv->max_packet_size = usb_endpoint_maxp(ep_desc); 163062306a36Sopenharmony_ci} 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci/* 163462306a36Sopenharmony_ci * *************************************************************************** 163562306a36Sopenharmony_ci * Sysfs Attribute 163662306a36Sopenharmony_ci * *************************************************************************** 163762306a36Sopenharmony_ci */ 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_cistatic ssize_t latency_timer_show(struct device *dev, 164062306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 164162306a36Sopenharmony_ci{ 164262306a36Sopenharmony_ci struct usb_serial_port *port = to_usb_serial_port(dev); 164362306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 164462306a36Sopenharmony_ci if (priv->flags & ASYNC_LOW_LATENCY) 164562306a36Sopenharmony_ci return sprintf(buf, "1\n"); 164662306a36Sopenharmony_ci else 164762306a36Sopenharmony_ci return sprintf(buf, "%u\n", priv->latency); 164862306a36Sopenharmony_ci} 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci/* Write a new value of the latency timer, in units of milliseconds. */ 165162306a36Sopenharmony_cistatic ssize_t latency_timer_store(struct device *dev, 165262306a36Sopenharmony_ci struct device_attribute *attr, 165362306a36Sopenharmony_ci const char *valbuf, size_t count) 165462306a36Sopenharmony_ci{ 165562306a36Sopenharmony_ci struct usb_serial_port *port = to_usb_serial_port(dev); 165662306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 165762306a36Sopenharmony_ci u8 v; 165862306a36Sopenharmony_ci int rv; 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci if (kstrtou8(valbuf, 10, &v)) 166162306a36Sopenharmony_ci return -EINVAL; 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci priv->latency = v; 166462306a36Sopenharmony_ci rv = write_latency_timer(port); 166562306a36Sopenharmony_ci if (rv < 0) 166662306a36Sopenharmony_ci return -EIO; 166762306a36Sopenharmony_ci return count; 166862306a36Sopenharmony_ci} 166962306a36Sopenharmony_cistatic DEVICE_ATTR_RW(latency_timer); 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci/* Write an event character directly to the FTDI register. The ASCII 167262306a36Sopenharmony_ci value is in the low 8 bits, with the enable bit in the 9th bit. */ 167362306a36Sopenharmony_cistatic ssize_t event_char_store(struct device *dev, 167462306a36Sopenharmony_ci struct device_attribute *attr, const char *valbuf, size_t count) 167562306a36Sopenharmony_ci{ 167662306a36Sopenharmony_ci struct usb_serial_port *port = to_usb_serial_port(dev); 167762306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 167862306a36Sopenharmony_ci struct usb_device *udev = port->serial->dev; 167962306a36Sopenharmony_ci unsigned int v; 168062306a36Sopenharmony_ci int rv; 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci if (kstrtouint(valbuf, 0, &v) || v >= 0x200) 168362306a36Sopenharmony_ci return -EINVAL; 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci dev_dbg(&port->dev, "%s: setting event char = 0x%03x\n", __func__, v); 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci rv = usb_control_msg(udev, 168862306a36Sopenharmony_ci usb_sndctrlpipe(udev, 0), 168962306a36Sopenharmony_ci FTDI_SIO_SET_EVENT_CHAR_REQUEST, 169062306a36Sopenharmony_ci FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE, 169162306a36Sopenharmony_ci v, priv->channel, 169262306a36Sopenharmony_ci NULL, 0, WDR_TIMEOUT); 169362306a36Sopenharmony_ci if (rv < 0) { 169462306a36Sopenharmony_ci dev_dbg(&port->dev, "Unable to write event character: %i\n", rv); 169562306a36Sopenharmony_ci return -EIO; 169662306a36Sopenharmony_ci } 169762306a36Sopenharmony_ci 169862306a36Sopenharmony_ci return count; 169962306a36Sopenharmony_ci} 170062306a36Sopenharmony_cistatic DEVICE_ATTR_WO(event_char); 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_cistatic struct attribute *ftdi_attrs[] = { 170362306a36Sopenharmony_ci &dev_attr_event_char.attr, 170462306a36Sopenharmony_ci &dev_attr_latency_timer.attr, 170562306a36Sopenharmony_ci NULL 170662306a36Sopenharmony_ci}; 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_cistatic umode_t ftdi_is_visible(struct kobject *kobj, struct attribute *attr, int idx) 170962306a36Sopenharmony_ci{ 171062306a36Sopenharmony_ci struct device *dev = kobj_to_dev(kobj); 171162306a36Sopenharmony_ci struct usb_serial_port *port = to_usb_serial_port(dev); 171262306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 171362306a36Sopenharmony_ci enum ftdi_chip_type type = priv->chip_type; 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci if (attr == &dev_attr_event_char.attr) { 171662306a36Sopenharmony_ci if (type == SIO) 171762306a36Sopenharmony_ci return 0; 171862306a36Sopenharmony_ci } 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci if (attr == &dev_attr_latency_timer.attr) { 172162306a36Sopenharmony_ci if (type == SIO || type == FT232A) 172262306a36Sopenharmony_ci return 0; 172362306a36Sopenharmony_ci } 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci return attr->mode; 172662306a36Sopenharmony_ci} 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_cistatic const struct attribute_group ftdi_group = { 172962306a36Sopenharmony_ci .attrs = ftdi_attrs, 173062306a36Sopenharmony_ci .is_visible = ftdi_is_visible, 173162306a36Sopenharmony_ci}; 173262306a36Sopenharmony_ci 173362306a36Sopenharmony_cistatic const struct attribute_group *ftdi_groups[] = { 173462306a36Sopenharmony_ci &ftdi_group, 173562306a36Sopenharmony_ci NULL 173662306a36Sopenharmony_ci}; 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci#ifdef CONFIG_GPIOLIB 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_cistatic int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode) 174162306a36Sopenharmony_ci{ 174262306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 174362306a36Sopenharmony_ci struct usb_serial *serial = port->serial; 174462306a36Sopenharmony_ci int result; 174562306a36Sopenharmony_ci u16 val; 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci result = usb_autopm_get_interface(serial->interface); 174862306a36Sopenharmony_ci if (result) 174962306a36Sopenharmony_ci return result; 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_ci val = (mode << 8) | (priv->gpio_output << 4) | priv->gpio_value; 175262306a36Sopenharmony_ci result = usb_control_msg(serial->dev, 175362306a36Sopenharmony_ci usb_sndctrlpipe(serial->dev, 0), 175462306a36Sopenharmony_ci FTDI_SIO_SET_BITMODE_REQUEST, 175562306a36Sopenharmony_ci FTDI_SIO_SET_BITMODE_REQUEST_TYPE, val, 175662306a36Sopenharmony_ci priv->channel, NULL, 0, WDR_TIMEOUT); 175762306a36Sopenharmony_ci if (result < 0) { 175862306a36Sopenharmony_ci dev_err(&serial->interface->dev, 175962306a36Sopenharmony_ci "bitmode request failed for value 0x%04x: %d\n", 176062306a36Sopenharmony_ci val, result); 176162306a36Sopenharmony_ci } 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci usb_autopm_put_interface(serial->interface); 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci return result; 176662306a36Sopenharmony_ci} 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_cistatic int ftdi_set_cbus_pins(struct usb_serial_port *port) 176962306a36Sopenharmony_ci{ 177062306a36Sopenharmony_ci return ftdi_set_bitmode(port, FTDI_SIO_BITMODE_CBUS); 177162306a36Sopenharmony_ci} 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_cistatic int ftdi_exit_cbus_mode(struct usb_serial_port *port) 177462306a36Sopenharmony_ci{ 177562306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci priv->gpio_output = 0; 177862306a36Sopenharmony_ci priv->gpio_value = 0; 177962306a36Sopenharmony_ci return ftdi_set_bitmode(port, FTDI_SIO_BITMODE_RESET); 178062306a36Sopenharmony_ci} 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_cistatic int ftdi_gpio_request(struct gpio_chip *gc, unsigned int offset) 178362306a36Sopenharmony_ci{ 178462306a36Sopenharmony_ci struct usb_serial_port *port = gpiochip_get_data(gc); 178562306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 178662306a36Sopenharmony_ci int result; 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci mutex_lock(&priv->gpio_lock); 178962306a36Sopenharmony_ci if (!priv->gpio_used) { 179062306a36Sopenharmony_ci /* Set default pin states, as we cannot get them from device */ 179162306a36Sopenharmony_ci priv->gpio_output = 0x00; 179262306a36Sopenharmony_ci priv->gpio_value = 0x00; 179362306a36Sopenharmony_ci result = ftdi_set_cbus_pins(port); 179462306a36Sopenharmony_ci if (result) { 179562306a36Sopenharmony_ci mutex_unlock(&priv->gpio_lock); 179662306a36Sopenharmony_ci return result; 179762306a36Sopenharmony_ci } 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci priv->gpio_used = true; 180062306a36Sopenharmony_ci } 180162306a36Sopenharmony_ci mutex_unlock(&priv->gpio_lock); 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci return 0; 180462306a36Sopenharmony_ci} 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_cistatic int ftdi_read_cbus_pins(struct usb_serial_port *port) 180762306a36Sopenharmony_ci{ 180862306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 180962306a36Sopenharmony_ci struct usb_serial *serial = port->serial; 181062306a36Sopenharmony_ci u8 buf; 181162306a36Sopenharmony_ci int result; 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci result = usb_autopm_get_interface(serial->interface); 181462306a36Sopenharmony_ci if (result) 181562306a36Sopenharmony_ci return result; 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci result = usb_control_msg_recv(serial->dev, 0, 181862306a36Sopenharmony_ci FTDI_SIO_READ_PINS_REQUEST, 181962306a36Sopenharmony_ci FTDI_SIO_READ_PINS_REQUEST_TYPE, 0, 182062306a36Sopenharmony_ci priv->channel, &buf, 1, WDR_TIMEOUT, 182162306a36Sopenharmony_ci GFP_KERNEL); 182262306a36Sopenharmony_ci if (result == 0) 182362306a36Sopenharmony_ci result = buf; 182462306a36Sopenharmony_ci 182562306a36Sopenharmony_ci usb_autopm_put_interface(serial->interface); 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_ci return result; 182862306a36Sopenharmony_ci} 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_cistatic int ftdi_gpio_get(struct gpio_chip *gc, unsigned int gpio) 183162306a36Sopenharmony_ci{ 183262306a36Sopenharmony_ci struct usb_serial_port *port = gpiochip_get_data(gc); 183362306a36Sopenharmony_ci int result; 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci result = ftdi_read_cbus_pins(port); 183662306a36Sopenharmony_ci if (result < 0) 183762306a36Sopenharmony_ci return result; 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci return !!(result & BIT(gpio)); 184062306a36Sopenharmony_ci} 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_cistatic void ftdi_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value) 184362306a36Sopenharmony_ci{ 184462306a36Sopenharmony_ci struct usb_serial_port *port = gpiochip_get_data(gc); 184562306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 184662306a36Sopenharmony_ci 184762306a36Sopenharmony_ci mutex_lock(&priv->gpio_lock); 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci if (value) 185062306a36Sopenharmony_ci priv->gpio_value |= BIT(gpio); 185162306a36Sopenharmony_ci else 185262306a36Sopenharmony_ci priv->gpio_value &= ~BIT(gpio); 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci ftdi_set_cbus_pins(port); 185562306a36Sopenharmony_ci 185662306a36Sopenharmony_ci mutex_unlock(&priv->gpio_lock); 185762306a36Sopenharmony_ci} 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_cistatic int ftdi_gpio_get_multiple(struct gpio_chip *gc, unsigned long *mask, 186062306a36Sopenharmony_ci unsigned long *bits) 186162306a36Sopenharmony_ci{ 186262306a36Sopenharmony_ci struct usb_serial_port *port = gpiochip_get_data(gc); 186362306a36Sopenharmony_ci int result; 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_ci result = ftdi_read_cbus_pins(port); 186662306a36Sopenharmony_ci if (result < 0) 186762306a36Sopenharmony_ci return result; 186862306a36Sopenharmony_ci 186962306a36Sopenharmony_ci *bits = result & *mask; 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci return 0; 187262306a36Sopenharmony_ci} 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_cistatic void ftdi_gpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, 187562306a36Sopenharmony_ci unsigned long *bits) 187662306a36Sopenharmony_ci{ 187762306a36Sopenharmony_ci struct usb_serial_port *port = gpiochip_get_data(gc); 187862306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 187962306a36Sopenharmony_ci 188062306a36Sopenharmony_ci mutex_lock(&priv->gpio_lock); 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ci priv->gpio_value &= ~(*mask); 188362306a36Sopenharmony_ci priv->gpio_value |= *bits & *mask; 188462306a36Sopenharmony_ci ftdi_set_cbus_pins(port); 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci mutex_unlock(&priv->gpio_lock); 188762306a36Sopenharmony_ci} 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_cistatic int ftdi_gpio_direction_get(struct gpio_chip *gc, unsigned int gpio) 189062306a36Sopenharmony_ci{ 189162306a36Sopenharmony_ci struct usb_serial_port *port = gpiochip_get_data(gc); 189262306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci return !(priv->gpio_output & BIT(gpio)); 189562306a36Sopenharmony_ci} 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_cistatic int ftdi_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio) 189862306a36Sopenharmony_ci{ 189962306a36Sopenharmony_ci struct usb_serial_port *port = gpiochip_get_data(gc); 190062306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 190162306a36Sopenharmony_ci int result; 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci mutex_lock(&priv->gpio_lock); 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci priv->gpio_output &= ~BIT(gpio); 190662306a36Sopenharmony_ci result = ftdi_set_cbus_pins(port); 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci mutex_unlock(&priv->gpio_lock); 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci return result; 191162306a36Sopenharmony_ci} 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_cistatic int ftdi_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio, 191462306a36Sopenharmony_ci int value) 191562306a36Sopenharmony_ci{ 191662306a36Sopenharmony_ci struct usb_serial_port *port = gpiochip_get_data(gc); 191762306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 191862306a36Sopenharmony_ci int result; 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_ci mutex_lock(&priv->gpio_lock); 192162306a36Sopenharmony_ci 192262306a36Sopenharmony_ci priv->gpio_output |= BIT(gpio); 192362306a36Sopenharmony_ci if (value) 192462306a36Sopenharmony_ci priv->gpio_value |= BIT(gpio); 192562306a36Sopenharmony_ci else 192662306a36Sopenharmony_ci priv->gpio_value &= ~BIT(gpio); 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci result = ftdi_set_cbus_pins(port); 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci mutex_unlock(&priv->gpio_lock); 193162306a36Sopenharmony_ci 193262306a36Sopenharmony_ci return result; 193362306a36Sopenharmony_ci} 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_cistatic int ftdi_gpio_init_valid_mask(struct gpio_chip *gc, 193662306a36Sopenharmony_ci unsigned long *valid_mask, 193762306a36Sopenharmony_ci unsigned int ngpios) 193862306a36Sopenharmony_ci{ 193962306a36Sopenharmony_ci struct usb_serial_port *port = gpiochip_get_data(gc); 194062306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 194162306a36Sopenharmony_ci unsigned long map = priv->gpio_altfunc; 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_ci bitmap_complement(valid_mask, &map, ngpios); 194462306a36Sopenharmony_ci 194562306a36Sopenharmony_ci if (bitmap_empty(valid_mask, ngpios)) 194662306a36Sopenharmony_ci dev_dbg(&port->dev, "no CBUS pin configured for GPIO\n"); 194762306a36Sopenharmony_ci else 194862306a36Sopenharmony_ci dev_dbg(&port->dev, "CBUS%*pbl configured for GPIO\n", ngpios, 194962306a36Sopenharmony_ci valid_mask); 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ci return 0; 195262306a36Sopenharmony_ci} 195362306a36Sopenharmony_ci 195462306a36Sopenharmony_cistatic int ftdi_read_eeprom(struct usb_serial *serial, void *dst, u16 addr, 195562306a36Sopenharmony_ci u16 nbytes) 195662306a36Sopenharmony_ci{ 195762306a36Sopenharmony_ci int read = 0; 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci if (addr % 2 != 0) 196062306a36Sopenharmony_ci return -EINVAL; 196162306a36Sopenharmony_ci if (nbytes % 2 != 0) 196262306a36Sopenharmony_ci return -EINVAL; 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ci /* Read EEPROM two bytes at a time */ 196562306a36Sopenharmony_ci while (read < nbytes) { 196662306a36Sopenharmony_ci int rv; 196762306a36Sopenharmony_ci 196862306a36Sopenharmony_ci rv = usb_control_msg(serial->dev, 196962306a36Sopenharmony_ci usb_rcvctrlpipe(serial->dev, 0), 197062306a36Sopenharmony_ci FTDI_SIO_READ_EEPROM_REQUEST, 197162306a36Sopenharmony_ci FTDI_SIO_READ_EEPROM_REQUEST_TYPE, 197262306a36Sopenharmony_ci 0, (addr + read) / 2, dst + read, 2, 197362306a36Sopenharmony_ci WDR_TIMEOUT); 197462306a36Sopenharmony_ci if (rv < 2) { 197562306a36Sopenharmony_ci if (rv >= 0) 197662306a36Sopenharmony_ci return -EIO; 197762306a36Sopenharmony_ci else 197862306a36Sopenharmony_ci return rv; 197962306a36Sopenharmony_ci } 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci read += rv; 198262306a36Sopenharmony_ci } 198362306a36Sopenharmony_ci 198462306a36Sopenharmony_ci return 0; 198562306a36Sopenharmony_ci} 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_cistatic int ftdi_gpio_init_ft232h(struct usb_serial_port *port) 198862306a36Sopenharmony_ci{ 198962306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 199062306a36Sopenharmony_ci u16 cbus_config; 199162306a36Sopenharmony_ci u8 *buf; 199262306a36Sopenharmony_ci int ret; 199362306a36Sopenharmony_ci int i; 199462306a36Sopenharmony_ci 199562306a36Sopenharmony_ci buf = kmalloc(4, GFP_KERNEL); 199662306a36Sopenharmony_ci if (!buf) 199762306a36Sopenharmony_ci return -ENOMEM; 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_ci ret = ftdi_read_eeprom(port->serial, buf, 0x1a, 4); 200062306a36Sopenharmony_ci if (ret < 0) 200162306a36Sopenharmony_ci goto out_free; 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci /* 200462306a36Sopenharmony_ci * FT232H CBUS Memory Map 200562306a36Sopenharmony_ci * 200662306a36Sopenharmony_ci * 0x1a: X- (upper nibble -> AC5) 200762306a36Sopenharmony_ci * 0x1b: -X (lower nibble -> AC6) 200862306a36Sopenharmony_ci * 0x1c: XX (upper nibble -> AC9 | lower nibble -> AC8) 200962306a36Sopenharmony_ci */ 201062306a36Sopenharmony_ci cbus_config = buf[2] << 8 | (buf[1] & 0xf) << 4 | (buf[0] & 0xf0) >> 4; 201162306a36Sopenharmony_ci 201262306a36Sopenharmony_ci priv->gc.ngpio = 4; 201362306a36Sopenharmony_ci priv->gpio_altfunc = 0xff; 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci for (i = 0; i < priv->gc.ngpio; ++i) { 201662306a36Sopenharmony_ci if ((cbus_config & 0xf) == FTDI_FTX_CBUS_MUX_GPIO) 201762306a36Sopenharmony_ci priv->gpio_altfunc &= ~BIT(i); 201862306a36Sopenharmony_ci cbus_config >>= 4; 201962306a36Sopenharmony_ci } 202062306a36Sopenharmony_ci 202162306a36Sopenharmony_ciout_free: 202262306a36Sopenharmony_ci kfree(buf); 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci return ret; 202562306a36Sopenharmony_ci} 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_cistatic int ftdi_gpio_init_ft232r(struct usb_serial_port *port) 202862306a36Sopenharmony_ci{ 202962306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 203062306a36Sopenharmony_ci u16 cbus_config; 203162306a36Sopenharmony_ci u8 *buf; 203262306a36Sopenharmony_ci int ret; 203362306a36Sopenharmony_ci int i; 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci buf = kmalloc(2, GFP_KERNEL); 203662306a36Sopenharmony_ci if (!buf) 203762306a36Sopenharmony_ci return -ENOMEM; 203862306a36Sopenharmony_ci 203962306a36Sopenharmony_ci ret = ftdi_read_eeprom(port->serial, buf, 0x14, 2); 204062306a36Sopenharmony_ci if (ret < 0) 204162306a36Sopenharmony_ci goto out_free; 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci cbus_config = le16_to_cpup((__le16 *)buf); 204462306a36Sopenharmony_ci dev_dbg(&port->dev, "cbus_config = 0x%04x\n", cbus_config); 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci priv->gc.ngpio = 4; 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_ci priv->gpio_altfunc = 0xff; 204962306a36Sopenharmony_ci for (i = 0; i < priv->gc.ngpio; ++i) { 205062306a36Sopenharmony_ci if ((cbus_config & 0xf) == FTDI_FT232R_CBUS_MUX_GPIO) 205162306a36Sopenharmony_ci priv->gpio_altfunc &= ~BIT(i); 205262306a36Sopenharmony_ci cbus_config >>= 4; 205362306a36Sopenharmony_ci } 205462306a36Sopenharmony_ciout_free: 205562306a36Sopenharmony_ci kfree(buf); 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci return ret; 205862306a36Sopenharmony_ci} 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_cistatic int ftdi_gpio_init_ftx(struct usb_serial_port *port) 206162306a36Sopenharmony_ci{ 206262306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 206362306a36Sopenharmony_ci struct usb_serial *serial = port->serial; 206462306a36Sopenharmony_ci const u16 cbus_cfg_addr = 0x1a; 206562306a36Sopenharmony_ci const u16 cbus_cfg_size = 4; 206662306a36Sopenharmony_ci u8 *cbus_cfg_buf; 206762306a36Sopenharmony_ci int result; 206862306a36Sopenharmony_ci u8 i; 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci cbus_cfg_buf = kmalloc(cbus_cfg_size, GFP_KERNEL); 207162306a36Sopenharmony_ci if (!cbus_cfg_buf) 207262306a36Sopenharmony_ci return -ENOMEM; 207362306a36Sopenharmony_ci 207462306a36Sopenharmony_ci result = ftdi_read_eeprom(serial, cbus_cfg_buf, 207562306a36Sopenharmony_ci cbus_cfg_addr, cbus_cfg_size); 207662306a36Sopenharmony_ci if (result < 0) 207762306a36Sopenharmony_ci goto out_free; 207862306a36Sopenharmony_ci 207962306a36Sopenharmony_ci /* FIXME: FT234XD alone has 1 GPIO, but how to recognize this IC? */ 208062306a36Sopenharmony_ci priv->gc.ngpio = 4; 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_ci /* Determine which pins are configured for CBUS bitbanging */ 208362306a36Sopenharmony_ci priv->gpio_altfunc = 0xff; 208462306a36Sopenharmony_ci for (i = 0; i < priv->gc.ngpio; ++i) { 208562306a36Sopenharmony_ci if (cbus_cfg_buf[i] == FTDI_FTX_CBUS_MUX_GPIO) 208662306a36Sopenharmony_ci priv->gpio_altfunc &= ~BIT(i); 208762306a36Sopenharmony_ci } 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ciout_free: 209062306a36Sopenharmony_ci kfree(cbus_cfg_buf); 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci return result; 209362306a36Sopenharmony_ci} 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_cistatic int ftdi_gpio_init(struct usb_serial_port *port) 209662306a36Sopenharmony_ci{ 209762306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 209862306a36Sopenharmony_ci struct usb_serial *serial = port->serial; 209962306a36Sopenharmony_ci int result; 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci switch (priv->chip_type) { 210262306a36Sopenharmony_ci case FT232H: 210362306a36Sopenharmony_ci result = ftdi_gpio_init_ft232h(port); 210462306a36Sopenharmony_ci break; 210562306a36Sopenharmony_ci case FT232R: 210662306a36Sopenharmony_ci result = ftdi_gpio_init_ft232r(port); 210762306a36Sopenharmony_ci break; 210862306a36Sopenharmony_ci case FTX: 210962306a36Sopenharmony_ci result = ftdi_gpio_init_ftx(port); 211062306a36Sopenharmony_ci break; 211162306a36Sopenharmony_ci default: 211262306a36Sopenharmony_ci return 0; 211362306a36Sopenharmony_ci } 211462306a36Sopenharmony_ci 211562306a36Sopenharmony_ci if (result < 0) 211662306a36Sopenharmony_ci return result; 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_ci mutex_init(&priv->gpio_lock); 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_ci priv->gc.label = "ftdi-cbus"; 212162306a36Sopenharmony_ci priv->gc.request = ftdi_gpio_request; 212262306a36Sopenharmony_ci priv->gc.get_direction = ftdi_gpio_direction_get; 212362306a36Sopenharmony_ci priv->gc.direction_input = ftdi_gpio_direction_input; 212462306a36Sopenharmony_ci priv->gc.direction_output = ftdi_gpio_direction_output; 212562306a36Sopenharmony_ci priv->gc.init_valid_mask = ftdi_gpio_init_valid_mask; 212662306a36Sopenharmony_ci priv->gc.get = ftdi_gpio_get; 212762306a36Sopenharmony_ci priv->gc.set = ftdi_gpio_set; 212862306a36Sopenharmony_ci priv->gc.get_multiple = ftdi_gpio_get_multiple; 212962306a36Sopenharmony_ci priv->gc.set_multiple = ftdi_gpio_set_multiple; 213062306a36Sopenharmony_ci priv->gc.owner = THIS_MODULE; 213162306a36Sopenharmony_ci priv->gc.parent = &serial->interface->dev; 213262306a36Sopenharmony_ci priv->gc.base = -1; 213362306a36Sopenharmony_ci priv->gc.can_sleep = true; 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_ci result = gpiochip_add_data(&priv->gc, port); 213662306a36Sopenharmony_ci if (!result) 213762306a36Sopenharmony_ci priv->gpio_registered = true; 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_ci return result; 214062306a36Sopenharmony_ci} 214162306a36Sopenharmony_ci 214262306a36Sopenharmony_cistatic void ftdi_gpio_remove(struct usb_serial_port *port) 214362306a36Sopenharmony_ci{ 214462306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 214562306a36Sopenharmony_ci 214662306a36Sopenharmony_ci if (priv->gpio_registered) { 214762306a36Sopenharmony_ci gpiochip_remove(&priv->gc); 214862306a36Sopenharmony_ci priv->gpio_registered = false; 214962306a36Sopenharmony_ci } 215062306a36Sopenharmony_ci 215162306a36Sopenharmony_ci if (priv->gpio_used) { 215262306a36Sopenharmony_ci /* Exiting CBUS-mode does not reset pin states. */ 215362306a36Sopenharmony_ci ftdi_exit_cbus_mode(port); 215462306a36Sopenharmony_ci priv->gpio_used = false; 215562306a36Sopenharmony_ci } 215662306a36Sopenharmony_ci} 215762306a36Sopenharmony_ci 215862306a36Sopenharmony_ci#else 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_cistatic int ftdi_gpio_init(struct usb_serial_port *port) 216162306a36Sopenharmony_ci{ 216262306a36Sopenharmony_ci return 0; 216362306a36Sopenharmony_ci} 216462306a36Sopenharmony_ci 216562306a36Sopenharmony_cistatic void ftdi_gpio_remove(struct usb_serial_port *port) { } 216662306a36Sopenharmony_ci 216762306a36Sopenharmony_ci#endif /* CONFIG_GPIOLIB */ 216862306a36Sopenharmony_ci 216962306a36Sopenharmony_ci/* 217062306a36Sopenharmony_ci * *************************************************************************** 217162306a36Sopenharmony_ci * FTDI driver specific functions 217262306a36Sopenharmony_ci * *************************************************************************** 217362306a36Sopenharmony_ci */ 217462306a36Sopenharmony_ci 217562306a36Sopenharmony_cistatic int ftdi_probe(struct usb_serial *serial, const struct usb_device_id *id) 217662306a36Sopenharmony_ci{ 217762306a36Sopenharmony_ci const struct ftdi_quirk *quirk = (struct ftdi_quirk *)id->driver_info; 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_ci if (quirk && quirk->probe) { 218062306a36Sopenharmony_ci int ret = quirk->probe(serial); 218162306a36Sopenharmony_ci if (ret != 0) 218262306a36Sopenharmony_ci return ret; 218362306a36Sopenharmony_ci } 218462306a36Sopenharmony_ci 218562306a36Sopenharmony_ci usb_set_serial_data(serial, (void *)id->driver_info); 218662306a36Sopenharmony_ci 218762306a36Sopenharmony_ci return 0; 218862306a36Sopenharmony_ci} 218962306a36Sopenharmony_ci 219062306a36Sopenharmony_cistatic int ftdi_port_probe(struct usb_serial_port *port) 219162306a36Sopenharmony_ci{ 219262306a36Sopenharmony_ci const struct ftdi_quirk *quirk = usb_get_serial_data(port->serial); 219362306a36Sopenharmony_ci struct ftdi_private *priv; 219462306a36Sopenharmony_ci int result; 219562306a36Sopenharmony_ci 219662306a36Sopenharmony_ci priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); 219762306a36Sopenharmony_ci if (!priv) 219862306a36Sopenharmony_ci return -ENOMEM; 219962306a36Sopenharmony_ci 220062306a36Sopenharmony_ci mutex_init(&priv->cfg_lock); 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ci if (quirk && quirk->port_probe) 220362306a36Sopenharmony_ci quirk->port_probe(priv); 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci usb_set_serial_port_data(port, priv); 220662306a36Sopenharmony_ci 220762306a36Sopenharmony_ci result = ftdi_determine_type(port); 220862306a36Sopenharmony_ci if (result) 220962306a36Sopenharmony_ci goto err_free; 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci ftdi_set_max_packet_size(port); 221262306a36Sopenharmony_ci if (read_latency_timer(port) < 0) 221362306a36Sopenharmony_ci priv->latency = 16; 221462306a36Sopenharmony_ci write_latency_timer(port); 221562306a36Sopenharmony_ci 221662306a36Sopenharmony_ci result = ftdi_gpio_init(port); 221762306a36Sopenharmony_ci if (result < 0) { 221862306a36Sopenharmony_ci dev_err(&port->serial->interface->dev, 221962306a36Sopenharmony_ci "GPIO initialisation failed: %d\n", 222062306a36Sopenharmony_ci result); 222162306a36Sopenharmony_ci } 222262306a36Sopenharmony_ci 222362306a36Sopenharmony_ci return 0; 222462306a36Sopenharmony_ci 222562306a36Sopenharmony_cierr_free: 222662306a36Sopenharmony_ci kfree(priv); 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_ci return result; 222962306a36Sopenharmony_ci} 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_ci/* Setup for the USB-UIRT device, which requires hardwired 223262306a36Sopenharmony_ci * baudrate (38400 gets mapped to 312500) */ 223362306a36Sopenharmony_ci/* Called from usbserial:serial_probe */ 223462306a36Sopenharmony_cistatic void ftdi_USB_UIRT_setup(struct ftdi_private *priv) 223562306a36Sopenharmony_ci{ 223662306a36Sopenharmony_ci priv->flags |= ASYNC_SPD_CUST; 223762306a36Sopenharmony_ci priv->custom_divisor = 77; 223862306a36Sopenharmony_ci priv->force_baud = 38400; 223962306a36Sopenharmony_ci} 224062306a36Sopenharmony_ci 224162306a36Sopenharmony_ci/* Setup for the HE-TIRA1 device, which requires hardwired 224262306a36Sopenharmony_ci * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ 224362306a36Sopenharmony_ci 224462306a36Sopenharmony_cistatic void ftdi_HE_TIRA1_setup(struct ftdi_private *priv) 224562306a36Sopenharmony_ci{ 224662306a36Sopenharmony_ci priv->flags |= ASYNC_SPD_CUST; 224762306a36Sopenharmony_ci priv->custom_divisor = 240; 224862306a36Sopenharmony_ci priv->force_baud = 38400; 224962306a36Sopenharmony_ci priv->force_rtscts = 1; 225062306a36Sopenharmony_ci} 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_ci/* 225362306a36Sopenharmony_ci * Module parameter to control latency timer for NDI FTDI-based USB devices. 225462306a36Sopenharmony_ci * If this value is not set in /etc/modprobe.d/ its value will be set 225562306a36Sopenharmony_ci * to 1ms. 225662306a36Sopenharmony_ci */ 225762306a36Sopenharmony_cistatic int ndi_latency_timer = 1; 225862306a36Sopenharmony_ci 225962306a36Sopenharmony_ci/* Setup for the NDI FTDI-based USB devices, which requires hardwired 226062306a36Sopenharmony_ci * baudrate (19200 gets mapped to 1200000). 226162306a36Sopenharmony_ci * 226262306a36Sopenharmony_ci * Called from usbserial:serial_probe. 226362306a36Sopenharmony_ci */ 226462306a36Sopenharmony_cistatic int ftdi_NDI_device_setup(struct usb_serial *serial) 226562306a36Sopenharmony_ci{ 226662306a36Sopenharmony_ci struct usb_device *udev = serial->dev; 226762306a36Sopenharmony_ci int latency = ndi_latency_timer; 226862306a36Sopenharmony_ci 226962306a36Sopenharmony_ci if (latency == 0) 227062306a36Sopenharmony_ci latency = 1; 227162306a36Sopenharmony_ci if (latency > 99) 227262306a36Sopenharmony_ci latency = 99; 227362306a36Sopenharmony_ci 227462306a36Sopenharmony_ci dev_dbg(&udev->dev, "%s setting NDI device latency to %d\n", __func__, latency); 227562306a36Sopenharmony_ci dev_info(&udev->dev, "NDI device with a latency value of %d\n", latency); 227662306a36Sopenharmony_ci 227762306a36Sopenharmony_ci /* FIXME: errors are not returned */ 227862306a36Sopenharmony_ci usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 227962306a36Sopenharmony_ci FTDI_SIO_SET_LATENCY_TIMER_REQUEST, 228062306a36Sopenharmony_ci FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, 228162306a36Sopenharmony_ci latency, 0, NULL, 0, WDR_TIMEOUT); 228262306a36Sopenharmony_ci return 0; 228362306a36Sopenharmony_ci} 228462306a36Sopenharmony_ci 228562306a36Sopenharmony_ci/* 228662306a36Sopenharmony_ci * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko 228762306a36Sopenharmony_ci * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from 228862306a36Sopenharmony_ci * userspace using openocd. 228962306a36Sopenharmony_ci */ 229062306a36Sopenharmony_cistatic int ftdi_jtag_probe(struct usb_serial *serial) 229162306a36Sopenharmony_ci{ 229262306a36Sopenharmony_ci struct usb_interface *intf = serial->interface; 229362306a36Sopenharmony_ci int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; 229462306a36Sopenharmony_ci 229562306a36Sopenharmony_ci if (ifnum == 0) { 229662306a36Sopenharmony_ci dev_info(&intf->dev, "Ignoring interface reserved for JTAG\n"); 229762306a36Sopenharmony_ci return -ENODEV; 229862306a36Sopenharmony_ci } 229962306a36Sopenharmony_ci 230062306a36Sopenharmony_ci return 0; 230162306a36Sopenharmony_ci} 230262306a36Sopenharmony_ci 230362306a36Sopenharmony_cistatic int ftdi_8u2232c_probe(struct usb_serial *serial) 230462306a36Sopenharmony_ci{ 230562306a36Sopenharmony_ci struct usb_device *udev = serial->dev; 230662306a36Sopenharmony_ci 230762306a36Sopenharmony_ci if (udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) 230862306a36Sopenharmony_ci return ftdi_jtag_probe(serial); 230962306a36Sopenharmony_ci 231062306a36Sopenharmony_ci if (udev->product && 231162306a36Sopenharmony_ci (!strcmp(udev->product, "Arrow USB Blaster") || 231262306a36Sopenharmony_ci !strcmp(udev->product, "BeagleBone/XDS100V2") || 231362306a36Sopenharmony_ci !strcmp(udev->product, "SNAP Connect E10"))) 231462306a36Sopenharmony_ci return ftdi_jtag_probe(serial); 231562306a36Sopenharmony_ci 231662306a36Sopenharmony_ci return 0; 231762306a36Sopenharmony_ci} 231862306a36Sopenharmony_ci 231962306a36Sopenharmony_ci/* 232062306a36Sopenharmony_ci * First two ports on JTAG adaptors using an FT4232 such as STMicroelectronics's 232162306a36Sopenharmony_ci * ST Micro Connect Lite are reserved for JTAG or other non-UART interfaces and 232262306a36Sopenharmony_ci * can be accessed from userspace. 232362306a36Sopenharmony_ci * The next two ports are enabled as UARTs by default, where port 2 is 232462306a36Sopenharmony_ci * a conventional RS-232 UART. 232562306a36Sopenharmony_ci */ 232662306a36Sopenharmony_cistatic int ftdi_stmclite_probe(struct usb_serial *serial) 232762306a36Sopenharmony_ci{ 232862306a36Sopenharmony_ci struct usb_interface *intf = serial->interface; 232962306a36Sopenharmony_ci int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; 233062306a36Sopenharmony_ci 233162306a36Sopenharmony_ci if (ifnum < 2) { 233262306a36Sopenharmony_ci dev_info(&intf->dev, "Ignoring interface reserved for JTAG\n"); 233362306a36Sopenharmony_ci return -ENODEV; 233462306a36Sopenharmony_ci } 233562306a36Sopenharmony_ci 233662306a36Sopenharmony_ci return 0; 233762306a36Sopenharmony_ci} 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_cistatic void ftdi_port_remove(struct usb_serial_port *port) 234062306a36Sopenharmony_ci{ 234162306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 234262306a36Sopenharmony_ci 234362306a36Sopenharmony_ci ftdi_gpio_remove(port); 234462306a36Sopenharmony_ci 234562306a36Sopenharmony_ci kfree(priv); 234662306a36Sopenharmony_ci} 234762306a36Sopenharmony_ci 234862306a36Sopenharmony_cistatic int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) 234962306a36Sopenharmony_ci{ 235062306a36Sopenharmony_ci struct usb_device *dev = port->serial->dev; 235162306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 235262306a36Sopenharmony_ci 235362306a36Sopenharmony_ci /* No error checking for this (will get errors later anyway) */ 235462306a36Sopenharmony_ci /* See ftdi_sio.h for description of what is reset */ 235562306a36Sopenharmony_ci usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 235662306a36Sopenharmony_ci FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 235762306a36Sopenharmony_ci FTDI_SIO_RESET_SIO, 235862306a36Sopenharmony_ci priv->channel, NULL, 0, WDR_TIMEOUT); 235962306a36Sopenharmony_ci 236062306a36Sopenharmony_ci /* Termios defaults are set by usb_serial_init. We don't change 236162306a36Sopenharmony_ci port->tty->termios - this would lose speed settings, etc. 236262306a36Sopenharmony_ci This is same behaviour as serial.c/rs_open() - Kuba */ 236362306a36Sopenharmony_ci 236462306a36Sopenharmony_ci /* ftdi_set_termios will send usb control messages */ 236562306a36Sopenharmony_ci if (tty) 236662306a36Sopenharmony_ci ftdi_set_termios(tty, port, NULL); 236762306a36Sopenharmony_ci 236862306a36Sopenharmony_ci return usb_serial_generic_open(tty, port); 236962306a36Sopenharmony_ci} 237062306a36Sopenharmony_ci 237162306a36Sopenharmony_cistatic void ftdi_dtr_rts(struct usb_serial_port *port, int on) 237262306a36Sopenharmony_ci{ 237362306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 237462306a36Sopenharmony_ci 237562306a36Sopenharmony_ci /* Disable flow control */ 237662306a36Sopenharmony_ci if (!on) { 237762306a36Sopenharmony_ci if (usb_control_msg(port->serial->dev, 237862306a36Sopenharmony_ci usb_sndctrlpipe(port->serial->dev, 0), 237962306a36Sopenharmony_ci FTDI_SIO_SET_FLOW_CTRL_REQUEST, 238062306a36Sopenharmony_ci FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 238162306a36Sopenharmony_ci 0, priv->channel, NULL, 0, 238262306a36Sopenharmony_ci WDR_TIMEOUT) < 0) { 238362306a36Sopenharmony_ci dev_err(&port->dev, "error from flowcontrol urb\n"); 238462306a36Sopenharmony_ci } 238562306a36Sopenharmony_ci } 238662306a36Sopenharmony_ci /* drop RTS and DTR */ 238762306a36Sopenharmony_ci if (on) 238862306a36Sopenharmony_ci set_mctrl(port, TIOCM_DTR | TIOCM_RTS); 238962306a36Sopenharmony_ci else 239062306a36Sopenharmony_ci clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); 239162306a36Sopenharmony_ci} 239262306a36Sopenharmony_ci 239362306a36Sopenharmony_ci/* The SIO requires the first byte to have: 239462306a36Sopenharmony_ci * B0 1 239562306a36Sopenharmony_ci * B1 0 239662306a36Sopenharmony_ci * B2..7 length of message excluding byte 0 239762306a36Sopenharmony_ci * 239862306a36Sopenharmony_ci * The new devices do not require this byte 239962306a36Sopenharmony_ci */ 240062306a36Sopenharmony_cistatic int ftdi_prepare_write_buffer(struct usb_serial_port *port, 240162306a36Sopenharmony_ci void *dest, size_t size) 240262306a36Sopenharmony_ci{ 240362306a36Sopenharmony_ci struct ftdi_private *priv; 240462306a36Sopenharmony_ci int count; 240562306a36Sopenharmony_ci unsigned long flags; 240662306a36Sopenharmony_ci 240762306a36Sopenharmony_ci priv = usb_get_serial_port_data(port); 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci if (priv->chip_type == SIO) { 241062306a36Sopenharmony_ci unsigned char *buffer = dest; 241162306a36Sopenharmony_ci int i, len, c; 241262306a36Sopenharmony_ci 241362306a36Sopenharmony_ci count = 0; 241462306a36Sopenharmony_ci spin_lock_irqsave(&port->lock, flags); 241562306a36Sopenharmony_ci for (i = 0; i < size - 1; i += priv->max_packet_size) { 241662306a36Sopenharmony_ci len = min_t(int, size - i, priv->max_packet_size) - 1; 241762306a36Sopenharmony_ci c = kfifo_out(&port->write_fifo, &buffer[i + 1], len); 241862306a36Sopenharmony_ci if (!c) 241962306a36Sopenharmony_ci break; 242062306a36Sopenharmony_ci port->icount.tx += c; 242162306a36Sopenharmony_ci buffer[i] = (c << 2) + 1; 242262306a36Sopenharmony_ci count += c + 1; 242362306a36Sopenharmony_ci } 242462306a36Sopenharmony_ci spin_unlock_irqrestore(&port->lock, flags); 242562306a36Sopenharmony_ci } else { 242662306a36Sopenharmony_ci count = kfifo_out_locked(&port->write_fifo, dest, size, 242762306a36Sopenharmony_ci &port->lock); 242862306a36Sopenharmony_ci port->icount.tx += count; 242962306a36Sopenharmony_ci } 243062306a36Sopenharmony_ci 243162306a36Sopenharmony_ci return count; 243262306a36Sopenharmony_ci} 243362306a36Sopenharmony_ci 243462306a36Sopenharmony_ci#define FTDI_RS_ERR_MASK (FTDI_RS_BI | FTDI_RS_PE | FTDI_RS_FE | FTDI_RS_OE) 243562306a36Sopenharmony_ci 243662306a36Sopenharmony_cistatic int ftdi_process_packet(struct usb_serial_port *port, 243762306a36Sopenharmony_ci struct ftdi_private *priv, unsigned char *buf, int len) 243862306a36Sopenharmony_ci{ 243962306a36Sopenharmony_ci unsigned char status; 244062306a36Sopenharmony_ci bool brkint = false; 244162306a36Sopenharmony_ci int i; 244262306a36Sopenharmony_ci char flag; 244362306a36Sopenharmony_ci 244462306a36Sopenharmony_ci if (len < 2) { 244562306a36Sopenharmony_ci dev_dbg(&port->dev, "malformed packet\n"); 244662306a36Sopenharmony_ci return 0; 244762306a36Sopenharmony_ci } 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci /* Compare new line status to the old one, signal if different/ 245062306a36Sopenharmony_ci N.B. packet may be processed more than once, but differences 245162306a36Sopenharmony_ci are only processed once. */ 245262306a36Sopenharmony_ci status = buf[0] & FTDI_STATUS_B0_MASK; 245362306a36Sopenharmony_ci if (status != priv->prev_status) { 245462306a36Sopenharmony_ci char diff_status = status ^ priv->prev_status; 245562306a36Sopenharmony_ci 245662306a36Sopenharmony_ci if (diff_status & FTDI_RS0_CTS) 245762306a36Sopenharmony_ci port->icount.cts++; 245862306a36Sopenharmony_ci if (diff_status & FTDI_RS0_DSR) 245962306a36Sopenharmony_ci port->icount.dsr++; 246062306a36Sopenharmony_ci if (diff_status & FTDI_RS0_RI) 246162306a36Sopenharmony_ci port->icount.rng++; 246262306a36Sopenharmony_ci if (diff_status & FTDI_RS0_RLSD) { 246362306a36Sopenharmony_ci struct tty_struct *tty; 246462306a36Sopenharmony_ci 246562306a36Sopenharmony_ci port->icount.dcd++; 246662306a36Sopenharmony_ci tty = tty_port_tty_get(&port->port); 246762306a36Sopenharmony_ci if (tty) 246862306a36Sopenharmony_ci usb_serial_handle_dcd_change(port, tty, 246962306a36Sopenharmony_ci status & FTDI_RS0_RLSD); 247062306a36Sopenharmony_ci tty_kref_put(tty); 247162306a36Sopenharmony_ci } 247262306a36Sopenharmony_ci 247362306a36Sopenharmony_ci wake_up_interruptible(&port->port.delta_msr_wait); 247462306a36Sopenharmony_ci priv->prev_status = status; 247562306a36Sopenharmony_ci } 247662306a36Sopenharmony_ci 247762306a36Sopenharmony_ci /* save if the transmitter is empty or not */ 247862306a36Sopenharmony_ci if (buf[1] & FTDI_RS_TEMT) 247962306a36Sopenharmony_ci priv->transmit_empty = 1; 248062306a36Sopenharmony_ci else 248162306a36Sopenharmony_ci priv->transmit_empty = 0; 248262306a36Sopenharmony_ci 248362306a36Sopenharmony_ci if (len == 2) 248462306a36Sopenharmony_ci return 0; /* status only */ 248562306a36Sopenharmony_ci 248662306a36Sopenharmony_ci /* 248762306a36Sopenharmony_ci * Break and error status must only be processed for packets with 248862306a36Sopenharmony_ci * data payload to avoid over-reporting. 248962306a36Sopenharmony_ci */ 249062306a36Sopenharmony_ci flag = TTY_NORMAL; 249162306a36Sopenharmony_ci if (buf[1] & FTDI_RS_ERR_MASK) { 249262306a36Sopenharmony_ci /* 249362306a36Sopenharmony_ci * Break takes precedence over parity, which takes precedence 249462306a36Sopenharmony_ci * over framing errors. Note that break is only associated 249562306a36Sopenharmony_ci * with the last character in the buffer and only when it's a 249662306a36Sopenharmony_ci * NUL. 249762306a36Sopenharmony_ci */ 249862306a36Sopenharmony_ci if (buf[1] & FTDI_RS_BI && buf[len - 1] == '\0') { 249962306a36Sopenharmony_ci port->icount.brk++; 250062306a36Sopenharmony_ci brkint = true; 250162306a36Sopenharmony_ci } 250262306a36Sopenharmony_ci if (buf[1] & FTDI_RS_PE) { 250362306a36Sopenharmony_ci flag = TTY_PARITY; 250462306a36Sopenharmony_ci port->icount.parity++; 250562306a36Sopenharmony_ci } else if (buf[1] & FTDI_RS_FE) { 250662306a36Sopenharmony_ci flag = TTY_FRAME; 250762306a36Sopenharmony_ci port->icount.frame++; 250862306a36Sopenharmony_ci } 250962306a36Sopenharmony_ci /* Overrun is special, not associated with a char */ 251062306a36Sopenharmony_ci if (buf[1] & FTDI_RS_OE) { 251162306a36Sopenharmony_ci port->icount.overrun++; 251262306a36Sopenharmony_ci tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); 251362306a36Sopenharmony_ci } 251462306a36Sopenharmony_ci } 251562306a36Sopenharmony_ci 251662306a36Sopenharmony_ci port->icount.rx += len - 2; 251762306a36Sopenharmony_ci 251862306a36Sopenharmony_ci if (brkint || port->sysrq) { 251962306a36Sopenharmony_ci for (i = 2; i < len; i++) { 252062306a36Sopenharmony_ci if (brkint && i == len - 1) { 252162306a36Sopenharmony_ci if (usb_serial_handle_break(port)) 252262306a36Sopenharmony_ci return len - 3; 252362306a36Sopenharmony_ci flag = TTY_BREAK; 252462306a36Sopenharmony_ci } 252562306a36Sopenharmony_ci if (usb_serial_handle_sysrq_char(port, buf[i])) 252662306a36Sopenharmony_ci continue; 252762306a36Sopenharmony_ci tty_insert_flip_char(&port->port, buf[i], flag); 252862306a36Sopenharmony_ci } 252962306a36Sopenharmony_ci } else { 253062306a36Sopenharmony_ci tty_insert_flip_string_fixed_flag(&port->port, buf + 2, flag, 253162306a36Sopenharmony_ci len - 2); 253262306a36Sopenharmony_ci } 253362306a36Sopenharmony_ci 253462306a36Sopenharmony_ci return len - 2; 253562306a36Sopenharmony_ci} 253662306a36Sopenharmony_ci 253762306a36Sopenharmony_cistatic void ftdi_process_read_urb(struct urb *urb) 253862306a36Sopenharmony_ci{ 253962306a36Sopenharmony_ci struct usb_serial_port *port = urb->context; 254062306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 254162306a36Sopenharmony_ci char *data = urb->transfer_buffer; 254262306a36Sopenharmony_ci int i; 254362306a36Sopenharmony_ci int len; 254462306a36Sopenharmony_ci int count = 0; 254562306a36Sopenharmony_ci 254662306a36Sopenharmony_ci for (i = 0; i < urb->actual_length; i += priv->max_packet_size) { 254762306a36Sopenharmony_ci len = min_t(int, urb->actual_length - i, priv->max_packet_size); 254862306a36Sopenharmony_ci count += ftdi_process_packet(port, priv, &data[i], len); 254962306a36Sopenharmony_ci } 255062306a36Sopenharmony_ci 255162306a36Sopenharmony_ci if (count) 255262306a36Sopenharmony_ci tty_flip_buffer_push(&port->port); 255362306a36Sopenharmony_ci} 255462306a36Sopenharmony_ci 255562306a36Sopenharmony_cistatic int ftdi_break_ctl(struct tty_struct *tty, int break_state) 255662306a36Sopenharmony_ci{ 255762306a36Sopenharmony_ci struct usb_serial_port *port = tty->driver_data; 255862306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 255962306a36Sopenharmony_ci u16 value; 256062306a36Sopenharmony_ci int ret; 256162306a36Sopenharmony_ci 256262306a36Sopenharmony_ci /* break_state = -1 to turn on break, and 0 to turn off break */ 256362306a36Sopenharmony_ci /* see drivers/char/tty_io.c to see it used */ 256462306a36Sopenharmony_ci /* last_set_data_value NEVER has the break bit set in it */ 256562306a36Sopenharmony_ci 256662306a36Sopenharmony_ci if (break_state) 256762306a36Sopenharmony_ci value = priv->last_set_data_value | FTDI_SIO_SET_BREAK; 256862306a36Sopenharmony_ci else 256962306a36Sopenharmony_ci value = priv->last_set_data_value; 257062306a36Sopenharmony_ci 257162306a36Sopenharmony_ci ret = usb_control_msg(port->serial->dev, 257262306a36Sopenharmony_ci usb_sndctrlpipe(port->serial->dev, 0), 257362306a36Sopenharmony_ci FTDI_SIO_SET_DATA_REQUEST, 257462306a36Sopenharmony_ci FTDI_SIO_SET_DATA_REQUEST_TYPE, 257562306a36Sopenharmony_ci value, priv->channel, 257662306a36Sopenharmony_ci NULL, 0, WDR_TIMEOUT); 257762306a36Sopenharmony_ci if (ret < 0) { 257862306a36Sopenharmony_ci dev_err(&port->dev, "%s FAILED to enable/disable break state (state was %d)\n", 257962306a36Sopenharmony_ci __func__, break_state); 258062306a36Sopenharmony_ci return ret; 258162306a36Sopenharmony_ci } 258262306a36Sopenharmony_ci 258362306a36Sopenharmony_ci dev_dbg(&port->dev, "%s break state is %d - urb is %d\n", __func__, 258462306a36Sopenharmony_ci break_state, value); 258562306a36Sopenharmony_ci 258662306a36Sopenharmony_ci return 0; 258762306a36Sopenharmony_ci} 258862306a36Sopenharmony_ci 258962306a36Sopenharmony_cistatic bool ftdi_tx_empty(struct usb_serial_port *port) 259062306a36Sopenharmony_ci{ 259162306a36Sopenharmony_ci unsigned char buf[2]; 259262306a36Sopenharmony_ci int ret; 259362306a36Sopenharmony_ci 259462306a36Sopenharmony_ci ret = ftdi_get_modem_status(port, buf); 259562306a36Sopenharmony_ci if (ret == 2) { 259662306a36Sopenharmony_ci if (!(buf[1] & FTDI_RS_TEMT)) 259762306a36Sopenharmony_ci return false; 259862306a36Sopenharmony_ci } 259962306a36Sopenharmony_ci 260062306a36Sopenharmony_ci return true; 260162306a36Sopenharmony_ci} 260262306a36Sopenharmony_ci 260362306a36Sopenharmony_ci/* old_termios contains the original termios settings and tty->termios contains 260462306a36Sopenharmony_ci * the new setting to be used 260562306a36Sopenharmony_ci * WARNING: set_termios calls this with old_termios in kernel space 260662306a36Sopenharmony_ci */ 260762306a36Sopenharmony_cistatic void ftdi_set_termios(struct tty_struct *tty, 260862306a36Sopenharmony_ci struct usb_serial_port *port, 260962306a36Sopenharmony_ci const struct ktermios *old_termios) 261062306a36Sopenharmony_ci{ 261162306a36Sopenharmony_ci struct usb_device *dev = port->serial->dev; 261262306a36Sopenharmony_ci struct device *ddev = &port->dev; 261362306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 261462306a36Sopenharmony_ci struct ktermios *termios = &tty->termios; 261562306a36Sopenharmony_ci unsigned int cflag = termios->c_cflag; 261662306a36Sopenharmony_ci u16 value, index; 261762306a36Sopenharmony_ci int ret; 261862306a36Sopenharmony_ci 261962306a36Sopenharmony_ci /* Force baud rate if this device requires it, unless it is set to 262062306a36Sopenharmony_ci B0. */ 262162306a36Sopenharmony_ci if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) { 262262306a36Sopenharmony_ci dev_dbg(ddev, "%s: forcing baud rate for this device\n", __func__); 262362306a36Sopenharmony_ci tty_encode_baud_rate(tty, priv->force_baud, 262462306a36Sopenharmony_ci priv->force_baud); 262562306a36Sopenharmony_ci } 262662306a36Sopenharmony_ci 262762306a36Sopenharmony_ci /* Force RTS-CTS if this device requires it. */ 262862306a36Sopenharmony_ci if (priv->force_rtscts) { 262962306a36Sopenharmony_ci dev_dbg(ddev, "%s: forcing rtscts for this device\n", __func__); 263062306a36Sopenharmony_ci termios->c_cflag |= CRTSCTS; 263162306a36Sopenharmony_ci } 263262306a36Sopenharmony_ci 263362306a36Sopenharmony_ci /* 263462306a36Sopenharmony_ci * All FTDI UART chips are limited to CS7/8. We shouldn't pretend to 263562306a36Sopenharmony_ci * support CS5/6 and revert the CSIZE setting instead. 263662306a36Sopenharmony_ci * 263762306a36Sopenharmony_ci * CS5 however is used to control some smartcard readers which abuse 263862306a36Sopenharmony_ci * this limitation to switch modes. Original FTDI chips fall back to 263962306a36Sopenharmony_ci * eight data bits. 264062306a36Sopenharmony_ci * 264162306a36Sopenharmony_ci * TODO: Implement a quirk to only allow this with mentioned 264262306a36Sopenharmony_ci * readers. One I know of (Argolis Smartreader V1) 264362306a36Sopenharmony_ci * returns "USB smartcard server" as iInterface string. 264462306a36Sopenharmony_ci * The vendor didn't bother with a custom VID/PID of 264562306a36Sopenharmony_ci * course. 264662306a36Sopenharmony_ci */ 264762306a36Sopenharmony_ci if (C_CSIZE(tty) == CS6) { 264862306a36Sopenharmony_ci dev_warn(ddev, "requested CSIZE setting not supported\n"); 264962306a36Sopenharmony_ci 265062306a36Sopenharmony_ci termios->c_cflag &= ~CSIZE; 265162306a36Sopenharmony_ci if (old_termios) 265262306a36Sopenharmony_ci termios->c_cflag |= old_termios->c_cflag & CSIZE; 265362306a36Sopenharmony_ci else 265462306a36Sopenharmony_ci termios->c_cflag |= CS8; 265562306a36Sopenharmony_ci } 265662306a36Sopenharmony_ci 265762306a36Sopenharmony_ci cflag = termios->c_cflag; 265862306a36Sopenharmony_ci 265962306a36Sopenharmony_ci if (!old_termios) 266062306a36Sopenharmony_ci goto no_skip; 266162306a36Sopenharmony_ci 266262306a36Sopenharmony_ci if (old_termios->c_cflag == termios->c_cflag 266362306a36Sopenharmony_ci && old_termios->c_ispeed == termios->c_ispeed 266462306a36Sopenharmony_ci && old_termios->c_ospeed == termios->c_ospeed) 266562306a36Sopenharmony_ci goto no_c_cflag_changes; 266662306a36Sopenharmony_ci 266762306a36Sopenharmony_ci /* NOTE These routines can get interrupted by 266862306a36Sopenharmony_ci ftdi_sio_read_bulk_callback - need to examine what this means - 266962306a36Sopenharmony_ci don't see any problems yet */ 267062306a36Sopenharmony_ci 267162306a36Sopenharmony_ci if ((old_termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB)) == 267262306a36Sopenharmony_ci (termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB))) 267362306a36Sopenharmony_ci goto no_data_parity_stop_changes; 267462306a36Sopenharmony_ci 267562306a36Sopenharmony_cino_skip: 267662306a36Sopenharmony_ci /* Set number of data bits, parity, stop bits */ 267762306a36Sopenharmony_ci 267862306a36Sopenharmony_ci value = 0; 267962306a36Sopenharmony_ci value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 : 268062306a36Sopenharmony_ci FTDI_SIO_SET_DATA_STOP_BITS_1); 268162306a36Sopenharmony_ci if (cflag & PARENB) { 268262306a36Sopenharmony_ci if (cflag & CMSPAR) 268362306a36Sopenharmony_ci value |= cflag & PARODD ? 268462306a36Sopenharmony_ci FTDI_SIO_SET_DATA_PARITY_MARK : 268562306a36Sopenharmony_ci FTDI_SIO_SET_DATA_PARITY_SPACE; 268662306a36Sopenharmony_ci else 268762306a36Sopenharmony_ci value |= cflag & PARODD ? 268862306a36Sopenharmony_ci FTDI_SIO_SET_DATA_PARITY_ODD : 268962306a36Sopenharmony_ci FTDI_SIO_SET_DATA_PARITY_EVEN; 269062306a36Sopenharmony_ci } else { 269162306a36Sopenharmony_ci value |= FTDI_SIO_SET_DATA_PARITY_NONE; 269262306a36Sopenharmony_ci } 269362306a36Sopenharmony_ci switch (cflag & CSIZE) { 269462306a36Sopenharmony_ci case CS5: 269562306a36Sopenharmony_ci dev_dbg(ddev, "Setting CS5 quirk\n"); 269662306a36Sopenharmony_ci break; 269762306a36Sopenharmony_ci case CS7: 269862306a36Sopenharmony_ci value |= 7; 269962306a36Sopenharmony_ci dev_dbg(ddev, "Setting CS7\n"); 270062306a36Sopenharmony_ci break; 270162306a36Sopenharmony_ci default: 270262306a36Sopenharmony_ci case CS8: 270362306a36Sopenharmony_ci value |= 8; 270462306a36Sopenharmony_ci dev_dbg(ddev, "Setting CS8\n"); 270562306a36Sopenharmony_ci break; 270662306a36Sopenharmony_ci } 270762306a36Sopenharmony_ci 270862306a36Sopenharmony_ci /* This is needed by the break command since it uses the same command 270962306a36Sopenharmony_ci - but is or'ed with this value */ 271062306a36Sopenharmony_ci priv->last_set_data_value = value; 271162306a36Sopenharmony_ci 271262306a36Sopenharmony_ci if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 271362306a36Sopenharmony_ci FTDI_SIO_SET_DATA_REQUEST, 271462306a36Sopenharmony_ci FTDI_SIO_SET_DATA_REQUEST_TYPE, 271562306a36Sopenharmony_ci value, priv->channel, 271662306a36Sopenharmony_ci NULL, 0, WDR_SHORT_TIMEOUT) < 0) { 271762306a36Sopenharmony_ci dev_err(ddev, "%s FAILED to set databits/stopbits/parity\n", 271862306a36Sopenharmony_ci __func__); 271962306a36Sopenharmony_ci } 272062306a36Sopenharmony_ci 272162306a36Sopenharmony_ci /* Now do the baudrate */ 272262306a36Sopenharmony_cino_data_parity_stop_changes: 272362306a36Sopenharmony_ci if ((cflag & CBAUD) == B0) { 272462306a36Sopenharmony_ci /* Disable flow control */ 272562306a36Sopenharmony_ci if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 272662306a36Sopenharmony_ci FTDI_SIO_SET_FLOW_CTRL_REQUEST, 272762306a36Sopenharmony_ci FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 272862306a36Sopenharmony_ci 0, priv->channel, 272962306a36Sopenharmony_ci NULL, 0, WDR_TIMEOUT) < 0) { 273062306a36Sopenharmony_ci dev_err(ddev, "%s error from disable flowcontrol urb\n", 273162306a36Sopenharmony_ci __func__); 273262306a36Sopenharmony_ci } 273362306a36Sopenharmony_ci /* Drop RTS and DTR */ 273462306a36Sopenharmony_ci clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); 273562306a36Sopenharmony_ci } else { 273662306a36Sopenharmony_ci /* set the baudrate determined before */ 273762306a36Sopenharmony_ci mutex_lock(&priv->cfg_lock); 273862306a36Sopenharmony_ci if (change_speed(tty, port)) 273962306a36Sopenharmony_ci dev_err(ddev, "%s urb failed to set baudrate\n", __func__); 274062306a36Sopenharmony_ci mutex_unlock(&priv->cfg_lock); 274162306a36Sopenharmony_ci /* Ensure RTS and DTR are raised when baudrate changed from 0 */ 274262306a36Sopenharmony_ci if (old_termios && (old_termios->c_cflag & CBAUD) == B0) 274362306a36Sopenharmony_ci set_mctrl(port, TIOCM_DTR | TIOCM_RTS); 274462306a36Sopenharmony_ci } 274562306a36Sopenharmony_ci 274662306a36Sopenharmony_cino_c_cflag_changes: 274762306a36Sopenharmony_ci /* Set hardware-assisted flow control */ 274862306a36Sopenharmony_ci value = 0; 274962306a36Sopenharmony_ci 275062306a36Sopenharmony_ci if (C_CRTSCTS(tty)) { 275162306a36Sopenharmony_ci dev_dbg(&port->dev, "enabling rts/cts flow control\n"); 275262306a36Sopenharmony_ci index = FTDI_SIO_RTS_CTS_HS; 275362306a36Sopenharmony_ci } else if (I_IXON(tty)) { 275462306a36Sopenharmony_ci dev_dbg(&port->dev, "enabling xon/xoff flow control\n"); 275562306a36Sopenharmony_ci index = FTDI_SIO_XON_XOFF_HS; 275662306a36Sopenharmony_ci value = STOP_CHAR(tty) << 8 | START_CHAR(tty); 275762306a36Sopenharmony_ci } else { 275862306a36Sopenharmony_ci dev_dbg(&port->dev, "disabling flow control\n"); 275962306a36Sopenharmony_ci index = FTDI_SIO_DISABLE_FLOW_CTRL; 276062306a36Sopenharmony_ci } 276162306a36Sopenharmony_ci 276262306a36Sopenharmony_ci index |= priv->channel; 276362306a36Sopenharmony_ci 276462306a36Sopenharmony_ci ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 276562306a36Sopenharmony_ci FTDI_SIO_SET_FLOW_CTRL_REQUEST, 276662306a36Sopenharmony_ci FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 276762306a36Sopenharmony_ci value, index, NULL, 0, WDR_TIMEOUT); 276862306a36Sopenharmony_ci if (ret < 0) 276962306a36Sopenharmony_ci dev_err(&port->dev, "failed to set flow control: %d\n", ret); 277062306a36Sopenharmony_ci} 277162306a36Sopenharmony_ci 277262306a36Sopenharmony_ci/* 277362306a36Sopenharmony_ci * Get modem-control status. 277462306a36Sopenharmony_ci * 277562306a36Sopenharmony_ci * Returns the number of status bytes retrieved (device dependant), or 277662306a36Sopenharmony_ci * negative error code. 277762306a36Sopenharmony_ci */ 277862306a36Sopenharmony_cistatic int ftdi_get_modem_status(struct usb_serial_port *port, 277962306a36Sopenharmony_ci unsigned char status[2]) 278062306a36Sopenharmony_ci{ 278162306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 278262306a36Sopenharmony_ci unsigned char *buf; 278362306a36Sopenharmony_ci int len; 278462306a36Sopenharmony_ci int ret; 278562306a36Sopenharmony_ci 278662306a36Sopenharmony_ci buf = kmalloc(2, GFP_KERNEL); 278762306a36Sopenharmony_ci if (!buf) 278862306a36Sopenharmony_ci return -ENOMEM; 278962306a36Sopenharmony_ci /* 279062306a36Sopenharmony_ci * The device returns a two byte value (the SIO a 1 byte value) in the 279162306a36Sopenharmony_ci * same format as the data returned from the IN endpoint. 279262306a36Sopenharmony_ci */ 279362306a36Sopenharmony_ci if (priv->chip_type == SIO) 279462306a36Sopenharmony_ci len = 1; 279562306a36Sopenharmony_ci else 279662306a36Sopenharmony_ci len = 2; 279762306a36Sopenharmony_ci 279862306a36Sopenharmony_ci ret = usb_control_msg(port->serial->dev, 279962306a36Sopenharmony_ci usb_rcvctrlpipe(port->serial->dev, 0), 280062306a36Sopenharmony_ci FTDI_SIO_GET_MODEM_STATUS_REQUEST, 280162306a36Sopenharmony_ci FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 280262306a36Sopenharmony_ci 0, priv->channel, 280362306a36Sopenharmony_ci buf, len, WDR_TIMEOUT); 280462306a36Sopenharmony_ci 280562306a36Sopenharmony_ci /* NOTE: We allow short responses and handle that below. */ 280662306a36Sopenharmony_ci if (ret < 1) { 280762306a36Sopenharmony_ci dev_err(&port->dev, "failed to get modem status: %d\n", ret); 280862306a36Sopenharmony_ci if (ret >= 0) 280962306a36Sopenharmony_ci ret = -EIO; 281062306a36Sopenharmony_ci ret = usb_translate_errors(ret); 281162306a36Sopenharmony_ci goto out; 281262306a36Sopenharmony_ci } 281362306a36Sopenharmony_ci 281462306a36Sopenharmony_ci status[0] = buf[0]; 281562306a36Sopenharmony_ci if (ret > 1) 281662306a36Sopenharmony_ci status[1] = buf[1]; 281762306a36Sopenharmony_ci else 281862306a36Sopenharmony_ci status[1] = 0; 281962306a36Sopenharmony_ci 282062306a36Sopenharmony_ci dev_dbg(&port->dev, "%s - 0x%02x%02x\n", __func__, status[0], 282162306a36Sopenharmony_ci status[1]); 282262306a36Sopenharmony_ciout: 282362306a36Sopenharmony_ci kfree(buf); 282462306a36Sopenharmony_ci 282562306a36Sopenharmony_ci return ret; 282662306a36Sopenharmony_ci} 282762306a36Sopenharmony_ci 282862306a36Sopenharmony_cistatic int ftdi_tiocmget(struct tty_struct *tty) 282962306a36Sopenharmony_ci{ 283062306a36Sopenharmony_ci struct usb_serial_port *port = tty->driver_data; 283162306a36Sopenharmony_ci struct ftdi_private *priv = usb_get_serial_port_data(port); 283262306a36Sopenharmony_ci unsigned char buf[2]; 283362306a36Sopenharmony_ci int ret; 283462306a36Sopenharmony_ci 283562306a36Sopenharmony_ci ret = ftdi_get_modem_status(port, buf); 283662306a36Sopenharmony_ci if (ret < 0) 283762306a36Sopenharmony_ci return ret; 283862306a36Sopenharmony_ci 283962306a36Sopenharmony_ci ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | 284062306a36Sopenharmony_ci (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | 284162306a36Sopenharmony_ci (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | 284262306a36Sopenharmony_ci (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | 284362306a36Sopenharmony_ci priv->last_dtr_rts; 284462306a36Sopenharmony_ci 284562306a36Sopenharmony_ci return ret; 284662306a36Sopenharmony_ci} 284762306a36Sopenharmony_ci 284862306a36Sopenharmony_cistatic int ftdi_tiocmset(struct tty_struct *tty, 284962306a36Sopenharmony_ci unsigned int set, unsigned int clear) 285062306a36Sopenharmony_ci{ 285162306a36Sopenharmony_ci struct usb_serial_port *port = tty->driver_data; 285262306a36Sopenharmony_ci 285362306a36Sopenharmony_ci return update_mctrl(port, set, clear); 285462306a36Sopenharmony_ci} 285562306a36Sopenharmony_ci 285662306a36Sopenharmony_cistatic int ftdi_ioctl(struct tty_struct *tty, 285762306a36Sopenharmony_ci unsigned int cmd, unsigned long arg) 285862306a36Sopenharmony_ci{ 285962306a36Sopenharmony_ci struct usb_serial_port *port = tty->driver_data; 286062306a36Sopenharmony_ci void __user *argp = (void __user *)arg; 286162306a36Sopenharmony_ci 286262306a36Sopenharmony_ci switch (cmd) { 286362306a36Sopenharmony_ci case TIOCSERGETLSR: 286462306a36Sopenharmony_ci return get_lsr_info(port, argp); 286562306a36Sopenharmony_ci default: 286662306a36Sopenharmony_ci break; 286762306a36Sopenharmony_ci } 286862306a36Sopenharmony_ci 286962306a36Sopenharmony_ci return -ENOIOCTLCMD; 287062306a36Sopenharmony_ci} 287162306a36Sopenharmony_ci 287262306a36Sopenharmony_cistatic struct usb_serial_driver ftdi_device = { 287362306a36Sopenharmony_ci .driver = { 287462306a36Sopenharmony_ci .owner = THIS_MODULE, 287562306a36Sopenharmony_ci .name = "ftdi_sio", 287662306a36Sopenharmony_ci .dev_groups = ftdi_groups, 287762306a36Sopenharmony_ci }, 287862306a36Sopenharmony_ci .description = "FTDI USB Serial Device", 287962306a36Sopenharmony_ci .id_table = id_table_combined, 288062306a36Sopenharmony_ci .num_ports = 1, 288162306a36Sopenharmony_ci .bulk_in_size = 512, 288262306a36Sopenharmony_ci .bulk_out_size = 256, 288362306a36Sopenharmony_ci .probe = ftdi_probe, 288462306a36Sopenharmony_ci .port_probe = ftdi_port_probe, 288562306a36Sopenharmony_ci .port_remove = ftdi_port_remove, 288662306a36Sopenharmony_ci .open = ftdi_open, 288762306a36Sopenharmony_ci .dtr_rts = ftdi_dtr_rts, 288862306a36Sopenharmony_ci .throttle = usb_serial_generic_throttle, 288962306a36Sopenharmony_ci .unthrottle = usb_serial_generic_unthrottle, 289062306a36Sopenharmony_ci .process_read_urb = ftdi_process_read_urb, 289162306a36Sopenharmony_ci .prepare_write_buffer = ftdi_prepare_write_buffer, 289262306a36Sopenharmony_ci .tiocmget = ftdi_tiocmget, 289362306a36Sopenharmony_ci .tiocmset = ftdi_tiocmset, 289462306a36Sopenharmony_ci .tiocmiwait = usb_serial_generic_tiocmiwait, 289562306a36Sopenharmony_ci .get_icount = usb_serial_generic_get_icount, 289662306a36Sopenharmony_ci .ioctl = ftdi_ioctl, 289762306a36Sopenharmony_ci .get_serial = get_serial_info, 289862306a36Sopenharmony_ci .set_serial = set_serial_info, 289962306a36Sopenharmony_ci .set_termios = ftdi_set_termios, 290062306a36Sopenharmony_ci .break_ctl = ftdi_break_ctl, 290162306a36Sopenharmony_ci .tx_empty = ftdi_tx_empty, 290262306a36Sopenharmony_ci}; 290362306a36Sopenharmony_ci 290462306a36Sopenharmony_cistatic struct usb_serial_driver * const serial_drivers[] = { 290562306a36Sopenharmony_ci &ftdi_device, NULL 290662306a36Sopenharmony_ci}; 290762306a36Sopenharmony_cimodule_usb_serial_driver(serial_drivers, id_table_combined); 290862306a36Sopenharmony_ci 290962306a36Sopenharmony_ciMODULE_AUTHOR(DRIVER_AUTHOR); 291062306a36Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC); 291162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 291262306a36Sopenharmony_ci 291362306a36Sopenharmony_cimodule_param(ndi_latency_timer, int, 0644); 291462306a36Sopenharmony_ciMODULE_PARM_DESC(ndi_latency_timer, "NDI device latency timer override"); 2915