[PATCH] USB ftdi_sio: reduce device id table clutter

ftdi_sio: Use a single usb_device_id table and detect the type of chip
programatically.  The table also flags devices requiring special
initialization.  The patch makes the driver about 10K smaller and makes
it easier to add new device IDs.

Signed-off-by: Ian Abbott <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>

---
commit 8f977e4201fcc0bd512eb01e775894e0a9c34a39
tree cc9c0bc66267c55c2bdeeb26eac11822d7325f6f
parent 9c8d61783e5bb5e29744b6481a1c67c6e4e8e135
author Ian Abbott <[EMAIL PROTECTED]> Mon, 20 Jun 2005 16:45:42 +0100
committer Greg Kroah-Hartman <[EMAIL PROTECTED]> Tue, 12 Jul 2005 11:52:55 -0700

 drivers/usb/serial/ftdi_sio.c |  707 ++++++++---------------------------------
 1 files changed, 144 insertions(+), 563 deletions(-)

diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -264,16 +264,26 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.4.2"
+#define DRIVER_VERSION "v1.4.3"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <[EMAIL PROTECTED]>, Bill Ryder 
<[EMAIL PROTECTED]>, Kuba Ober <[EMAIL PROTECTED]>"
 #define DRIVER_DESC "USB FTDI Serial Converters Driver"
 
 static int debug;
 
-static struct usb_device_id id_table_sio [] = {
-       { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
-       { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
-       { }                                             /* Terminating entry */
+/* struct ftdi_sio_quirk is used by devices requiring special attention. */
+struct ftdi_sio_quirk {
+       void (*setup)(struct usb_serial *); /* Special settings during startup. 
*/
+};
+
+static void  ftdi_USB_UIRT_setup       (struct usb_serial *serial);
+static void  ftdi_HE_TIRA1_setup       (struct usb_serial *serial);
+
+static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
+       .setup = ftdi_USB_UIRT_setup,
+};
+
+static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
+       .setup = ftdi_HE_TIRA1_setup,
 };
 
 /*
@@ -288,237 +298,11 @@ static struct usb_device_id id_table_sio
  * the bcdDevice value is used to differentiate FT232BM and FT245BM from
  * the earlier FT8U232AM and FT8U232BM.  For now, include all known VID/PID
  * combinations in both tables.
- * FIXME: perhaps bcdDevice can also identify 12MHz devices, but I don't know
- * if those ever went into mass production. [Ian Abbott]
+ * FIXME: perhaps bcdDevice can also identify 12MHz FT8U232AM devices,
+ * but I don't know if those ever went into mass production. [Ian Abbott]
  */
 
 
-static struct usb_device_id id_table_8U232AM [] = {
-       { USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) },
-       { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
-       { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
-       { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_547_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_633_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_631_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_635_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_640_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_642_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(OCT_VID, OCT_US101_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_1, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0, 0x3ff) },
-       { USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_RM_CANVIEW_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_0_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID, 0, 0x3ff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID, 0, 0x3ff) },
-       { }                                             /* Terminating entry */
-};
-
-
-static struct usb_device_id id_table_FT232BM [] = {
-       { USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_547_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_633_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_631_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_635_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_640_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_XF_642_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_3_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_4_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_PIEGROUP_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(OCT_VID, OCT_US101_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_1, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E808_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E809_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80A_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80B_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80C_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80D_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80E_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80F_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E888_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E889_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88A_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88B_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88C_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88D_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
-       { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
-       { USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0x400, 0xffff) },
-       { USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_RM_CANVIEW_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_0_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID, 0x400, 0xffff) },
-       { }                                             /* Terminating entry */
-};
-
-
-static struct usb_device_id id_table_USB_UIRT [] = {
-       { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
-       { }                                             /* Terminating entry */
-};
-
-
-static struct usb_device_id id_table_HE_TIRA1 [] = {
-       { USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) },
-       { }                                             /* Terminating entry */
-};
-
-
-static struct usb_device_id id_table_FT2232C[] = {
-       { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
-       { }                                             /* Terminating entry */
-};
-
 
 static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
@@ -540,14 +324,14 @@ static struct usb_device_id id_table_com
        { USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) },
        { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_3_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_4_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID, 0x400, 0xffff) },
+       { USB_DEVICE(FTDI_VID, FTDI_MTXORB_0_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_MTXORB_1_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_MTXORB_2_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_MTXORB_3_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) },
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
@@ -597,35 +381,37 @@ static struct usb_device_id id_table_com
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
        { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
        { USB_DEVICE(OCT_VID, OCT_US101_PID) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) },
-       { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_HE_TIRA1_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_USB_UIRT_quirk },
        { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_1) },
        { USB_DEVICE(FTDI_VID, PROTEGO_R2X0) },
        { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) },
        { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E808_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E809_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80A_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80B_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80C_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80D_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80E_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80F_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E888_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E889_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88A_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88B_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88C_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88D_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E808_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E809_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80A_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80B_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80C_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80D_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80E_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80F_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E888_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E889_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88A_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88B_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88C_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88D_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88E_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88F_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) },
