freebsd-dev/sys/dev/usb/serial/uftdi.c
Ian Lepore 9537ab6cc8 Support serial speeds up to 12mbaud with newer FTDI chips.
Recent FDTI chips have the ability to operate at up to 12mbps.  The newer
chips with faster clocks have the same usb vendor/product IDs as the older
chips; the bcdDevice field must be used to detect the newer versions.  This
change includes a new function to do that instead of using just the IDs from
the vendor/product table.

The code to choose the baud clock divisor is completely rewritten.  In
addition to supporting the new higher clock rates, the rewrite fixes a
longstanding bug in the old code which put the high bits of the fractional
part of the divisor into the wrong place in the wIndex field.  That bug
was mostly harmless -- it accidentally didn't affect standard baud rates
and would only show up when using relatively fast non-standard rates.
2014-04-01 15:56:31 +00:00

1565 lines
57 KiB
C

/* $NetBSD: uftdi.c,v 1.13 2002/09/23 05:51:23 simonb Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Lennart Augustsson (lennart@augustsson.net).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* NOTE: all function names beginning like "uftdi_cfg_" can only
* be called from within the config thread function !
*/
/*
* FTDI FT2232x, FT8U100AX and FT8U232AM serial adapter driver
*/
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/sysctl.h>
#include <sys/sx.h>
#include <sys/unistd.h>
#include <sys/callout.h>
#include <sys/malloc.h>
#include <sys/priv.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include "usbdevs.h"
#define USB_DEBUG_VAR uftdi_debug
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_process.h>
#include <dev/usb/serial/usb_serial.h>
#include <dev/usb/serial/uftdi_reg.h>
#ifdef USB_DEBUG
static int uftdi_debug = 0;
static SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW, 0, "USB uftdi");
SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, debug, CTLFLAG_RW,
&uftdi_debug, 0, "Debug level");
#endif
#define UFTDI_CONFIG_INDEX 0
#define UFTDI_IFACE_INDEX_JTAG 0
#define UFTDI_OBUFSIZE 64 /* bytes, cannot be increased due to
* do size encoding */
enum {
UFTDI_BULK_DT_WR,
UFTDI_BULK_DT_RD,
UFTDI_N_TRANSFER,
};
enum {
DEVT_SIO,
DEVT_232A,
DEVT_232B,
DEVT_2232D, /* Includes 2232C */
DEVT_232R,
DEVT_2232H,
DEVT_4232H,
DEVT_232H,
DEVT_230X,
};
#define DEVF_BAUDBITS_HINDEX 0x01 /* Baud bits in high byte of index. */
#define DEVF_BAUDCLK_12M 0X02 /* Base baud clock is 12MHz. */
struct uftdi_softc {
struct ucom_super_softc sc_super_ucom;
struct ucom_softc sc_ucom;
struct usb_device *sc_udev;
struct usb_xfer *sc_xfer[UFTDI_N_TRANSFER];
device_t sc_dev;
struct mtx sc_mtx;
uint32_t sc_unit;
uint16_t sc_last_lcr;
uint8_t sc_devtype;
uint8_t sc_devflags;
uint8_t sc_hdrlen;
uint8_t sc_msr;
uint8_t sc_lsr;
};
struct uftdi_param_config {
uint16_t baud_lobits;
uint16_t baud_hibits;
uint16_t lcr;
uint8_t v_start;
uint8_t v_stop;
uint8_t v_flow;
};
/* prototypes */
static device_probe_t uftdi_probe;
static device_attach_t uftdi_attach;
static device_detach_t uftdi_detach;
static void uftdi_free_softc(struct uftdi_softc *);
static usb_callback_t uftdi_write_callback;
static usb_callback_t uftdi_read_callback;
static void uftdi_free(struct ucom_softc *);
static void uftdi_cfg_open(struct ucom_softc *);
static void uftdi_cfg_set_dtr(struct ucom_softc *, uint8_t);
static void uftdi_cfg_set_rts(struct ucom_softc *, uint8_t);
static void uftdi_cfg_set_break(struct ucom_softc *, uint8_t);
static int uftdi_set_parm_soft(struct ucom_softc *, struct termios *,
struct uftdi_param_config *);
static int uftdi_pre_param(struct ucom_softc *, struct termios *);
static void uftdi_cfg_param(struct ucom_softc *, struct termios *);
static void uftdi_cfg_get_status(struct ucom_softc *, uint8_t *,
uint8_t *);
static void uftdi_start_read(struct ucom_softc *);
static void uftdi_stop_read(struct ucom_softc *);
static void uftdi_start_write(struct ucom_softc *);
static void uftdi_stop_write(struct ucom_softc *);
static void uftdi_poll(struct ucom_softc *ucom);
static const struct usb_config uftdi_config[UFTDI_N_TRANSFER] = {
[UFTDI_BULK_DT_WR] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = UFTDI_OBUFSIZE,
.flags = {.pipe_bof = 1,},
.callback = &uftdi_write_callback,
},
[UFTDI_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = 0, /* use wMaxPacketSize */
.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
.callback = &uftdi_read_callback,
},
};
static const struct ucom_callback uftdi_callback = {
.ucom_cfg_get_status = &uftdi_cfg_get_status,
.ucom_cfg_set_dtr = &uftdi_cfg_set_dtr,
.ucom_cfg_set_rts = &uftdi_cfg_set_rts,
.ucom_cfg_set_break = &uftdi_cfg_set_break,
.ucom_cfg_param = &uftdi_cfg_param,
.ucom_cfg_open = &uftdi_cfg_open,
.ucom_pre_param = &uftdi_pre_param,
.ucom_start_read = &uftdi_start_read,
.ucom_stop_read = &uftdi_stop_read,
.ucom_start_write = &uftdi_start_write,
.ucom_stop_write = &uftdi_stop_write,
.ucom_poll = &uftdi_poll,
.ucom_free = &uftdi_free,
};
static device_method_t uftdi_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, uftdi_probe),
DEVMETHOD(device_attach, uftdi_attach),
DEVMETHOD(device_detach, uftdi_detach),
DEVMETHOD_END
};
static devclass_t uftdi_devclass;
static driver_t uftdi_driver = {
.name = "uftdi",
.methods = uftdi_methods,
.size = sizeof(struct uftdi_softc),
};
DRIVER_MODULE(uftdi, uhub, uftdi_driver, uftdi_devclass, NULL, NULL);
MODULE_DEPEND(uftdi, ucom, 1, 1, 1);
MODULE_DEPEND(uftdi, usb, 1, 1, 1);
MODULE_VERSION(uftdi, 1);
static const STRUCT_USB_HOST_ID uftdi_devs[] = {
#define UFTDI_DEV(v, p, i) \
{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
UFTDI_DEV(ACTON, SPECTRAPRO, UFTDI_TYPE_AUTO),
UFTDI_DEV(ALTI2, N3, UFTDI_TYPE_AUTO),
UFTDI_DEV(ANALOGDEVICES, GNICE, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(ANALOGDEVICES, GNICEPLUS, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(ATMEL, STK541, UFTDI_TYPE_8U232AM),
UFTDI_DEV(BAYER, CONTOUR_CABLE, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, 232USB9M, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, 485USB9F_2W, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, 485USB9F_4W, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, 485USBTB_2W, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, 485USBTB_4W, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, TTL3USB9M, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, TTL5USB9M, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, USO9ML2, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, USO9ML2DR, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, USO9ML2DR_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, USOPTL4, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, USOPTL4DR, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, USOPTL4DR2, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, USOTL4, UFTDI_TYPE_8U232AM),
UFTDI_DEV(BBELECTRONICS, USPTL4, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, USTL4, UFTDI_TYPE_AUTO),
UFTDI_DEV(BBELECTRONICS, ZZ_PROG1_USB, UFTDI_TYPE_AUTO),
UFTDI_DEV(CONTEC, COM1USBH, UFTDI_TYPE_AUTO),
UFTDI_DEV(DRESDENELEKTRONIK, SENSORTERMINALBOARD, UFTDI_TYPE_8U232AM),
UFTDI_DEV(DRESDENELEKTRONIK, WIRELESSHANDHELDTERMINAL, UFTDI_TYPE_8U232AM),
UFTDI_DEV(ELEKTOR, FT323R, UFTDI_TYPE_AUTO),
UFTDI_DEV(EVOLUTION, ER1, UFTDI_TYPE_AUTO),
UFTDI_DEV(EVOLUTION, HYBRID, UFTDI_TYPE_AUTO),
UFTDI_DEV(EVOLUTION, RCM4, UFTDI_TYPE_AUTO),
UFTDI_DEV(FALCOM, SAMBA, UFTDI_TYPE_AUTO),
UFTDI_DEV(FALCOM, TWIST, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(FTDI, 232EX, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, 232H, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, 232RL, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, 4N_GALAXY_DE_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, 4N_GALAXY_DE_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, 4N_GALAXY_DE_3, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, 8U232AM_ALT, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ACCESSO, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ACG_HFDUAL, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ACTIVE_ROBOTS, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ACTZWAVE, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, AMC232, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ARTEMIS, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ASK_RDR400, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ATIK_ATK16, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ATIK_ATK16C, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ATIK_ATK16HR, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ATIK_ATK16HRC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ATIK_ATK16IC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, BCS_SE923, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, BEAGLEBONE, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, CANDAPTER, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CANUSB, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CCSICDU20_0, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CCSICDU40_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CCSICDU64_4, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CCSLOAD_N_GO_3, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CCSMACHX_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CCSPRIME8_5, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CFA_631, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, CFA_632, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, CFA_633, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, CFA_634, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, CFA_635, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, CHAMSYS_24_MASTER_WING, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CHAMSYS_MAXI_WING, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CHAMSYS_MEDIA_WING, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CHAMSYS_MIDI_TIMECODE, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CHAMSYS_MINI_WING, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CHAMSYS_PC_WING, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CHAMSYS_USB_DMX, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CHAMSYS_WING, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, COM4SM, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CONVERTER_0, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CONVERTER_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CONVERTER_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CONVERTER_3, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CONVERTER_4, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CONVERTER_5, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CONVERTER_6, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CONVERTER_7, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, CTI_USB_MINI_485, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, CTI_USB_NANO_485, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, DMX4ALL, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, DOMINTELL_DGQG, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, DOMINTELL_DUSB, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, DOTEC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ECLO_COM_1WIRE, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ECO_PRO_CDS, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, EISCOU, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, ELSTER_UNICOM, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_ALC8500, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_CLI7000, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_CSI8, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_EC3000, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_EM1000DL, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_EM1010PC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_FEM, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_FHZ1000PC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_FHZ1300PC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_FM3RX, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_FS20SIG, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_HS485, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_KL100, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_MSM1, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_PCD200, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_PCK100, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_PPS7330, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_RFP500, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_T1100, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_TFD128, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_TFM100, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_TWS550, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_UAD8, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_UDA7, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_UDF77, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_UIO88, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_ULA200, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_UM100, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_UMS100, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_UO100, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_UR100, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_USI2, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_USR, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_UTP8, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_WS300PC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_WS444PC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_WS500, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_WS550, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_WS777, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, ELV_WS888, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, EMCU2D, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, EMCU2H, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, FUTURE_0, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, FUTURE_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, FUTURE_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GAMMASCOUT, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, GENERIC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GUDEADS_E808, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GUDEADS_E809, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GUDEADS_E80A, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GUDEADS_E80B, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GUDEADS_E80C, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GUDEADS_E80D, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GUDEADS_E80E, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GUDEADS_E80F, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GUDEADS_E88D, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GUDEADS_E88E, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, GUDEADS_E88F, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, HD_RADIO, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, HO720, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, HO730, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, HO820, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, HO870, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, IBS_APP70, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, IBS_PCMCIA, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, IBS_PEDO, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, IBS_PICPRO, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, IBS_PK1, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, IBS_PROD, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, IBS_RS232MON, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, IBS_US485, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, IPLUS, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, IPLUS2, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, IRTRANS, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, KBS, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, KTLINK, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, LENZ_LIUSB, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, LK202, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, LK204, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, LM3S_DEVEL_BOARD, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(FTDI, LM3S_EVAL_BOARD, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(FTDI, LM3S_ICDI_B_BOARD, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(FTDI, MASTERDEVEL2, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MAXSTREAM, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, MHAM_DB9, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MHAM_IC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MHAM_KW, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MHAM_RS232, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MHAM_Y6, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MHAM_Y8, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MHAM_Y9, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MHAM_YS, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MICRO_CHAMELEON, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MTXORB_5, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MTXORB_6, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, MX2_3, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, MX4_5, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, NXTCAM, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, OCEANIC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, OOCDLINK, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(FTDI, OPENDCC, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, OPENDCC_GATEWAY, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, OPENDCC_GBM, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, OPENDCC_SNIFFER, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, OPENDCC_THROTTLE, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, PCDJ_DAC2, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, PCMSFU, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, PERLE_ULTRAPORT, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, PHI_FISCO, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, PIEGROUP, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, PROPOX_JTAGCABLEII, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, R2000KU_TRUE_RNG, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, R2X0, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, RELAIS, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, REU_TINY, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, RMP200, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, RM_CANVIEW, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, RRCIRKITS_LOCOBUFFER, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SCIENCESCOPE_HS_LOGBOOK, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SCIENCESCOPE_LOGBOOKML, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SCIENCESCOPE_LS_LOGBOOK, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SCS_DEVICE_0, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SCS_DEVICE_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SCS_DEVICE_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SCS_DEVICE_3, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SCS_DEVICE_4, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SCS_DEVICE_5, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SCS_DEVICE_6, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SCS_DEVICE_7, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SDMUSBQSS, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SEMC_DSS20, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, SERIAL_2232C, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, SERIAL_2232D, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, SERIAL_232RL, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SERIAL_4232H, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, SERIAL_8U100AX, UFTDI_TYPE_SIO),
UFTDI_DEV(FTDI, SERIAL_8U232AM, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, SERIAL_8U232AM4, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, SIGNALYZER_SH2, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(FTDI, SIGNALYZER_SH4, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(FTDI, SIGNALYZER_SLITE, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(FTDI, SIGNALYZER_ST, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(FTDI, SPECIAL_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SPECIAL_3, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SPECIAL_4, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SPROG_II, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SR_RADIO, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, SUUNTO_SPORTS, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13M, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13S, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13U, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, TAVIR_STK500, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, TERATRONIK_D2XX, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, TERATRONIK_VCP, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, THORLABS, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, TNC_X, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, TTUSB, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, TURTELIZER2, UFTDI_TYPE_8U232AM | UFTDI_FLAG_JTAG),
UFTDI_DEV(FTDI, UOPTBR, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, USBSERIAL, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, USBX_707, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, USB_UIRT, UFTDI_TYPE_8U232AM),
UFTDI_DEV(FTDI, USINT_CAT, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, USINT_RS232, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, USINT_WKEY, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, VARDAAN, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, VNHCPCUSB_D, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, WESTREX_MODEL_777, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, WESTREX_MODEL_8900F, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, XF_547, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, XF_640, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, XF_642, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, XM_RADIO, UFTDI_TYPE_AUTO),
UFTDI_DEV(FTDI, YEI_SERVOCENTER31, UFTDI_TYPE_AUTO),
UFTDI_DEV(GNOTOMETRICS, USB, UFTDI_TYPE_AUTO),
UFTDI_DEV(ICOM, SP1, UFTDI_TYPE_AUTO),
UFTDI_DEV(ICOM, OPC_U_UC, UFTDI_TYPE_AUTO),
UFTDI_DEV(ICOM, RP2C1, UFTDI_TYPE_AUTO),
UFTDI_DEV(ICOM, RP2C2, UFTDI_TYPE_AUTO),
UFTDI_DEV(ICOM, RP2D, UFTDI_TYPE_AUTO),
UFTDI_DEV(ICOM, RP2KVR, UFTDI_TYPE_AUTO),
UFTDI_DEV(ICOM, RP2KVT, UFTDI_TYPE_AUTO),
UFTDI_DEV(ICOM, RP2VR, UFTDI_TYPE_AUTO),
UFTDI_DEV(ICOM, RP2VT, UFTDI_TYPE_AUTO),
UFTDI_DEV(ICOM, RP4KVR, UFTDI_TYPE_AUTO),
UFTDI_DEV(ICOM, RP4KVT, UFTDI_TYPE_AUTO),
UFTDI_DEV(IDTECH, IDT1221U, UFTDI_TYPE_AUTO),
UFTDI_DEV(INTERBIOMETRICS, IOBOARD, UFTDI_TYPE_AUTO),
UFTDI_DEV(INTERBIOMETRICS, MINI_IOBOARD, UFTDI_TYPE_AUTO),
UFTDI_DEV(INTREPIDCS, NEOVI, UFTDI_TYPE_8U232AM),
UFTDI_DEV(INTREPIDCS, VALUECAN, UFTDI_TYPE_8U232AM),
UFTDI_DEV(IONICS, PLUGCOMPUTER, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(JETI, SPC1201, UFTDI_TYPE_AUTO),
UFTDI_DEV(KOBIL, CONV_B1, UFTDI_TYPE_AUTO),
UFTDI_DEV(KOBIL, CONV_KAAN, UFTDI_TYPE_AUTO),
UFTDI_DEV(LARSENBRUSGAARD, ALTITRACK, UFTDI_TYPE_AUTO),
UFTDI_DEV(MARVELL, SHEEVAPLUG, UFTDI_TYPE_8U232AM),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0100, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0101, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0102, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0103, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0104, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0105, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0106, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0107, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0108, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0109, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010A, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010B, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010C, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010D, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010E, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010F, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0110, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0111, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0112, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0113, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0114, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0115, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0116, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0117, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0118, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0119, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011A, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011B, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011C, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011D, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011E, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011F, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0120, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0121, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0122, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0123, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0124, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0125, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0126, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0128, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0129, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012A, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012B, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012D, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012E, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012F, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0130, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0131, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0132, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0133, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0134, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0135, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0136, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0137, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0138, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0139, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013A, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013B, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013C, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013D, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013E, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013F, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0140, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0141, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0142, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0143, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0144, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0145, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0146, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0147, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0148, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0149, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014A, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014B, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014C, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014D, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014E, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014F, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0150, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0151, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0152, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0159, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015A, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015B, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015C, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015D, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015E, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015F, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0160, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0161, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0162, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0163, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0164, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0165, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0166, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0167, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0168, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0169, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016A, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016B, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016C, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016D, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016E, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016F, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0170, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0171, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0172, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0173, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0174, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0175, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0176, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0177, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0178, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0179, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017A, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017B, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017C, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017D, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017E, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017F, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0180, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0181, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0182, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0183, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0184, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0185, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0186, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0187, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0188, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0189, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018A, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018B, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018C, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018D, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018E, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018F, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0190, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0191, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0192, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0193, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0194, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0195, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0196, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0197, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0198, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0199, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019A, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019B, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019C, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019D, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019E, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019F, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A0, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A1, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A2, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A3, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A4, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A5, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A6, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A7, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A8, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A9, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AA, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AB, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AC, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AD, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AE, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AF, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B0, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B1, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B2, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B3, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B4, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B5, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B6, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B7, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B8, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B9, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BA, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BB, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BC, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BD, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BE, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BF, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C0, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C1, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C2, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C3, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C4, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C5, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C6, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C7, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C8, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C9, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CA, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CB, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CC, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CD, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CE, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CF, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D0, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D1, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D2, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D3, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D4, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D5, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D6, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D7, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D8, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D9, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DA, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DB, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DC, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DD, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DE, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DF, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E0, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E1, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E2, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E3, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E4, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E5, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E6, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E7, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E8, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E9, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EA, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EB, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EC, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01ED, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EE, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EF, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F0, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F1, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F2, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F3, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F4, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F5, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F6, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F7, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F8, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F9, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FA, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FB, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FC, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FD, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FE, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FF, UFTDI_TYPE_AUTO),
UFTDI_DEV(MATRIXORBITAL, MOUA, UFTDI_TYPE_8U232AM),
UFTDI_DEV(MELCO, PCOPRS1, UFTDI_TYPE_8U232AM),
UFTDI_DEV(METAGEEK, TELLSTICK, UFTDI_TYPE_AUTO),
UFTDI_DEV(MOBILITY, USB_SERIAL, UFTDI_TYPE_AUTO),
UFTDI_DEV(OLIMEX, ARM_USB_OCD, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(OLIMEX, ARM_USB_OCD_H, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(OPTO, CRD7734, UFTDI_TYPE_AUTO),
UFTDI_DEV(OPTO, CRD7734_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, AD4USB, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, AP485, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, AP485_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, DRAK5, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, DRAK6, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, GMSR, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, GMUX, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, IRAMP, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, LEC, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, MU, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, QUIDO10X1, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, QUIDO2X16, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, QUIDO2X2, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, QUIDO30X3, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, QUIDO3X32, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, QUIDO4X4, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, QUIDO60X3, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, QUIDO8X8, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, SB232, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, SB422, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, SB422_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, SB485, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, SB485C, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, SB485S, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, SB485_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, SIMUKEY, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, TMU, UFTDI_TYPE_AUTO),
UFTDI_DEV(PAPOUCH, UPSUSB, UFTDI_TYPE_AUTO),
UFTDI_DEV(POSIFLEX, PP7000, UFTDI_TYPE_AUTO),
UFTDI_DEV(QIHARDWARE, JTAGSERIAL, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
UFTDI_DEV(RATOC, REXUSB60F, UFTDI_TYPE_8U232AM),
UFTDI_DEV(RTSYSTEMS, CT29B, UFTDI_TYPE_AUTO),
UFTDI_DEV(RTSYSTEMS, SERIAL_VX7, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2101, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2102, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2103, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2104, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2106, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2201_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2201_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2202_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2202_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2203_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2203_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2401_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2401_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2401_3, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2401_4, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2402_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2402_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2402_3, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2402_4, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2403_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2403_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2403_3, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2403_4, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2801_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2801_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2801_3, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2801_4, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2801_5, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2801_6, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2801_7, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2801_8, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2802_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2802_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2802_3, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2802_4, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2802_5, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2802_6, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2802_7, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2802_8, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2803_1, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2803_2, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2803_3, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2803_4, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2803_5, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2803_6, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2803_7, UFTDI_TYPE_AUTO),
UFTDI_DEV(SEALEVEL, 2803_8, UFTDI_TYPE_AUTO),
UFTDI_DEV(SIIG2, DK201, UFTDI_TYPE_AUTO),
UFTDI_DEV(SIIG2, US2308, UFTDI_TYPE_8U232AM),
UFTDI_DEV(TESTO, USB_INTERFACE, UFTDI_TYPE_AUTO),
UFTDI_DEV(TML, USB_SERIAL, UFTDI_TYPE_AUTO),
UFTDI_DEV(TTI, QL355P, UFTDI_TYPE_AUTO),
UFTDI_DEV(UNKNOWN4, NF_RIC, UFTDI_TYPE_AUTO),
#undef UFTDI_DEV
};
/*
* Set up softc fields whose value depends on the device type.
*
* Note that the 2232C and 2232D devices are the same for our purposes. In the
* silicon the difference is that the D series has CPU FIFO mode and C doesn't.
* I haven't found any way of determining the C/D difference from info provided
* by the chip other than trying to set CPU FIFO mode and having it work or not.
*
* Due to a hardware bug, a 232B chip without an eeprom reports itself as a
* 232A, but if the serial number is also zero we know it's really a 232B.
*/
static void
uftdi_devtype_setup(struct uftdi_softc *sc, struct usb_attach_arg *uaa)
{
struct usb_device_descriptor *dd;
switch (uaa->info.bcdDevice) {
case 0x200:
dd = usbd_get_device_descriptor(sc->sc_udev);
if (dd->iSerialNumber == 0) {
sc->sc_devtype = DEVT_232B;
} else {
sc->sc_devtype = DEVT_232A;
}
sc->sc_ucom.sc_portno = 0;
break;
case 0x400:
sc->sc_devtype = DEVT_232B;
sc->sc_ucom.sc_portno = 0;
break;
case 0x500:
sc->sc_devtype = DEVT_2232D;
sc->sc_devflags |= DEVF_BAUDBITS_HINDEX;
sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
break;
case 0x600:
sc->sc_devtype = DEVT_232R;
sc->sc_ucom.sc_portno = 0;
break;
case 0x700:
sc->sc_devtype = DEVT_2232H;
sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
break;
case 0x800:
sc->sc_devtype = DEVT_4232H;
sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
break;
case 0x900:
sc->sc_devtype = DEVT_232H;
sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
break;
case 0x1000:
sc->sc_devtype = DEVT_230X;
sc->sc_devflags |= DEVF_BAUDBITS_HINDEX;
sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
break;
default:
if (uaa->info.bcdDevice < 0x200) {
sc->sc_devtype = DEVT_SIO;
sc->sc_hdrlen = 1;
} else {
sc->sc_devtype = DEVT_232R;
device_printf(sc->sc_dev, "Warning: unknown FTDI "
"device type, bcdDevice=0x%04x, assuming 232R",
uaa->info.bcdDevice);
}
sc->sc_ucom.sc_portno = 0;
break;
}
}
static int
uftdi_probe(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
const struct usb_device_id *id;
if (uaa->usb_mode != USB_MODE_HOST) {
return (ENXIO);
}
if (uaa->info.bConfigIndex != UFTDI_CONFIG_INDEX) {
return (ENXIO);
}
/*
* Attach to all present interfaces unless this is a JTAG one, which
* we leave for userland.
*/
id = usbd_lookup_id_by_info(uftdi_devs, sizeof(uftdi_devs),
&uaa->info);
if (id == NULL)
return (ENXIO);
if ((id->driver_info & UFTDI_FLAG_JTAG) != 0 &&
uaa->info.bIfaceIndex == UFTDI_IFACE_INDEX_JTAG) {
printf("%s: skipping JTAG interface at %u.%u\n",
device_get_name(dev), usbd_get_bus_index(uaa->device),
usbd_get_device_index(uaa->device));
return (ENXIO);
}
uaa->driver_info = id->driver_info;
return (BUS_PROBE_SPECIFIC);
}
static int
uftdi_attach(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct uftdi_softc *sc = device_get_softc(dev);
int error;
DPRINTF("\n");
sc->sc_udev = uaa->device;
sc->sc_dev = dev;
sc->sc_unit = device_get_unit(dev);
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "uftdi", NULL, MTX_DEF);
ucom_ref(&sc->sc_super_ucom);
uftdi_devtype_setup(sc, uaa);
error = usbd_transfer_setup(uaa->device,
&uaa->info.bIfaceIndex, sc->sc_xfer, uftdi_config,
UFTDI_N_TRANSFER, sc, &sc->sc_mtx);
if (error) {
device_printf(dev, "allocating USB "
"transfers failed\n");
goto detach;
}
/* clear stall at first run */
mtx_lock(&sc->sc_mtx);
usbd_xfer_set_stall(sc->sc_xfer[UFTDI_BULK_DT_WR]);
usbd_xfer_set_stall(sc->sc_xfer[UFTDI_BULK_DT_RD]);
mtx_unlock(&sc->sc_mtx);
/* set a valid "lcr" value */
sc->sc_last_lcr =
(FTDI_SIO_SET_DATA_STOP_BITS_2 |
FTDI_SIO_SET_DATA_PARITY_NONE |
FTDI_SIO_SET_DATA_BITS(8));
error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
&uftdi_callback, &sc->sc_mtx);
if (error) {
goto detach;
}
ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev);
return (0); /* success */
detach:
uftdi_detach(dev);
return (ENXIO);
}
static int
uftdi_detach(device_t dev)
{
struct uftdi_softc *sc = device_get_softc(dev);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UFTDI_N_TRANSFER);
device_claim_softc(dev);
uftdi_free_softc(sc);
return (0);
}
UCOM_UNLOAD_DRAIN(uftdi);
static void
uftdi_free_softc(struct uftdi_softc *sc)
{
if (ucom_unref(&sc->sc_super_ucom)) {
mtx_destroy(&sc->sc_mtx);
device_free_softc(sc);
}
}
static void
uftdi_free(struct ucom_softc *ucom)
{
uftdi_free_softc(ucom->sc_parent);
}
static void
uftdi_cfg_open(struct ucom_softc *ucom)
{
struct uftdi_softc *sc = ucom->sc_parent;
uint16_t wIndex = ucom->sc_portno;
struct usb_device_request req;
DPRINTF("");
/* perform a full reset on the device */
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = FTDI_SIO_RESET;
USETW(req.wValue, FTDI_SIO_RESET_SIO);
USETW(req.wIndex, wIndex);
USETW(req.wLength, 0);
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
&req, NULL, 0, 1000);
/* turn on RTS/CTS flow control */
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = FTDI_SIO_SET_FLOW_CTRL;
USETW(req.wValue, 0);
USETW2(req.wIndex, FTDI_SIO_RTS_CTS_HS, wIndex);
USETW(req.wLength, 0);
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
&req, NULL, 0, 1000);
/*
* NOTE: with the new UCOM layer there will always be a
* "uftdi_cfg_param()" call after "open()", so there is no need for
* "open()" to configure anything
*/
}
static void
uftdi_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct uftdi_softc *sc = usbd_xfer_softc(xfer);
struct usb_page_cache *pc;
uint32_t actlen;
uint8_t buf[1];
switch (USB_GET_STATE(xfer)) {
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(&sc->sc_ucom, pc,
sc->sc_hdrlen, UFTDI_OBUFSIZE - sc->sc_hdrlen,
&actlen)) {
if (sc->sc_hdrlen > 0) {
buf[0] =
FTDI_OUT_TAG(actlen, sc->sc_ucom.sc_portno);
usbd_copy_in(pc, 0, buf, 1);
}
usbd_xfer_set_frame_len(xfer, 0, actlen + sc->sc_hdrlen);
usbd_transfer_submit(xfer);
}
return;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
/* try to clear stall first */
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
return;
}
}
static void
uftdi_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct uftdi_softc *sc = usbd_xfer_softc(xfer);
struct usb_page_cache *pc;
uint8_t buf[2];
uint8_t ftdi_msr;
uint8_t msr;
uint8_t lsr;
int actlen;
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
if (actlen < 2) {
goto tr_setup;
}
pc = usbd_xfer_get_frame(xfer, 0);
usbd_copy_out(pc, 0, buf, 2);
ftdi_msr = FTDI_GET_MSR(buf);
lsr = FTDI_GET_LSR(buf);
msr = 0;
if (ftdi_msr & FTDI_SIO_CTS_MASK)
msr |= SER_CTS;
if (ftdi_msr & FTDI_SIO_DSR_MASK)
msr |= SER_DSR;
if (ftdi_msr & FTDI_SIO_RI_MASK)
msr |= SER_RI;
if (ftdi_msr & FTDI_SIO_RLSD_MASK)
msr |= SER_DCD;
if ((sc->sc_msr != msr) ||
((sc->sc_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK))) {
DPRINTF("status change msr=0x%02x (0x%02x) "
"lsr=0x%02x (0x%02x)\n", msr, sc->sc_msr,
lsr, sc->sc_lsr);
sc->sc_msr = msr;
sc->sc_lsr = lsr;
ucom_status_change(&sc->sc_ucom);
}
actlen -= 2;
if (actlen > 0) {
ucom_put_data(&sc->sc_ucom, pc, 2, actlen);
}
case USB_ST_SETUP:
tr_setup:
usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
usbd_transfer_submit(xfer);
return;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
/* try to clear stall first */
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
return;
}
}
static void
uftdi_cfg_set_dtr(struct ucom_softc *ucom, uint8_t onoff)
{
struct uftdi_softc *sc = ucom->sc_parent;
uint16_t wIndex = ucom->sc_portno;
uint16_t wValue;
struct usb_device_request req;
wValue = onoff ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW;
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = FTDI_SIO_MODEM_CTRL;
USETW(req.wValue, wValue);
USETW(req.wIndex, wIndex);
USETW(req.wLength, 0);
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
&req, NULL, 0, 1000);
}
static void
uftdi_cfg_set_rts(struct ucom_softc *ucom, uint8_t onoff)
{
struct uftdi_softc *sc = ucom->sc_parent;
uint16_t wIndex = ucom->sc_portno;
uint16_t wValue;
struct usb_device_request req;
wValue = onoff ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW;
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = FTDI_SIO_MODEM_CTRL;
USETW(req.wValue, wValue);
USETW(req.wIndex, wIndex);
USETW(req.wLength, 0);
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
&req, NULL, 0, 1000);
}
static void
uftdi_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff)
{
struct uftdi_softc *sc = ucom->sc_parent;
uint16_t wIndex = ucom->sc_portno;
uint16_t wValue;
struct usb_device_request req;
if (onoff) {
sc->sc_last_lcr |= FTDI_SIO_SET_BREAK;
} else {
sc->sc_last_lcr &= ~FTDI_SIO_SET_BREAK;
}
wValue = sc->sc_last_lcr;
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = FTDI_SIO_SET_DATA;
USETW(req.wValue, wValue);
USETW(req.wIndex, wIndex);
USETW(req.wLength, 0);
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
&req, NULL, 0, 1000);
}
/*
* Return true if the given speed is within operational tolerance of the target
* speed. FTDI recommends that the hardware speed be within 3% of nominal.
*/
static inline boolean_t
uftdi_baud_within_tolerance(uint64_t speed, uint64_t target)
{
return ((speed >= (target * 100) / 103) &&
(speed <= (target * 100) / 97));
}
static int
uftdi_sio_encode_baudrate(struct uftdi_softc *sc, speed_t speed,
struct uftdi_param_config *cfg)
{
u_int i;
const speed_t sio_speeds[] = {
300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200
};
/*
* The original SIO chips were limited to a small choice of speeds
* listed in an internal table of speeds chosen by an index value.
*/
for (i = 0; i < nitems(sio_speeds); ++i) {
if (speed == sio_speeds[i]) {
cfg->baud_lobits = i;
cfg->baud_hibits = 0;
return (0);
}
}
return (ERANGE);
}
static int
uftdi_encode_baudrate(struct uftdi_softc *sc, speed_t speed,
struct uftdi_param_config *cfg)
{
static const uint8_t encoded_fraction[8] = {0, 3, 2, 4, 1, 5, 6, 7};
static const uint8_t roundoff_232a[16] = {
0, 1, 0, 1, 0, -1, 2, 1,
0, -1, -2, -3, 4, 3, 2, 1,
};
uint32_t clk, divisor, fastclk_flag, frac, hwspeed;
/*
* If this chip has the fast clock capability and the speed is within
* range, use the 12MHz clock, otherwise the standard clock is 3MHz.
*/
if ((sc->sc_devflags & DEVF_BAUDCLK_12M) && speed >= 1200) {
clk = 12000000;
fastclk_flag = (1 << 17);
} else {
clk = 3000000;
fastclk_flag = 0;
}
/*
* Make sure the requested speed is reachable with the available clock
* and a 14-bit divisor.
*/
if (speed < (clk >> 14) || speed > clk)
return (ERANGE);
/*
* Calculate the divisor, initially yielding a fixed point number with a
* 4-bit (1/16ths) fraction, then round it to the nearest fraction the
* hardware can handle. When the integral part of the divisor is
* greater than one, the fractional part is in 1/8ths of the base clock.
* The FT8U232AM chips can handle only 0.125, 0.250, and 0.5 fractions.
* Later chips can handle all 1/8th fractions.
*
* If the integral part of the divisor is 1, a special rule applies: the
* fractional part can only be .0 or .5 (this is a limitation of the
* hardware). We handle this by truncating the fraction rather than
* rounding, because this only applies to the two fastest speeds the
* chip can achieve and rounding doesn't matter, either you've asked for
* that exact speed or you've asked for something the chip can't do.
*
* For the FT8U232AM chips, use a roundoff table to adjust the result
* to the nearest 1/8th fraction that is supported by the hardware,
* leaving a fixed-point number with a 3-bit fraction which exactly
* represents the math the hardware divider will do. For later-series
* chips that support all 8 fractional divisors, just round 16ths to
* 8ths by adding 1 and dividing by 2.
*/
divisor = (clk << 4) / speed;
if ((divisor & 0xfffffff0) == 1)
divisor &= 0xfffffff8;
else if (sc->sc_devtype == DEVT_232A)
divisor += roundoff_232a[divisor & 0x0f];
else
divisor += 1; /* Rounds odd 16ths up to next 8th. */
divisor >>= 1;
/*
* Ensure the resulting hardware speed will be within operational
* tolerance (within 3% of nominal).
*/
hwspeed = (clk << 3) / divisor;
if (!uftdi_baud_within_tolerance(hwspeed, speed))
return (ERANGE);
/*
* Re-pack the divisor into hardware format. The lower 14-bits hold the
* integral part, while the upper bits specify the fraction by indexing
* a table of fractions within the hardware which is laid out as:
* {0.0, 0.5, 0.25, 0.125, 0.325, 0.625, 0.725, 0.875}
* The A-series chips only have the first four table entries; the
* roundoff table logic above ensures that the fractional part for those
* chips will be one of the first four values.
*
* When the divisor is 1 a special encoding applies: 1.0 is encoded as
* 0.0, and 1.5 is encoded as 1.0. The rounding logic above has already
* ensured that the fraction is either .0 or .5 if the integral is 1.
*/
frac = divisor & 0x07;
divisor >>= 3;
if (divisor == 1) {
if (frac == 0)
divisor = 0; /* 1.0 becomes 0.0 */
else
frac = 0; /* 1.5 becomes 1.0 */
}
divisor |= (encoded_fraction[frac] << 14) | fastclk_flag;
cfg->baud_lobits = (uint16_t)divisor;
cfg->baud_hibits = (uint16_t)(divisor >> 16);
/*
* If this chip requires the baud bits to be in the high byte of the
* index word, move the bits up to that location.
*/
if (sc->sc_devflags & DEVF_BAUDBITS_HINDEX) {
cfg->baud_hibits <<= 8;
}
return (0);
}
static int
uftdi_set_parm_soft(struct ucom_softc *ucom, struct termios *t,
struct uftdi_param_config *cfg)
{
struct uftdi_softc *sc = ucom->sc_parent;
int err;
memset(cfg, 0, sizeof(*cfg));
if (sc->sc_devtype == DEVT_SIO)
err = uftdi_sio_encode_baudrate(sc, t->c_ospeed, cfg);
else
err = uftdi_encode_baudrate(sc, t->c_ospeed, cfg);
if (err != 0)
return (err);
if (t->c_cflag & CSTOPB)
cfg->lcr = FTDI_SIO_SET_DATA_STOP_BITS_2;
else
cfg->lcr = FTDI_SIO_SET_DATA_STOP_BITS_1;
if (t->c_cflag & PARENB) {
if (t->c_cflag & PARODD) {
cfg->lcr |= FTDI_SIO_SET_DATA_PARITY_ODD;
} else {
cfg->lcr |= FTDI_SIO_SET_DATA_PARITY_EVEN;
}
} else {
cfg->lcr |= FTDI_SIO_SET_DATA_PARITY_NONE;
}
switch (t->c_cflag & CSIZE) {
case CS5:
cfg->lcr |= FTDI_SIO_SET_DATA_BITS(5);
break;
case CS6:
cfg->lcr |= FTDI_SIO_SET_DATA_BITS(6);
break;
case CS7:
cfg->lcr |= FTDI_SIO_SET_DATA_BITS(7);
break;
case CS8:
cfg->lcr |= FTDI_SIO_SET_DATA_BITS(8);
break;
}
if (t->c_cflag & CRTSCTS) {
cfg->v_flow = FTDI_SIO_RTS_CTS_HS;
} else if (t->c_iflag & (IXON | IXOFF)) {
cfg->v_flow = FTDI_SIO_XON_XOFF_HS;
cfg->v_start = t->c_cc[VSTART];
cfg->v_stop = t->c_cc[VSTOP];
} else {
cfg->v_flow = FTDI_SIO_DISABLE_FLOW_CTRL;
}
return (0);
}
static int
uftdi_pre_param(struct ucom_softc *ucom, struct termios *t)
{
struct uftdi_param_config cfg;
DPRINTF("\n");
return (uftdi_set_parm_soft(ucom, t, &cfg));
}
static void
uftdi_cfg_param(struct ucom_softc *ucom, struct termios *t)
{
struct uftdi_softc *sc = ucom->sc_parent;
uint16_t wIndex = ucom->sc_portno;
struct uftdi_param_config cfg;
struct usb_device_request req;
if (uftdi_set_parm_soft(ucom, t, &cfg)) {
/* should not happen */
return;
}
sc->sc_last_lcr = cfg.lcr;
DPRINTF("\n");
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = FTDI_SIO_SET_BAUD_RATE;
USETW(req.wValue, cfg.baud_lobits);
USETW(req.wIndex, cfg.baud_hibits | wIndex);
USETW(req.wLength, 0);
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
&req, NULL, 0, 1000);
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = FTDI_SIO_SET_DATA;
USETW(req.wValue, cfg.lcr);
USETW(req.wIndex, wIndex);
USETW(req.wLength, 0);
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
&req, NULL, 0, 1000);
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = FTDI_SIO_SET_FLOW_CTRL;
USETW2(req.wValue, cfg.v_stop, cfg.v_start);
USETW2(req.wIndex, cfg.v_flow, wIndex);
USETW(req.wLength, 0);
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
&req, NULL, 0, 1000);
}
static void
uftdi_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr)
{
struct uftdi_softc *sc = ucom->sc_parent;
DPRINTF("msr=0x%02x lsr=0x%02x\n",
sc->sc_msr, sc->sc_lsr);
*msr = sc->sc_msr;
*lsr = sc->sc_lsr;
}
static void
uftdi_start_read(struct ucom_softc *ucom)
{
struct uftdi_softc *sc = ucom->sc_parent;
usbd_transfer_start(sc->sc_xfer[UFTDI_BULK_DT_RD]);
}
static void
uftdi_stop_read(struct ucom_softc *ucom)
{
struct uftdi_softc *sc = ucom->sc_parent;
usbd_transfer_stop(sc->sc_xfer[UFTDI_BULK_DT_RD]);
}
static void
uftdi_start_write(struct ucom_softc *ucom)
{
struct uftdi_softc *sc = ucom->sc_parent;
usbd_transfer_start(sc->sc_xfer[UFTDI_BULK_DT_WR]);
}
static void
uftdi_stop_write(struct ucom_softc *ucom)
{
struct uftdi_softc *sc = ucom->sc_parent;
usbd_transfer_stop(sc->sc_xfer[UFTDI_BULK_DT_WR]);
}
static void
uftdi_poll(struct ucom_softc *ucom)
{
struct uftdi_softc *sc = ucom->sc_parent;
usbd_transfer_poll(sc->sc_xfer, UFTDI_N_TRANSFER);
}