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