-       { USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_1_PID, 0x400, 0xffff) },
-       { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_2_PID, 0x400, 0xffff) },
+       { USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
+       { USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
+       { USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
+       { USB_DEVICE(FTDI_VID, LINX_FUTURE_1_PID) },
+       { USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
        { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
@@ -642,7 +428,7 @@ static struct usb_device_id id_table_com
        { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
        { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
-       { USB_DEVICE_VER(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID, 0x400, 0xffff) },
+       { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
        { }                                             /* Terminating entry */
 };
 
@@ -705,12 +491,8 @@ struct ftdi_private {
  ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP )
 
 /* function prototypes for a FTDI serial converter */
-static int  ftdi_SIO_startup           (struct usb_serial *serial);
-static int  ftdi_8U232AM_startup       (struct usb_serial *serial);
-static int  ftdi_FT232BM_startup       (struct usb_serial *serial);
-static int  ftdi_FT2232C_startup       (struct usb_serial *serial);
-static int  ftdi_USB_UIRT_startup      (struct usb_serial *serial);
-static int  ftdi_HE_TIRA1_startup      (struct usb_serial *serial);
+static int  ftdi_sio_probe     (struct usb_serial *serial, const struct 
usb_device_id *id);
+static int  ftdi_sio_attach            (struct usb_serial *serial);
 static void ftdi_shutdown              (struct usb_serial *serial);
 static int  ftdi_open                  (struct usb_serial_port *port, struct 
file *filp);
 static void ftdi_close                 (struct usb_serial_port *port, struct 
file *filp);
@@ -733,66 +515,16 @@ static unsigned short int ftdi_232am_bau
 static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base);
 static __u32 ftdi_232bm_baud_to_divisor (int baud);
 
-static struct usb_serial_device_type ftdi_SIO_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "FTDI SIO",
-       .id_table =             id_table_sio,
-       .num_interrupt_in =     0,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
-       .num_ports =            1,
-       .open =                 ftdi_open,
-       .close =                ftdi_close,
-       .throttle =             ftdi_throttle,
-       .unthrottle =           ftdi_unthrottle,
-       .write =                ftdi_write,
-       .write_room =           ftdi_write_room,
-       .chars_in_buffer =      ftdi_chars_in_buffer,
-       .read_bulk_callback =   ftdi_read_bulk_callback,
-       .write_bulk_callback =  ftdi_write_bulk_callback,
-       .tiocmget =             ftdi_tiocmget,
-       .tiocmset =             ftdi_tiocmset,
-       .ioctl =                ftdi_ioctl,
-       .set_termios =          ftdi_set_termios,
-       .break_ctl =            ftdi_break_ctl,
-       .attach =               ftdi_SIO_startup,
-       .shutdown =             ftdi_shutdown,
-};
-
-static struct usb_serial_device_type ftdi_8U232AM_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "FTDI 8U232AM Compatible",
-       .id_table =             id_table_8U232AM,
-       .num_interrupt_in =     0,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
-       .num_ports =            1,
-       .open =                 ftdi_open,
-       .close =                ftdi_close,
-       .throttle =             ftdi_throttle,
-       .unthrottle =           ftdi_unthrottle,
-       .write =                ftdi_write,
-       .write_room =           ftdi_write_room,
-       .chars_in_buffer =      ftdi_chars_in_buffer,
-       .read_bulk_callback =   ftdi_read_bulk_callback,
-       .write_bulk_callback =  ftdi_write_bulk_callback,
-       .tiocmget =             ftdi_tiocmget,
-       .tiocmset =             ftdi_tiocmset,
-       .ioctl =                ftdi_ioctl,
-       .set_termios =          ftdi_set_termios,
-       .break_ctl =            ftdi_break_ctl,
-       .attach =               ftdi_8U232AM_startup,
-       .shutdown =             ftdi_shutdown,
-};
-
-static struct usb_serial_device_type ftdi_FT232BM_device = {
+static struct usb_serial_device_type ftdi_sio_device = {
        .owner =                THIS_MODULE,
-       .name =                 "FTDI FT232BM Compatible",
-       .id_table =             id_table_FT232BM,
+       .name =                 "FTDI USB Serial Device",
+       .short_name =           "ftdi_sio",
+       .id_table =             id_table_combined,
        .num_interrupt_in =     0,
        .num_bulk_in =          1,
        .num_bulk_out =         1,
        .num_ports =            1,
+       .probe =                ftdi_sio_probe,
        .open =                 ftdi_open,
        .close =                ftdi_close,
        .throttle =             ftdi_throttle,
@@ -807,91 +539,10 @@ static struct usb_serial_device_type ftd
        .ioctl =                ftdi_ioctl,
        .set_termios =          ftdi_set_termios,
        .break_ctl =            ftdi_break_ctl,
-       .attach =               ftdi_FT232BM_startup,
+       .attach =               ftdi_sio_attach,
        .shutdown =             ftdi_shutdown,
 };
 
-static struct usb_serial_device_type ftdi_FT2232C_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "FTDI FT2232C Compatible",
-       .id_table =             id_table_FT2232C,
-       .num_interrupt_in =     0,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
-       .num_ports =            1,
-       .open =                 ftdi_open,
-       .close =                ftdi_close,
-       .throttle =             ftdi_throttle,
-       .unthrottle =           ftdi_unthrottle,
-       .write =                ftdi_write,
-       .write_room =           ftdi_write_room,
-       .chars_in_buffer =      ftdi_chars_in_buffer,
-       .read_bulk_callback =   ftdi_read_bulk_callback,
-       .write_bulk_callback =  ftdi_write_bulk_callback,
-       .tiocmget =             ftdi_tiocmget,
-       .tiocmset =             ftdi_tiocmset,
-       .ioctl =                ftdi_ioctl,
-       .set_termios =          ftdi_set_termios,
-       .break_ctl =            ftdi_break_ctl,
-       .attach =               ftdi_FT2232C_startup,
-       .shutdown =             ftdi_shutdown,
-};
-
-static struct usb_serial_device_type ftdi_USB_UIRT_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "USB-UIRT Infrared Tranceiver",
-       .id_table =             id_table_USB_UIRT,
-       .num_interrupt_in =     0,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
-       .num_ports =            1,
-       .open =                 ftdi_open,
-       .close =                ftdi_close,
-       .throttle =             ftdi_throttle,
-       .unthrottle =           ftdi_unthrottle,
-       .write =                ftdi_write,
-       .write_room =           ftdi_write_room,
-       .chars_in_buffer =      ftdi_chars_in_buffer,
-       .read_bulk_callback =   ftdi_read_bulk_callback,
-       .write_bulk_callback =  ftdi_write_bulk_callback,
-       .tiocmget =             ftdi_tiocmget,
-       .tiocmset =             ftdi_tiocmset,
-       .ioctl =                ftdi_ioctl,
-       .set_termios =          ftdi_set_termios,
-       .break_ctl =            ftdi_break_ctl,
-       .attach =               ftdi_USB_UIRT_startup,
-       .shutdown =             ftdi_shutdown,
-};
-
-/* The TIRA1 is based on a  FT232BM which requires a fixed baud rate of 100000
- * and which requires RTS-CTS to be enabled. */
-static struct usb_serial_device_type ftdi_HE_TIRA1_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Home-Electronics TIRA-1 IR Transceiver",
-       .id_table =             id_table_HE_TIRA1,
-       .num_interrupt_in =     0,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
-       .num_ports =            1,
-       .open =                 ftdi_open,
-       .close =                ftdi_close,
-       .throttle =             ftdi_throttle,
-       .unthrottle =           ftdi_unthrottle,
-       .write =                ftdi_write,
-       .write_room =           ftdi_write_room,
-       .chars_in_buffer =      ftdi_chars_in_buffer,
-       .read_bulk_callback =   ftdi_read_bulk_callback,
-       .write_bulk_callback =  ftdi_write_bulk_callback,
-       .tiocmget =             ftdi_tiocmget,
-       .tiocmset =             ftdi_tiocmset,
-       .ioctl =                ftdi_ioctl,
-       .set_termios =          ftdi_set_termios,
-       .break_ctl =            ftdi_break_ctl,
-       .attach =               ftdi_HE_TIRA1_startup,
-       .shutdown =             ftdi_shutdown,
-};
-
-
 
 #define WDR_TIMEOUT 5000 /* default urb timeout */
 
@@ -1212,6 +863,59 @@ check_and_exit:
 } /* set_serial_info */
 
 
+/* Determine type of FTDI chip based on USB config and descriptor. */
+static void ftdi_determine_type(struct usb_serial_port *port)
+{
+       struct ftdi_private *priv = usb_get_serial_port_data(port);
+       struct usb_serial *serial = port->serial;
+       struct usb_device *udev = serial->dev;
+       unsigned version;
+       unsigned interfaces;
+
+       /* Assume it is not the original SIO device for now. */
+       priv->baud_base = 48000000 / 16;
+       priv->write_offset = 0;
+
+       version = le16_to_cpu(udev->descriptor.bcdDevice);
+       interfaces = udev->actconfig->desc.bNumInterfaces;
+       dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __FUNCTION__,
+                       version, interfaces);
+       if (interfaces > 1) {
+               int inter;
+
+               /* Multiple interfaces.  Assume FT2232C. */
+               priv->chip_type = FT2232C;
+               /* Determine interface code. */
+               inter = serial->interface->altsetting->desc.bInterfaceNumber;
+               if (inter == 0) {
+                       priv->interface = PIT_SIOA;
+               } else {
+                       priv->interface = PIT_SIOB;
+               }
+               /* BM-type devices have a bug where bcdDevice gets set
+                * to 0x200 when iSerialNumber is 0.  */
+               if (version < 0x500) {
+                       dbg("%s: something fishy - bcdDevice too low for 
multi-interface device",
+                                       __FUNCTION__);
+               }
+       } else if (version < 0x200) {
+               /* Old device.  Assume its the original SIO. */
+               priv->chip_type = SIO;
+               priv->baud_base = 12000000 / 16;
+               priv->write_offset = 1;
+       } else if (version < 0x400) {
+               /* Assume its an FT8U232AM (or FT8U245AM) */
+               /* (It might be a BM because of the iSerialNumber bug,
+                * but it will still work as an AM device.) */
+               priv->chip_type = FT8U232AM;
+       } else {
+               /* Assume its an FT232BM (or FT245BM) */
+               priv->chip_type = FT232BM;
+       }
+       info("Detected %s", ftdi_chip_name[priv->chip_type]);
+}
+
+
 /*
  * ***************************************************************************
  * Sysfs Attribute
@@ -1355,12 +1059,20 @@ static void remove_sysfs_attrs(struct us
  * ***************************************************************************
  */
 
-/* Common startup subroutine */
-/* Called from ftdi_SIO_startup, etc. */
-static int ftdi_common_startup (struct usb_serial *serial)
+/* Probe function to check for special devices */
+static int ftdi_sio_probe (struct usb_serial *serial, const struct 
usb_device_id *id)
+{
+       usb_set_serial_data(serial, (void *)id->driver_info);
+
+       return (0);
+}
+
+/* attach subroutine */
+static int ftdi_sio_attach (struct usb_serial *serial)
 {
        struct usb_serial_port *port = serial->port[0];
        struct ftdi_private *priv;
+       struct ftdi_sio_quirk *quirk;
        
        dbg("%s",__FUNCTION__);
 
@@ -1400,150 +1112,49 @@ static int ftdi_common_startup (struct u
        port->bulk_out_buffer = NULL;
 
        usb_set_serial_port_data(serial->port[0], priv);
-       
-       return (0);
-}
-
-
-/* Startup for the SIO chip */
-/* Called from usbserial:serial_probe */
-static int ftdi_SIO_startup (struct usb_serial *serial)
-{
-       struct ftdi_private *priv;
-       int err;
 
-       dbg("%s",__FUNCTION__);
-
-       err = ftdi_common_startup(serial);
-       if (err){
-               return (err);
-       }
-
-       priv = usb_get_serial_port_data(serial->port[0]);
-       priv->chip_type = SIO;
-       priv->baud_base = 12000000 / 16;
-       priv->write_offset = 1;
-       
-       return (0);
-}
-
-/* Startup for the 8U232AM chip */
-/* Called from usbserial:serial_probe */
-static int ftdi_8U232AM_startup (struct usb_serial *serial)
-{ /* ftdi_8U232AM_startup */
-       struct ftdi_private *priv;
-       int err;
-
-       dbg("%s",__FUNCTION__);
-       err = ftdi_common_startup(serial);
-       if (err){
-               return (err);
-       }
-
-       priv = usb_get_serial_port_data(serial->port[0]);
-       priv->chip_type = FT8U232AM;
-       priv->baud_base = 48000000 / 2; /* Would be / 16, but FTDI supports 
0.125, 0.25 and 0.5 divisor fractions! */
-       
+       ftdi_determine_type (serial->port[0]);
        create_sysfs_attrs(serial);
-       
-       return (0);
-} /* ftdi_8U232AM_startup */
 
-/* Startup for the FT232BM chip */
-/* Called from usbserial:serial_probe */
-static int ftdi_FT232BM_startup (struct usb_serial *serial)
-{ /* ftdi_FT232BM_startup */
-       struct ftdi_private *priv;
-       int err;
-
-       dbg("%s",__FUNCTION__);
-       err = ftdi_common_startup(serial);
-       if (err){
-               return (err);
+       /* Check for device requiring special set up. */
+       quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial);
+       if (quirk && quirk->setup) {
+               quirk->setup(serial);
        }
-
-       priv = usb_get_serial_port_data(serial->port[0]);
-       priv->chip_type = FT232BM;
-       priv->baud_base = 48000000 / 2; /* Would be / 16, but FT232BM supports 
multiple of 0.125 divisor fractions! */
        
-       create_sysfs_attrs(serial);
-
        return (0);
-} /* ftdi_FT232BM_startup */
+} /* ftdi_sio_attach */
 
-/* Startup for the FT2232C chip */
-/* Called from usbserial:serial_probe */
-static int ftdi_FT2232C_startup (struct usb_serial *serial)
-{ /* ftdi_FT2232C_startup */
-       struct ftdi_private *priv;
-       int err;
-       int inter;
-
-       dbg("%s",__FUNCTION__);
-       err = ftdi_common_startup(serial);
-       if (err){
-               return (err);
-       }
-
-       priv = usb_get_serial_port_data(serial->port[0]);
-       priv->chip_type = FT2232C;
-       inter = serial->interface->altsetting->desc.bInterfaceNumber;
-
-       if (inter) {
-               priv->interface = PIT_SIOB;
-       }
-       else  {
-               priv->interface = PIT_SIOA;
-       }
-       priv->baud_base = 48000000 / 2; /* Would be / 16, but FT2232C supports 
multiple of 0.125 divisor fractions! */
-       
-       create_sysfs_attrs(serial);
-
-       return (0);
-} /* ftdi_FT2232C_startup */
 
-/* Startup for the USB-UIRT device, which requires hardwired baudrate (38400 
gets mapped to 312500) */
+/* Setup for the USB-UIRT device, which requires hardwired
+ * baudrate (38400 gets mapped to 312500) */
 /* Called from usbserial:serial_probe */
-static int ftdi_USB_UIRT_startup (struct usb_serial *serial)
-{ /* ftdi_USB_UIRT_startup */
+static void ftdi_USB_UIRT_setup (struct usb_serial *serial)
+{
        struct ftdi_private *priv;
-       int err;
 
        dbg("%s",__FUNCTION__);
-       err = ftdi_8U232AM_startup(serial);
-       if (err){
-               return (err);
-       }
 
        priv = usb_get_serial_port_data(serial->port[0]);
        priv->flags |= ASYNC_SPD_CUST;
        priv->custom_divisor = 77;
        priv->force_baud = B38400;
-       
-       return (0);
-} /* ftdi_USB_UIRT_startup */
+} /* ftdi_USB_UIRT_setup */
 
-/* Startup for the HE-TIRA1 device, which requires hardwired
- * baudrate (38400 gets mapped to 100000) */
-static int ftdi_HE_TIRA1_startup (struct usb_serial *serial)
-{ /* ftdi_HE_TIRA1_startup */
+/* Setup for the HE-TIRA1 device, which requires hardwired
+ * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled.  */
+static void ftdi_HE_TIRA1_setup (struct usb_serial *serial)
+{
        struct ftdi_private *priv;
-       int err;
 
        dbg("%s",__FUNCTION__);
-       err = ftdi_FT232BM_startup(serial);
-       if (err){
-               return (err);
-       }
 
        priv = usb_get_serial_port_data(serial->port[0]);
        priv->flags |= ASYNC_SPD_CUST;
        priv->custom_divisor = 240;
        priv->force_baud = B38400;
        priv->force_rtscts = 1;
-       
-       return (0);
-} /* ftdi_HE_TIRA1_startup */
+} /* ftdi_HE_TIRA1_setup */
 
 
 /* ftdi_shutdown is called from usbserial:usb_serial_disconnect 
@@ -2516,24 +2127,9 @@ static int __init ftdi_init (void)
        int retval;
 
        dbg("%s", __FUNCTION__);
-       retval = usb_serial_register(&ftdi_SIO_device);
-       if (retval)
-               goto failed_SIO_register;
-       retval = usb_serial_register(&ftdi_8U232AM_device);
-       if (retval)
-               goto failed_8U232AM_register;
-       retval = usb_serial_register(&ftdi_FT232BM_device);
-       if (retval)
-               goto failed_FT232BM_register;
-       retval = usb_serial_register(&ftdi_FT2232C_device);
-       if (retval)
-               goto failed_FT2232C_register;
-       retval = usb_serial_register(&ftdi_USB_UIRT_device);
-       if (retval)
-               goto failed_USB_UIRT_register;
-       retval = usb_serial_register(&ftdi_HE_TIRA1_device);
+       retval = usb_serial_register(&ftdi_sio_device);
        if (retval)
-               goto failed_HE_TIRA1_register;
+               goto failed_sio_register;
        retval = usb_register(&ftdi_driver);
        if (retval) 
                goto failed_usb_register;
@@ -2541,18 +2137,8 @@ static int __init ftdi_init (void)
        info(DRIVER_VERSION ":" DRIVER_DESC);
        return 0;
 failed_usb_register:
-       usb_serial_deregister(&ftdi_HE_TIRA1_device);
-failed_HE_TIRA1_register:
-       usb_serial_deregister(&ftdi_USB_UIRT_device);
-failed_USB_UIRT_register:
-       usb_serial_deregister(&ftdi_FT2232C_device);
-failed_FT2232C_register:
-       usb_serial_deregister(&ftdi_FT232BM_device);
-failed_FT232BM_register:
-       usb_serial_deregister(&ftdi_8U232AM_device);
-failed_8U232AM_register:
-       usb_serial_deregister(&ftdi_SIO_device);
-failed_SIO_register:
+       usb_serial_deregister(&ftdi_sio_device);
+failed_sio_register:
        return retval;
 }
 
@@ -2563,12 +2149,7 @@ static void __exit ftdi_exit (void)
        dbg("%s", __FUNCTION__);
 
        usb_deregister (&ftdi_driver);
-       usb_serial_deregister (&ftdi_HE_TIRA1_device);
-       usb_serial_deregister (&ftdi_USB_UIRT_device);
-       usb_serial_deregister (&ftdi_FT2232C_device);
-       usb_serial_deregister (&ftdi_FT232BM_device);
-       usb_serial_deregister (&ftdi_8U232AM_device);
-       usb_serial_deregister (&ftdi_SIO_device);
+       usb_serial_deregister (&ftdi_sio_device);
 
 }
 



-------------------------------------------------------
This SF.Net email is sponsored by the 'Do More With Dual!' webinar happening
July 14 at 8am PDT/11am EDT. We invite you to explore the latest in dual
core and dual graphics technology at this free one hour event hosted by HP,
AMD, and NVIDIA.  To register visit http://www.hp.com/go/dualwebinar
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to