/*
 * USB FTDI SIO driver
 *
 * 	Copyright (C) 1999 - 2001
 * 	    Greg Kroah-Hartman (greg@kroah.com)
 *          Bill Ryder (bryder@sgi.com)
 *	Copyright (C) 2002
 *	    Kuba Ober (kuba@mareimbrium.org)
 *
 * 	This program is free software; you can redistribute it and/or modify
 * 	it under the terms of the GNU General Public License as published by
 * 	the Free Software Foundation; either version 2 of the License, or
 * 	(at your option) any later version.
 *
 * See Documentation/usb/usb-serial.txt for more information on using this driver
 *
 * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
 *	and extra documentation
 *
 * (2/Feb/2006) ST
 *      Added support for the 232R chip.
 *
 * (10/Mar/2004) Jan Capek
 *      Added PID's for ICD-U20/ICD-U40 - incircuit PIC debuggers from CCS Inc.
 *
 * (09/Feb/2004) Ian Abbott
 *      Changed full name of USB-UIRT device to avoid "/" character.
 *      Added FTDI's alternate PID (0x6006) for FT232/245 devices.
 *      Added PID for "ELV USB Module UO100" from Stefan Frings.
 * 
 * (21/Oct/2003) Ian Abbott
 *      Renamed some VID/PID macros for Matrix Orbital and Perle Systems
 *      devices.  Removed Matrix Orbital and Perle Systems devices from the
 *      8U232AM device table, but left them in the FT232BM table, as they are
 *      known to use only FT232BM.
 *
 * (17/Oct/2003) Scott Allen
 *      Added vid/pid for Perle Systems UltraPort USB serial converters
 *
 * (21/Sep/2003) Ian Abbott
 *      Added VID/PID for Omnidirectional Control Technology US101 USB to
 *      RS-232 adapter (also rebadged as Dick Smith Electronics XH6381).
 *      VID/PID supplied by Donald Gordon.
 *
 * (19/Aug/2003) Ian Abbott
 *      Omitted some paranoid checks in write bulk callback that don't matter.
 *
 * (05/Aug/2003) Ian Abbott
 *      Added VID/PID for ID TECH IDT1221U USB to RS-232 adapter.
 *      VID/PID provided by Steve Briggs.
 *
 * (23/Jul/2003) Ian Abbott
 *      Added PIDs for CrystalFontz 547, 633, 631, 635, 640 and 640 from
 *      Wayne Wylupski.
 *
 * (10/Jul/2003) David Glance
 *      Added PID for DSS-20 SyncStation cradle for Sony-Ericsson P800.
 *
 * (23/Jun/2003) Ian Abbott
 *      Reduced flip buffer pushes and corrected a data length test in
 *      ftdi_read_bulk_callback.
 *      Defererence pointers after any paranoid checks, not before.
 *
 * (21/Jun/2003) Erik Nygren
 *      Added support for Home Electronics Tira-1 IR tranceiver using FT232BM chip.
 *      See <http://www.home-electro.com/tira1.htm>.  Only operates properly 
 *      at 100000 and RTS-CTS, so set custom divisor mode on startup.
 *      Also force the Tira-1 and USB-UIRT to only use their custom baud rates.
 *
 * (18/Jun/2003) Ian Abbott
 *      Added Device ID of the USB relais from Rudolf Gugler (backported from
 *      Philipp Gühring's patch for 2.5.x kernel).
 *      Moved read transfer buffer reallocation into startup function.
 *      Free existing write urb and transfer buffer in startup function.
 *      Only use urbs in write urb pool that were successfully allocated.
 *      Moved some constant macros out of functions.
 *      Minor whitespace and comment changes.
 *
 * (12/Jun/2003) David Norwood
 *      Added support for USB-UIRT IR tranceiver using 8U232AM chip.
 *      See <http://home.earthlink.net/~jrhees/USBUIRT/index.htm>.  Only
 *      operates properly at 312500, so set custom divisor mode on startup.
 *
 * (12/Jun/2003) Ian Abbott
 *      Added Sealevel SeaLINK+ 210x, 220x, 240x, 280x vid/pids from Tuan Hoang
 *      - I've eliminated some that don't seem to exist!
 *      Added Home Electronics Tira-1 IR transceiver pid from Chris Horn
 *      Some whitespace/coding-style cleanups
 *
 * (11/Jun/2003) Ian Abbott
 *      Fixed unsafe spinlock usage in ftdi_write
 *
 * (24/Feb/2003) Richard Shooter
 *      Increase read buffer size to improve read speeds at higher baud rates
 *      (specifically tested with up to 1Mb/sec at 1.5M baud)
 *
 * (23/Feb/2003) John Wilkins
 *      Added Xon/xoff flow control (activating support in the ftdi device)
 *      Added vid/pid for Videonetworks/Homechoice (UK ISP)
 *
 * (23/Feb/2003) Bill Ryder
 *      Added matrix orb device vid/pids from Wayne Wylupski
 *
 * (19/Feb/2003) Ian Abbott
 *      For TIOCSSERIAL, set alt_speed to 0 when ASYNC_SPD_MASK value has
 *      changed to something other than ASYNC_SPD_HI, ASYNC_SPD_VHI,
 *      ASYNC_SPD_SHI or ASYNC_SPD_WARP.  Also, unless ASYNC_SPD_CUST is in
 *      force, don't bother changing baud rate when custom_divisor has changed.
 *
 * (18/Feb/2003) Ian Abbott
 *      Fixed TIOCMGET handling to include state of DTR and RTS, the state
 *      of which are now saved by set_dtr() and set_rts().
 *      Fixed improper storage class for buf in set_dtr() and set_rts().
 *      Added FT232BM chip type and support for its extra baud rates (compared
 *      to FT8U232AM).
 *      Took account of special case divisor values for highest baud rates of
 *      FT8U232AM and FT232BM.
 *      For TIOCSSERIAL, forced alt_speed to 0 when ASYNC_SPD_CUST kludge used,
 *      as previous alt_speed setting is now stale.
 *      Moved startup code common between the startup routines for the
 *      different chip types into a common subroutine.
 *
 * (17/Feb/2003) Bill Ryder
 *      Added write urb buffer pool on a per device basis
 *      Added more checking for open file on callbacks (fixed OOPS)
 *      Added CrystalFontz 632 and 634 PIDs 
 *         (thanx to CrystalFontz for the sample devices - they flushed out
 *           some driver bugs)
 *      Minor debugging message changes
 *      Added throttle, unthrottle and chars_in_buffer functions
 *      Fixed FTDI_SIO (the original device) bug
 *      Fixed some shutdown handling
 *      
 * 
 * 
 * 
 * (07/Jun/2002) Kuba Ober
 *	Changed FTDI_SIO_BASE_BAUD_TO_DIVISOR macro into ftdi_baud_to_divisor
 *	function. It was getting too complex.
 *	Fix the divisor calculation logic which was setting divisor of 0.125
 *	instead of 0.5 for fractional parts of divisor equal to 5/8, 6/8, 7/8.
 *	Also make it bump up the divisor to next integer in case of 7/8 - it's
 *	a better approximation.
 *
 * (25/Jul/2002) Bill Ryder inserted Dmitri's TIOCMIWAIT patch
 *      Not tested by me but it doesn't break anything I use.
 * 
 * (04/Jan/2002) Kuba Ober
 *	Implemented 38400 baudrate kludge, where it can be substituted with other
 *	  values. That's the only way to set custom baudrates.
 *	Implemented TIOCSSERIAL, TIOCGSERIAL ioctl's so that setserial is happy.
 *	FIXME: both baudrate things should eventually go to usbserial.c as other
 *	  devices may need that functionality too. Actually, it can probably be
 *	  merged in serial.c somehow - too many drivers repeat this code over
 *	  and over.
 *	Fixed baudrate forgetfulness - open() used to reset baudrate to 9600 every time.
 *	Divisors for baudrates are calculated by a macro.
 *	Small code cleanups. Ugly whitespace changes for Plato's sake only ;-].
 *
 * (04/Nov/2001) Bill Ryder
 *	Fixed bug in read_bulk_callback where incorrect urb buffer was used.
 *	Cleaned up write offset calculation
 *	Added write_room since default values can be incorrect for sio
 *	Changed write_bulk_callback to use same queue_task as other drivers
 *        (the previous version caused panics)
 *	Removed port iteration code since the device only has one I/O port and it
 *	  was wrong anyway.
 * 
 * (31/May/2001) gkh
 *	Switched from using spinlock to a semaphore, which fixes lots of problems.
 *
 * (23/May/2001)   Bill Ryder
 *	Added runtime debug patch (thanx Tyson D Sawyer).
 *	Cleaned up comments for 8U232
 *	Added parity, framing and overrun error handling
 *	Added receive break handling.
 * 
 * (04/08/2001) gb
 *	Identify version on module load.
 *       
 * (18/March/2001) Bill Ryder
 *	(Not released)
 *	Added send break handling. (requires kernel patch too)
 *	Fixed 8U232AM hardware RTS/CTS etc status reporting.
 *	Added flipbuf fix copied from generic device
 * 
 * (12/3/2000) Bill Ryder
 *	Added support for 8U232AM device.
 *	Moved PID and VIDs into header file only.
 *	Turned on low-latency for the tty (device will do high baudrates)
 *	Added shutdown routine to close files when device removed.
 *	More debug and error message cleanups.
 *
 * (11/13/2000) Bill Ryder
 *	Added spinlock protected open code and close code.
 *	Multiple opens work (sort of - see webpage mentioned above).
 *	Cleaned up comments. Removed multiple PID/VID definitions.
 *	Factorised cts/dtr code
 *	Made use of __FUNCTION__ in dbg's
 *      
 * (11/01/2000) Adam J. Richter
 *	usb_device_id table support
 * 
 * (10/05/2000) gkh
 *	Fixed bug with urb->dev not being set properly, now that the usb
 *	core needs it.
 * 
 * (09/11/2000) gkh
 *	Removed DEBUG #ifdefs with call to usb_serial_debug_data
 *
 * (07/19/2000) gkh
 *	Added module_init and module_exit functions to handle the fact that this
 *	driver is a loadable module now.
 *
 * (04/04/2000) Bill Ryder 
 *	Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
 *        handled elsewhere in the tty io driver chain).
 *
 * (03/30/2000) Bill Ryder 
 *	Implemented lots of ioctls
 *	Fixed a race condition in write
 *	Changed some dbg's to errs
 *
 * (03/26/2000) gkh
 *	Split driver up into device specific pieces.
 *
 */

/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
/* Thanx to FTDI for so kindly providing details of the protocol required */
/*   to talk to the device */
/* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */

#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
#include <linux/serial.h>
#ifdef CONFIG_USB_SERIAL_DEBUG
	static int debug = 1;
#else
	static int debug;
#endif

#include "usb-serial.h"
#include "ftdi_sio.h"

/*
 * Version Information
 */
#define DRIVER_VERSION "v1.3.5r1"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
#define DRIVER_DESC "USB FTDI Serial Converters Driver"

static struct usb_device_id id_table_sio [] = {
	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
	{ }						/* Terminating entry */
};

/*
 * The 8U232AM has the same API as the sio except for:
 * - it can support MUCH higher baudrates; up to:
 *   o 921600 for RS232 and 2000000 for RS422/485 at 48MHz
 *   o 230400 at 12MHz
 *   so .. 8U232AM's baudrate setting codes are different
 * - it has a two byte status code.
 * - it returns characters every 16ms (the FTDI does it every 40ms)
 *
 * 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]
 */


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) },
	{ }						/* 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) },
	{ }						/* Terminating entry */
};

static struct usb_device_id id_table_FT2232C[] = {
	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U2232C_PID, 0x500, 0xffff) },
	{ }						/* Terminating entry */
};

static struct usb_device_id id_table_FT232R[] = {
	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x600, 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_userdev [] = {
	{ USB_DEVICE(-1, -1) },
	{ }						/* Terminating entry */
};


static __devinitdata struct usb_device_id id_table_combined [] = {
	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_XF_633_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_XF_631_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_XF_635_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_XF_640_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_XF_642_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) },
	{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) },
	{ 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_PIEGROUP_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_2_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_1_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_2_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_1_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_2_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_3_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_4_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_1_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_2_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_3_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_4_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_1_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_2_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_3_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_4_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_1_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_2_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_3_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_4_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_5_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_6_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_7_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_8_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_1_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_2_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_3_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_4_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_5_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_6_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_7_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_8_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_1_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_2_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_3_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_4_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_5_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
	{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
	{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
	{ USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) },
	{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
	{ 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_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, FTDI_CCSICDU20_0_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
	{ USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
	{ USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
	{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
	{ USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) },
	{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
	{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
	{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
	{ USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) },
	{ }						/* Terminating entry */
};

MODULE_DEVICE_TABLE (usb, id_table_combined);


/* constants which set the number of write urb buffers */
#define NUM_URBS			32
/* Don't be tempted to increase this buffer to > 64 ! I tried it and it doesn't work */
#define URB_TRANSFER_BUFFER_SIZE	64 /* the device's max packet size */

/* Constant for read urb */
#define BUFSZ 512
#define PKTSZ 64

static int vendor =-1, product = -1, baud_base = 48000000/2; 
    /* User specified VID and Product ID and baud base.  */ 


struct ftdi_private {
	ftdi_chip_type_t chip_type;
				/* type of the device, either SIO or FT8U232AM */
	int baud_base;		/* baud base clock for divisor setting */
	int custom_divisor;	/* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
	__u16 last_set_data_urb_value ;
				/* the last data state set - needed for doing a break */
        int write_offset;       /* This is the offset in the usb data block to write the serial data - 
				 * it is different between devices
				 */
	int flags;		/* some ASYNC_xxxx flags are supported */
	unsigned long last_dtr_rts;	/* saved modem control outputs */
        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
 	char prev_status, diff_status;        /* Used for TIOCMIWAIT */
	__u16 interface;		/* FT2232C */

	struct urb	*write_urb_pool[NUM_URBS];
	spinlock_t	write_urb_pool_lock;

	int force_baud;		/* if non-zero, force the baud rate to this value */
	int force_rtscts;	/* if non-zero, force RTS-CTS to always be enabled */
};

/* Used for TIOCMIWAIT */
#define FTDI_STATUS_B0_MASK	(FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
#define FTDI_STATUS_B1_MASK	(FTDI_RS_BI)
/* End TIOCMIWAIT */

#define FTDI_IMPL_ASYNC_FLAGS = ( ASYNC_SPD_HI | ASYNC_SPD_VHI \
 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_FT232R_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_userdev_startup	(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);
static int  ftdi_write			(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
static int  ftdi_write_room		(struct usb_serial_port *port);
static int  ftdi_chars_in_buffer	(struct usb_serial_port *port);
static void ftdi_write_bulk_callback	(struct urb *urb);
static void ftdi_read_bulk_callback	(struct urb *urb);
static void ftdi_set_termios		(struct usb_serial_port *port, struct termios * old);
static int  ftdi_ioctl			(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
static void ftdi_break_ctl		(struct usb_serial_port *port, int break_state );
static void ftdi_throttle		(struct usb_serial_port *port);
static void ftdi_unthrottle		(struct usb_serial_port *port);

static unsigned short int ftdi_232am_baud_base_to_divisor (int baud, int base);
static unsigned short int ftdi_232am_baud_to_divisor (int baud);
static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base);
static __u32 ftdi_232bm_baud_to_divisor (int baud);

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,
	.ioctl =		ftdi_ioctl,
	.set_termios =		ftdi_set_termios,
	.break_ctl =		ftdi_break_ctl,
	.startup =		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,
	.ioctl =		ftdi_ioctl,
	.set_termios =		ftdi_set_termios,
	.break_ctl =		ftdi_break_ctl,
	.startup =		ftdi_8U232AM_startup,
	.shutdown =		ftdi_shutdown,
};

static struct usb_serial_device_type ftdi_FT232BM_device = {
	.owner =		THIS_MODULE,
	.name =			"FTDI FT232BM Compatible",
	.id_table =		id_table_FT232BM,
	.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,
	.ioctl =		ftdi_ioctl,
	.set_termios =		ftdi_set_termios,
	.break_ctl =		ftdi_break_ctl,
	.startup =		ftdi_FT232BM_startup,
	.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,
	.ioctl =		ftdi_ioctl,
	.set_termios =		ftdi_set_termios,
	.break_ctl =		ftdi_break_ctl,
	.startup =		ftdi_FT2232C_startup,
	.shutdown =		ftdi_shutdown,
};

static struct usb_serial_device_type ftdi_FT232R_device = {
	.owner =		THIS_MODULE,
	.name =			"FTDI FT232R Compatible",
	.id_table =		id_table_FT232R,
	.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,
	.ioctl =		ftdi_ioctl,
	.set_termios =		ftdi_set_termios,
	.break_ctl =		ftdi_break_ctl,
	.startup =		ftdi_FT232R_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,
	.ioctl =		ftdi_ioctl,
	.set_termios =		ftdi_set_termios,
	.break_ctl =		ftdi_break_ctl,
	.startup =		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,
	.ioctl =		ftdi_ioctl,
	.set_termios =		ftdi_set_termios,
	.break_ctl =		ftdi_break_ctl,
	.startup =		ftdi_HE_TIRA1_startup,
	.shutdown =		ftdi_shutdown,
};


static struct usb_serial_device_type ftdi_userdev_device = {
	.owner =		THIS_MODULE,
	.name =			"FTDI SIO compatible",
	.id_table =		id_table_userdev,
	.num_interrupt_in =	0,
	.num_bulk_in =		1,
	.num_bulk_out =		1,
	.num_ports =		1,
	.open =			ftdi_open,
	.close =		ftdi_close,
	.write =		ftdi_write,
	.write_room =		ftdi_write_room,
	.read_bulk_callback =	ftdi_read_bulk_callback,
	.write_bulk_callback =	ftdi_write_bulk_callback,
	.ioctl =		ftdi_ioctl,
	.set_termios =		ftdi_set_termios,
	.break_ctl =		ftdi_break_ctl,
	.startup =		ftdi_userdev_startup,
	.shutdown =		ftdi_shutdown,
};

#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */

/* High and low are for DTR, RTS etc etc */
#define HIGH 1
#define LOW 0

/*
 * ***************************************************************************
 * Utlity functions
 * ***************************************************************************
 */

static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base)
{
	unsigned short int divisor;
	int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
	if ((divisor3 & 0x7) == 7) divisor3 ++; // round x.7/8 up to x+1
	divisor = divisor3 >> 3;
	divisor3 &= 0x7;
	if (divisor3 == 1) divisor |= 0xc000; else // 0.125
	if (divisor3 >= 4) divisor |= 0x4000; else // 0.5
	if (divisor3 != 0) divisor |= 0x8000;      // 0.25
	if (divisor == 1) divisor = 0;	/* special case for maximum baud rate */
	return divisor;
}

static unsigned short int ftdi_232am_baud_to_divisor(int baud)
{
	 return(ftdi_232am_baud_base_to_divisor(baud, 48000000));
}

static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base)
{
	static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
	__u32 divisor;
	int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
	divisor = divisor3 >> 3;
	divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
	/* Deal with special cases for highest baud rates. */
	if (divisor == 1) divisor = 0; else	// 1.0
	if (divisor == 0x4001) divisor = 1;	// 1.5
	return divisor;
}

static __u32 ftdi_232bm_baud_to_divisor(int baud)
{
	 return(ftdi_232bm_baud_base_to_divisor(baud, 48000000));
}

static int set_rts(struct usb_serial_port *port, int high_or_low)
{
	struct ftdi_private * priv = (struct ftdi_private *)port->private;
	char buf[1];
	unsigned ftdi_high_or_low;
	if (high_or_low) {
		ftdi_high_or_low = FTDI_SIO_SET_RTS_HIGH;
		priv->last_dtr_rts |= TIOCM_RTS;
	} else {
		ftdi_high_or_low = FTDI_SIO_SET_RTS_LOW;
		priv->last_dtr_rts &= ~TIOCM_RTS;
	}
	return(usb_control_msg(port->serial->dev,
			       usb_sndctrlpipe(port->serial->dev, 0),
			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
			       ftdi_high_or_low, priv->interface, 
			       buf, 0, WDR_TIMEOUT));
}


static int set_dtr(struct usb_serial_port *port, int high_or_low)
{
	struct ftdi_private * priv = (struct ftdi_private *)port->private;
	char buf[1];
	unsigned ftdi_high_or_low;
	if (high_or_low) {
		ftdi_high_or_low = FTDI_SIO_SET_DTR_HIGH;
		priv->last_dtr_rts |= TIOCM_DTR;
	} else {
		ftdi_high_or_low = FTDI_SIO_SET_DTR_LOW;
		priv->last_dtr_rts &= ~TIOCM_DTR;
	}
	return(usb_control_msg(port->serial->dev,
			       usb_sndctrlpipe(port->serial->dev, 0),
			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
			       ftdi_high_or_low, priv->interface, 
			       buf, 0, WDR_TIMEOUT));
}


static __u32 get_ftdi_divisor(struct usb_serial_port * port);


static int change_speed(struct usb_serial_port *port)
{
	char buf[1];
	struct ftdi_private * priv = (struct ftdi_private *)port->private;
        __u16 urb_value;
	__u16 urb_index;
	__u32 urb_index_value;

	urb_index_value = get_ftdi_divisor(port);
	urb_value = (__u16)urb_index_value;

	if(priv->chip_type == FT2232C) {
		urb_index = (__u16)(urb_index_value >> 8);
		urb_index &= 0xFF00;
		urb_index |= priv->interface;
	} else {
		urb_index = (__u16)(urb_index_value >> 16);
		urb_index |= priv->interface;
	}	
	
	return (usb_control_msg(port->serial->dev,
			    usb_sndctrlpipe(port->serial->dev, 0),
			    FTDI_SIO_SET_BAUDRATE_REQUEST,
			    FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
			    urb_value, urb_index,
			    buf, 0, 100) < 0);
}


static __u32 get_ftdi_divisor(struct usb_serial_port * port)
{ /* get_ftdi_divisor */
	
	struct ftdi_private * priv = (struct ftdi_private *)port->private;
	__u32 div_value = 0;
	int div_okay = 1;
	char *chip_name = "";
	int baud;

	/*
	 * The logic involved in setting the baudrate can be cleanly split in 3 steps.
	 * Obtaining the actual baud rate is a little tricky since unix traditionally
	 * somehow ignored the possibility to set non-standard baud rates.
	 * 1. Standard baud rates are set in tty->termios->c_cflag
	 * 2. If these are not enough, you can set any speed using alt_speed as follows:
	 *    - set tty->termios->c_cflag speed to B38400
	 *    - set your real speed in tty->alt_speed; it gets ignored when
	 *      alt_speed==0, (or)
	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
	 *      flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], this just
	 *      sets alt_speed to (HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800)
	 * ** Steps 1, 2 are done courtesy of tty_get_baud_rate
	 * 3. You can also set baud rate by setting custom divisor as follows
	 *    - set tty->termios->c_cflag speed to B38400
	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
	 *      o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
	 *      o custom_divisor set to baud_base / your_new_baudrate
	 * ** Step 3 is done courtesy of code borrowed from serial.c - I should really
	 *    spend some time and separate+move this common code to serial.c, it is
	 *    replicated in nearly every serial driver you see.
	 */

	/* 1. Get the baud rate from the tty settings, this observes alt_speed m_baud_to_divisor(int baud)B38 =te
	 * 3. You can ev, 0),e
	= prdbg("%sly
e
	 * 3. You can earln =		diviso%d",divFUNCl wN__,struct usaud notOd m_ba   ync-d_table =	set to baud_baser(in   pdustomleanly sce Ra brea baud {
	)B38 == all T &&
) < 0( == FT2D_MASK == ASYNC_SPD_CU)ST
	 *      o cust) &&
) < 0  == FT22t to baud_bas)= (__u)B38 =t== FT2_new_baudrat== FT22t to baud_bas pridbg("%sly
s follows
	 *  %dto (HIs value */
	i%d",divFUNCl wN__,s== FT22t to baud_bas,struct uontsaud setCic intomleanly s
	ier =		-d Produc ruct ftdi_pud {
	!truct )B38 =t9, S;rivaialch == FT2232C) {
	= (__ baud_RE:isor
	.id32Cdi_pr		int baud;

	 =		 priaialch truct (__u baud300:	int div_okay;

#deio_b3
	ifrtup ;__u baud600:	int div_okay;

#deio_b6
	ifrtup ;__u baud1200:	int div_okay;

#deio_b1200ifrtup ;__u baud2400:	int div_okay;

#deio_b2400ifrtup ;__u baudtati:	int div_okay;

#deio_btatiifrtup ;__u baud9600:	int div_okay;

#deio_b96
	ifrtup ;__u baud19200:	int div_okay;

#deio_b19200ifrtup ;__u baudall T:	int div_okay;

#deio_b38400ifrtup ;__u baud00, S:	int div_okay;

#deio_b00, S; frtup ;__u baud100, W:	int div_okay;

#deio_b100, Wifrtup ;__u} ck for di_pr	x4001)  div_oka0x800{rb_	ridbg("%sly
Bleanly s(%ct  to esery ss can signed lo",divFUNCl wN__,sstruct uo		int div_okay;

#deio_b96
	iuo		int *chip_n	iuo	}__u)tup ;__ baudt baud_ba:isorle",
	.id32Cdi_pr		int baud;

	t baud_ba	 pri {
	)B38 <=d300c int (__u	int div_okay;

#dvisor(int baud)
{
	 retruct uo	ndex = (__                dbg("%sly
Blealue */
	o	stru!",divFUNCl wN__t uo		int div_okay;

#dvisor(int baud)
{
	 re96
	)iuo		int *chip_n	iuo	}__u)tup ;__ baudt ires :isorquires ad32Cdi_pr baudt idex :isorqui,
	.id32Cdi_pr baudt i32R:isorquireRid32Cdi_pr	 {
	== FT2232C) {
		urb_inreRt (__u		int baud;

	t nreR" uo	ndex =  {
	== FT2232C) {
		urb_index = (__u		int baud;

	t ndex " uo	ndex = (__u		int baud;

	t nreBa	 pri}pri {
	)B38 <=d300c int (__u	int div_okay;

#dvisor(int baud)
{
	 retruct uo	ndex = (__                dbg("%sly
Blealue */
	o	stru!",divFUNCl wN__t uo		int div_okay;

#dvisor(int baud)
{
	 re96
	)iuo		int *chip_n	iuo	}__u)tup ;__} ck == FT2232C) {
		i_pud {
	int *chit (__udbg("%sly
Blealue */ / your%dt01) divis0x%lX)hichd32Cd%s" 100)ivFUNCl wN__,struccalg);
static vo)int div_o, 	int baudt uontsaol_msg(int div_ot set_dtr(struct u* 3.et as finfoal_port * port)
{ /* get_ftdi_file, unset as followst_fol_info_private * priv = (struct ftdi_private *)port->private*) __u32 div_value le, unset as followsttmp;pud {
	!ol_info_p	trol_msg-EFAULTue mem / (&tmp}


stantof(tmp_u32	tmp.D_MASK=t== FT2ASYNC_2	tmp.0000/2; 
   == FT2_new_baud_2	tmp.et to baud_base=t== FT22t to baud_bas pr {
	copybaud
	.s(ol_info, &tmp}
tantof(*ol_info_)_p	trol_msg-EFAULTue rol_msg	iu}isor */
et as finfo	i_pudtr(struct usb_set as finfoal_port * port)
{ /* get_ftdi_file, unset as followst_f **info_prisors*/
et as finfo	i_pvate * priv = (struct ftdi_private *)port->private;
	 __u32 div_value le, unset as followst ** et as rivate * priv = (structold= (st;pud {
	copyb unsigned(& ** et as ,f **info}
tantof( ** et as _)_p	trol_msg-EFAULTue old= (stpri ftdi_ usaud Do eal.r 	ieck foll thpspeessiichd3eck foli_pud {
	!capnum_(CAP_SYS_ADMIN)= (__u0x7) ( ** et as .D_MASK =~ *    USRPD_CU)S!=
	) < 0  == FT2D_MASK =~ *    USRPD_CU))_p	ttrol_msg-EPERMtr_rts &= D_MASK=t( == FT2D_MASK =~ *    USRPD_CU)S|0, WDR_TIME( ** et as .D_MASK = *    USRPD_CU))tr_rts &= et to baud_base=t ** et as .2t to baud_bas prigoourd3eck_l t_exit uontsa0x7)  ** et as .0000/2; 
 !  == FT2_new_baud) &&
) < 0  ** et as .0000/2; 
 <d9600)_p	trol_msg-EINVAL usaud Make__u16 lt ussly
eugh, you == Fileg8] = { uss!li_pudts &= D_MASK=t( == FT2D_MASK =~ *    SPD_H)S|0,               ( ** et as .D_MASK = *    SPD_H));rivts &= et to baud_base=t ** et as .2t to baud_bas pivt, 0),e
	->low_lrucncip_n == FT2D_MASK == ASYNLOW_LATENCY) ? 1 :g	iu
d3eck_l t_exit:sa0x7) old= (st.D_MASK == ASYNC_SPD_CU)S!=
	 < 0  == FT2D_MASK == ASYNC_SPD_CU)= (__u0x7) == FT2D_MASK == ASYNC_SPD_CU)ST
	 *      o HI_p	ttt, 0),e
	->_to_diviso=d00, S priex =  {
	 == FT2D_MASK == ASYNC_SPD_CU)ST
	 *      o VHI_p	ttt, 0),e
	->_to_diviso=d100, Wipriex =  {
	 == FT2D_MASK == ASYNC_SPD_CU)ST
	 *      o SHI_p	ttt, 0),e
	->_to_diviso=d0800)
ipriex =  {
	 == FT2D_MASK == ASYNC_SPD_CU)ST
	 *      o * **_p	ttt, 0),e
	->_to_diviso=dteps 1ipriex =p	ttt, 0),e
	->_to_diviso=d0_contr0x7) (old= (st.D_MASK == ASYNC_SPD_CU)S!=
	 < 0  == FT2D_MASK == ASYNC_SPD_CU)= ||
) < 0(  == FT2D_MASK == ASYNC_SPD_CU)ST
	 *      o cust) &&
) < 0  old= (st.et to baud_base!=t== FT22t to baud_bas))= (__uuct usb_seriae = (__u}control_msg(	)iuu}isors*/
et as finfo	i_p******************************************************************
 * Utlity functionsble",	 */

	d Produc ************************************************************************
 */

static unsigned read ial.cuserdev_subrout ***nedreadall - I shoriv =hutdown =		fHIGH.ftdi_SIO_startuite =	 ial.down =		 al *serial);
static int  ftprivate * p*port)
{
	char buf[1]o=d&
			    f[1][0private * priv = (struct tdi_ u	 * Ti ;ite_urb_pooloid f; contdbg("%s",ivFUNCl wN__t uivts &o=dkmalloc(tantof(ate * priv = (struc), GFP_KERNEL) pr {
	! (st)(__ueal("%s-dkmalloc(%Zct faitruc",divFUNCl wN__,stantof(ate * priv = (struc))tr_rrol_msg-ENOMEM__u}comem / ( (st}


stantof( tdi_))tr_te_offset; itor TIta_msr_wai(&== FT2/* Used for TI)speciaet inwill push__u16 ltractUM_Ue =	ugh immediruclylue her
) < tct  ta_ms a tasks
	ierl*/

	 hem	i_pvts &= D_MASK=t= ASYNLOW_LATENCY usaud Ifer to > 6estant offine Bne NUM_URBS	 {
	=, 0),num_bulbulk_ca= (__ukfree
	=, 0),num_bulbulk_ca=__u}co=, 0),num_bulbulk_cao=dkmalloc (e PKT, GFP_KERNEL) pr {
	! , 0),num_bulbulk_ca= (__ukfree
	=di_)tr_rrol_msg-ENOMEM__u}co {
	=, 0),ck,
	d ft (__u=, 0),ck,
	d f),ed_ta_cabulk_cao=d , 0),num_bulbulk_ca;__u=, 0),ck,
	d f),ed_ta_cabulk_ca_lengtho=de PKT uontsaud Free
=, 0's exissor as */
#defil thed_ta_caBne NUM.URBS	 {
	=, 0),ock;

	in= (__u1porfree
	in
	=, 0),ock;

	in=;__u=, 0),ock;

	ino=dNULL__u}co {
	=, 0),.num_porbulk_ca= (__ukfree
	=, 0),num_bporbulk_ca=;__u=, 0),num_bporbulk_cao=dNULL__u}csaud er tuctouras */
#defi foril thed_ta_caBne NUMsdi_pre_urbce_ba_; it (&== FT2ock;

	int force_ba=;__fstati0
	if i <dlock_t	w; ++i= (__u16)0
	1poralloc
	in(0)tr_rts &= UM_URBS];
	spini, 1,d f;__u0x7)16)0
=dNULLt (__u	eal("Uc strs
	ier tuct **#defiin#defi for")iuo		rtup ;__u}
__u16)),ed_ta_cabulk_cao=dkmalloc (FER_SIZE	64 /* the devic, GFP_KERNEL) prr {
	!16)),ed_ta_cabulk_cat (__u	eal("%sly
and offmemoryd ratdefine NUM_c",d0, WDR_TivFUNCl wN__t uo		->seinndex;u}co}csaud N	 *  t leet -codes */
#defiblock t foriRBS	 {
	ika0x800{r_ukfree
	=di_)tr_rrol_msg-ENOMEM__u}cco=, 0), (struct=ftdi_ uontrol_msg(	)iu}which Swn =		  ratck t
	.id32Cdi_preadall - I sho1po
			  :t)
{
	chrobeftdi_SIO_startuite =hutdown =		 al *serial);
static int  ftprivate * priv = (struct tdi_ u	 * Teal usadbg("%s",ivFUNCl wN__t uivealkay;

#d	 ial.down =		(int  ftdi	 {
	eal)(__urol_msg(eal)__u}cco=s &o=d
			    f[1]2 div_value == FT2232C) {
		ut
	.ue == FT20000/2; 
   12000000 / 16ue == FT2    /* This p_name ntrol_msg(	)iu}whch Swn =		  ratck tle",
	.id32Cdi_preadall - I sho1po
			  :t)
{
	chrobeftdi_SIO_startuite =
	.shutdown =		 al *serial);
static int  ftprisorite =
	.shutdown =		 i_pvate * priv = (struct tdi_ u	 * Teal usadbg("%s",ivFUNCl wN__t uvealkay;

#d	 ial.down =		(int  ftdi	 {
	eal)(__urol_msg(eal)__u}cco=s &o=d
			    f[1]2 div_value == FT2232C) {
		utt baud_baue == FT20000/2; 
   tatic indiviOCMIWW   spbe / 16,inetverter igned ssor3 >,or ==il th0.5 ruct ftd0x7]*****!di_privrol_msg(	)iu}isorite =
	.shutdown =		 i_phch Swn =		  ratck tquires ad32Cdi_preadall - I sho1po
			  :t)
{
	chrobeftdi_SIO_startuite =
	.shutdown =		 al *serial);
static int  ftprisorite =
	.shutdown =		 i_pvate * priv = (struct tdi_ u	 * Teal usadbg("%s",ivFUNCl wN__t uvealkay;

#d	 ial.down =		(int  ftdi	 {
	eal)(__urol_msg(eal)__u}cco=s &o=d
			    f[1]2 div_value == FT2232C) {
		utt .shutue == FT20000/2; 
   tatic indiviOCMIWW   spbe / 16,inetverires a igned ssmultiplt offor3 > ruct ftd0x7]*****!di_privrol_msg(	)iu}isorite =
	.shutdown =		 i_phch Swn =		  ratck tqui,
	.id32Cdi_preadall - I sho1po
			  :t)
{
	chrobeftdi_SIO_startuite =
	.shutdown =		 al *serial);
static int  ftprisorite =
	.shutdown =		 i_pvate * priv = (struct tdi_ u	 * Teal u	 * Ti	ret usadbg("%s",ivFUNCl wN__t uvealkay;

#d	 ial.down =		(int  ftdi	 {
	eal)(__urol_msg(eal)__u}cco=s &o=d
			    f[1]2 div_value == FT2232C) {
		utt .shut u	 * cao=d
			    
	return ->_tobservesT20I	return Nrb bup_type 
	rett (__u=	}	
	
	return o=dMINI_FACE_B__u}coex =  (__u=	}	
	
	return o=dMINI_FACE_A__u}co== FT20000/2; 
   tatic indiviOCMIWW   spbe / 16,inetverires a igned ssmultiplt offor3 > ruct ftd0x7]*****!di_privrol_msg(	)iu}isorite =
	.shutdown =		 i_phch Swn =		  ratck tquireRad32Cdi_preadall - I sho1po
			  :t)
{
	chrobeftdi_SIO_startuite =
	.shRdown =		 al *serial);
static int  ftprisorite =
	.shRdown =		 i_pvate * priv = (struct tdi_ u	 * Teal usadbg("%s",ivFUNCl wN__t uvealkay;

#d	 ial.down =		(int  ftdi	 {
	eal)(__urol_msg(eal)__u}cco=s &o=d
			    f[1]2 div_value == FT2232C) {
		utt .shRue == FT20000/2; 
   tatic indiviOCMIWW   spbe / 16,inetverires a igned ssmultiplt offor3 > ruct ftd0x7]*****!di_privrol_msg(	)iu}isorite =
	.shRdown =		 i_phch Swn =		  ratck td TranceiIO or FTTS-CTS to be enltrdwir100000
nly s(all T n
	 *mapp    - 33 >int i_preadall - I sho1po
			  :t)
{
	chrobeftdi_SIO_startuite =,
	.shutdown =		 al *serial);
static int  ftprisorite =,
	.shutdown =		 i_pvate * priv = (struct tdi_ u	 * Teal usadbg("%s",ivFUNCl wN__t uvealkay;

#d
	.shutdown =		(int  ftdi	 {
	eal)(__urol_msg(eal)__u}cco=s &o=d
			    f[1]2 div_value == FT2D_MASK|
	 *      o cust;ivts &= et to baud_base=t77ue == FT2Df non-zero=de38400iprivrol_msg(	)iu}isorite =,
	.shutdown =		 i_phch Swn =		  ratck tHE-n a  FIO or FTTS-CTS to be enltrdwir10****000
nly s(all T n
	 *mapp    - 10c int tdi_SIO_startuite =,
	.shutdown =		 al *serial);
static int  ftprisorite =,
	.shutdown =		 i_pvate * priv = (struct tdi_ u	 * Teal usadbg("%s",ivFUNCl wN__t uvealkay;

#d
	.shutdown =		(int  ftdi	 {
	eal)(__urol_msg(eal)__u}cco=s &o=d
			    f[1]2 div_value == FT2D_MASK|
	 *      o cust;ivts &= et to baud_base=t240ue == FT2Df non-zero=de38400ipr== FT2Df nonn-zerop_name ntrol_msg(	)iu}isorite =,
	.shutdown =		 i_pphch Swn =		  ratgnednd Product le",
	.i(rat.shut)FIO or  tdi_SIO_startuite =
	.shutdown =		 al *serial);
static int  ftprivate * priv = (struct tdi_ u	 * Teal ussadbg("%s",ivFUNCl wN__t uvch XXX Assume i0's att baud_ba.  Anverires aIO or  plit in
	.d,inet
ent betwill behave like att baud_ba.  -- IJA i_pvealkay;

#d
	.shutdown =		(int  ftdi	 {
	eal)(__urol_msg(eal)__u}cco=s &o=d
			    f[1]2 div_value == FT20000/2; 
   _new_baud_ uontrol_msg(	)iu}which ;

#define WD ss call - I sho1po
			  :e_type ftdi_isconne* p
 in nbetweecall - t_spock to wriO or  ween sconne* 10***
 in n1po
			  :e_type ftdi_isconne* 
_divisorcalls _ype ftdiose,
	 rateaCTSen,
	ither Sf[1]
_divisorefine WD ss call - t_spo(ie ;

#define WD)igned short iwn		(struct usb_se al *serial);
static int  ftprisorite =t usb_se i_private * p*port)
{
	char buf[1]o=d&
			    f[1][0prrivate * priv = (struct =s &o=d
			    f[1]2 div_valu u	 * Ti;last_dtr_rts;	/*ASYNC_ ssadbg("%s",TivFUNCl wN__t uuvch iocten,
	ned ssyou ose,
*  t t_spepo * Tte_offset_divis(byn1po
			  .c:_ype ftdiose,
FTTS-CTScalls ite =		ftd)  t the bauvch Otepsexecutde to sifd_base (der Sfinacten,
	ned   ratckweenO or  tdio {
	=, 0),en,
_nt  fka0x80(__u_urbce_ba_;rqrol  (&== FT2ock;

	int force_ba,*ASYNCt uuv_fstati0
	if i <dlock_t	w && ts &= UM_URBS];
	spini,; ++i= (__uaud FIXME - un	 iaces
er Sf o flor a*porunlink
	ino ioctt_speerent er Shost */
    lUMsdn
	 of 100ard bau16)),nO o=dNULL after
)rent er SdefibsSfinishruct O herwio > 64 ! ioctoopssor == 1uaud *porunlink
	in(ts &= UM_URBS];
	spini,); == 1ua {
	== FT2UM_URBS];
	spini,),ed_ta_cabulk_cat (__u	ukfree	== FT2UM_URBS];
	spini,),ed_ta_cabulk_cat uo		rts &= UM_URBS];
	spini,),ed_ta_cabulk_cao=dNULL__uo	}__uu1porfree
	in
	=s &= UM_URBS];
	spini,);
		rts &= UM_URBS];
	spini,o=dNULL__uo}
__u_urbcune_ba_;rqe etor  (&== FT2ock;

	int force_ba,*ASYNCt uuaud *por_isconne* pt usof cwnher Sf[1]),ck,
	d f sof co'/
#dnbether  tdiovch is waof codef_stiouslDEVICu}co {
	
			    f[1]2 div_val){r_ukfree	
			    f[1]2 div_val) uua
			    f[1]2 div_valo=dNULL__u}c}isorite =t usb_se i_pudtr(struct uruct usb_s al *serial);
statiuct file *filp);
static int  ftprisorite =sb_s i_pvate * pset_termtmpk_ctl =	;ivate * p*port)
{
	c int  fo=d , 0),et as rivate * priv = (struct =s &o=df[1]2 div_value u	 * Te e*/

=d0_coruct ftdi_pr ud N	 *T */
#dck to wt->serial->dit dhinkthe badbg("%s",TivFUNCl wN__t uuivt, 0),e
	->low_lrucncip_n == FT2D_MASK == ASYNLOW_LATENCY) ? 1 :g	iu
aud No eal.r 	ieck fol ratckwee(will n
	 eal.rs lrucr altwhit i_pvch See ;

#deio.hak */
escripfor aferschipweee eetng lasort->serial->de
			    FTDI_port->serial->de
			    FTDI_SIO_SETDRATE_REQREriv->   FTDI_DRATE_REQREriv->   FTDb_valu _SETDRATE_REQREriv-_REu _SET=	}	
	
	return ,EOUT));
}


static __iu
aud Tet_termout */
->termios-byn1po
et as finit. Wef co'/
uct us
) < t, 0),e
	->set_term-tckweew   sploe,
	divisobserves alIGH.
) < et in thsaud;behaviouraaof
			  .c/rs=sb_s()m-tKubathe baud ,
	.break_ctl =	 twill sd seo wr*/
     messausslg la,
	.break_ctl =	(e *fil&tmpk_ctl =	_iu
aud FIXME: FET_D*/
     mightstatic stru, sofit *    sp in ieckiso-
) < w Shol  no */
      fmout */
-! i_pvch T_msgr adefil thDTRitionalw, you can fET_D*/
    l folbynout */

tdio {
	sb_seriae *filst_dic __u (__ueal("%s Eal.r I shoDTRiOW 0
d f",divFUNCl wN__t uo}io {
	sb_seriae *filst_dic __u(__ueal("%s Eal.r I shodefiOW 0
d f",divFUNCl wN__t uo}ipvch Swn =fine  fol ings, thnO or  tdioFILL_BULKk_t		=, 0),ck,
	d f, 
			    FTDI_
	) < 0 n1po
rcvnum_l->de
			    FTDI_ , 0),num_bulbd spo * Adde esIO_SE < 0 n=, 0),ck,
	d f),ed_ta_cabulk_ca,n=, 0),ck,
	d f),ed_ta_cabulk_ca_lengthO_SE < 0 nallback,
	.write_bulk_ca int cha	e e*/

=d1po
eubmit
	in(t, 0),ck,
	d ftdi	 {
	e e*/
)
u	eal("%sly
faitru eubmitsor aine BUFS, eal.r %d",divFUNCl wN__,se e*/
) uuivrol_msge e*/
iu}isorite =sb_s i_pwhich 
_di1po
			  :_ype ftdiose,
	gr lDEcalls ite =		ftdsifd_beepo * Tspeeb_s***
 in net inr lDEn
	 *call - t_spobetweeate set -		ftd
 in n
 in n
 ied short iwn		(struc		ftdsal *serial);
statiuct file *filp);
static int  ftprisorite =		ftdsi_pvate * p*port)
{
	c int  f;last_dtr_rt(struB38400
= t, 0),e
	->set_terto B38400rivate * priv = (struct =s &o=dvate *)port->private;
	char buf[1];
	unsigned ftdi_hi * Teal usadbg("%s",TivFUNCl wN__t uuvint  fo=d */
*port)
{
	c(ftdi_fiivFUNCl wN__t uo {
	!int  ftp_urol_ms;pud {
	
			    FTD= (__u0x7)uB38400
& HUPCL)(__uaud Dis strsfET_D*/
     == 1ua {
	sort->serial->de
			    FTDI_uo		rpipe(port->serial->de
			    FTDI_SIO_SETET_BAUDRATE_REQUESTFLOW_		       FTDI_SETET_BAUDRATE_REQUESTFLOW_		       FTDb_value, uET_BAU0e, 
			       buf, OUT));
}


static __c __u (__uu	eal("eal.r I shofET_*/
     d f");
		r}T_BAU
__uaud dropoDTRi== 1ua {
	sb_seriae *filLOWic __u(__uu	eal("Eal.r I shoDTRi****d f");
		r}__uaud dropodefi== 1ua {
	sb_seriae *filLOWic __u (__uu	eal("Eal.r I shodefi****d f");
		r}__u}isorNot16 lt us no l ***weehupclTspeeffthe ba for  usb_se oura.wriaine Bi_pr	 {
	=, 0),ck,
	d ft (__uvealkay*porunlink
	ino(t, 0),ck,
	d ftdi			 {
	ealc __ && ealc!=g-ENODEV)__uu	eal("Eal.r unlinkor a*ino(%d)", eal)ex;u}coaud *nlinkeate runnor as */
#defsthe ba}isor {
	
			    FTD= i_pwh}isorite =		ftdsi_p

AU
based o
	.i to be ener Sfir/
	iyy s
	ihol :
 in B0 1
 in B1 0
 in B2..7 lengthooffmessaus exclud folbyy s0***
 ined o **#	int fl
#dncan  to be > 64 ! yy 
 tdi_SIO_startuite =s */
#al_port *port, int from_user, const unsigned 0, WDR_har *buf, int count);
static int  ftprisorite =s */
#i_pvate * p*port)
{
	c int  fo=d */
*port)
{
	c(ftdi_fiivFUNCl wN__t uoate * priv = (struct =s &o=dvate *)port->private;
	char buf[1];
	unuf, int count);fir/
_ yy _hi * T
				 This pis the offswill be 1  ratck t
	.il th0 o herwio >scts;	/*e e*/
ius;	/*gned_ yy srt)n

=d0pis tch imt  fkoffgnedn neede)n

he baud Va
{
strsd ratdefi forimanausm)n

he nuf, int count);curices frsmehowo=dvuf, int count);)
st u	 * Tiu u	e_urb_pooloid f; ck =o * cao
	iooloI sho1efi forig last_dtr_rts;	/*ASYNC_2	ck d seoffgefi forimanausm)n

he ncontdbg("%s	ned  %u, %d! yy s",TivFUNCl wN__,n=, 0),urb bu,int  ftdiud {
	co  fka0x80 (__udbg("s */
# to ese offo! yy s")ex;ugoourexit uontontd				 This p= ts &= UM_URB This ite_offsetdbg("d				 This p / your%d",d				 This tdiudwhic i	co  fk>x80 (__uud *rb_ yy _nt  fka*gned_ yy _nt  fk+T
				 This pi_pr	 nt *rb_ yy _nt  f; tch Nrb buffer yy sffer_t	n need pi_pr	 nt *ned_ yy _nt  f;tch Nrb buffer yy sffergnedn needhe ba forFi sea free
defiblock tlis pi_pr		ino=dNULL____u_urbce_ba_;rqrol  (&	=s &= UM_URBS];
	spice_ba=,*ASYNCt _ ssa_fstati0
	i f i <dlock_t	w && ts &= UM_URBS];
	spini,; i++t (__uv {
	== FT2UM_URBS];
	spini, -> * Usedc!=g-EINPROGRErSu (__uu		ino=dts &= UM_URBS];
	spini,;
data stMus pmake_surove o heras */
##define grab> 64 !== 1uau16)),* Usedc=g-EINPROGRErS;
datartup ;__ur}__u}
__u_urbcune_ba_;rqe etor  (&== FT2ock;

	int force_ba,*ASYNCt u__u0x7)16)0
=dNULLt (__u	dbg("%sly
no mor  free
defs",TivFUNCl wN__t u	;ugoourexit uou}
__u stAllocate;memoryd rater Sdefibe Racessa_DEVIC_u0x7)16)),ed_ta_cabulk_cao==dNULLt (__u	16)),ed_ta_cabulk_cao=dkmalloc (FER_SIZE	64 /* the devic, GFP_KERNEL) prru0x7)16)),ed_ta_cabulk_cao==dNULLt (__u		eal("%sld_t
and offkernelfmemoryd ratdefi..c",divFUNCl wN__t uo		rgoourexit uour}__u}
		__u sted ooriginactsio Ra bener Sfir/
	iyy s
	i*/
 ablock tiyy nt  fk
	red thter Sdefimay be codeiyy sbigg

	 hapock to edn need
;		/* s	*rb_ yy _nt  fka*mblo(nt  fk+T
				 This ,FFER_SIZE	64 /* the devic= privned_ yy _nt  fk= *rb_ yy _nt  fk-T
				 This _ ssa_read pyiblock t needard bn Bi_pr	 {
	 unsignedt (__uv {
	copyb unsigned(16)),ed_ta_cabulk_cao+T
				 This ,e, uET_BAcurices frsmehow,*gned_ yy _nt  fk)u(__uu	rol_msg-EFAULTue 	r}__u}iex = (__u	memcpy(16)),ed_ta_cabulk_cao+T
				 This ,e, u_offsetcurices frsmehow,*gned_ yy _nt  fk) uou}AU
__ufir/
_ yy k= *rb),ed_ta_cabulk_ca;pr	 {
	
				 This p>__u(__uuMIWWdata - 
	*/
      yy kas
er Sfro fkoff_beep* Con== 1ua*fir/
_ yy k= 1 | ((gned_ yy _nt  f) wit2t _ s_u	dbg("%slByy s: %u, Fir/
	Byy :s0x%02x",TivFUNCl wN__,nt  f, fir/
_ yy [0])ex;u}coa
uu1porpe ftdi_ebug;
			ex_vFILE__,nivFUNCl wN__,n*rb_ yy _nt  f, fir/
_ yy )ex;usa_reafill ck tilk_caoe this thi pi_pr	FILL_BULKk_t		d f, 
			    FTDI_
	)) < 0 n1po
->snum_l->de
			    FTDI_ , 0),num_bporbd spo * Adde esIO_SE) < 0 n1 f),ed_ta_cabulk_ca,n*rb_ yy _nt  f,_SE) < 0 ncallback,
	.ioctl =		ftdi int cha		16)),ed_ta_cabD_MASK|
	,
	.  FUE_BULKex;usa_reauhci * Uck eal.rs  {
it * Usedc / your-EINPROGRErSgr atdiovch d f submissiic, sof 3 sr * Usedcbefo	unsibmissiic. d pi_pr	_urbce_ba_;rqrol  (&	=s &= UM_URBS];
	spice_ba=,*ASYNCt _ sau16)),* Usedc=g	iu
a	e e*/

=d1po
eubmit
	in(d ftdi		 {
	e e*/
) (__u	_urbcune_ba_;rqe etor  (&== FT2ock;

	int force_ba,*ASYNCt uua	eal("%sly
faitru eubmitsor as */
#def, eal.r %d",divFUNCl wN__,se e*/
) u	rivned_ yy srt)n

=de e*/
ius;ugoourexit uou}
_u_urbcune_ba_;rqe etor  (&== FT2ock;

	int force_ba,*ASYNCt u__uch hovnefkeep foli_p		curices frsmehowo+a*gned_ yy _nt  f privned_ yy srt)n

+a*gned_ yy _nt  f print  fk-a*gned_ yy _nt  f priba}isorwhic i co  fk>x8dhe b exit:sntdbg("%s	s */
# tl_ms fo: %d",divFUNCl wN__,svned_ yy srt)n
cha	e l_msgvned_ yy srt)n
;wh}isorite =s */
#i_ps basedbsSfes for amay n
	 call - t_spock tiO or  weeose,
* ied short iwn		(strucack =	ftdi_write_bul);
static void ftprivate * p*port)
{
	char buf[1]o=dal_port *port, int from_u)16)),*/
 extdiud {
	from_ comnoia_ ieck (tdi_fiivFUNCl wN__ttp_urol_ms;p	prdbg("%sly
ned  %u",TivFUNCl wN__,n=, 0),urb bu)ue u	 x7)16)),* Used0 (__udbg("nonzero	s */
#.wria* Usedcreble =d: %d",d16)),* Used0;p_urol_ms;p	}
_ o {
	=, 0),en,
_nt  fk>__u(__uta_msrtask(&=, 0),eta_msil&tq_immediruc0;p_umark_bh(IMMEDI,
		BH)__u}c}isorite =ack =	ftdi_write_buli_pudtr(struct u
	.read_bulk_ca(al_device_type ftdihar buf[1]otprivate * priv = (struct tdi_o=dvate *)port->private;
	char buf[1];
	un;	/*ee_rooy = 1;
	ci;last_dtr_rts;	/*ASYNC_

u_urbce_ba_;rqrol  (&== FT2ock;

	int force_ba,*ASYNCt u_fstati0
	if i <dlock_t	w && ts &= UM_URBS];
	spini,; i++t (__u {
	== FT2UM_URBS];
	spini,),* Usedc!=g-EINPROGRErSuus;uee_r++ uonto_urbcune_ba_;rqe etor  (&== FT2ock;

	int force_ba,*ASYNCt u__are arml estlirsd rat 6estake_offl ***_iscipl **_URBS	 {
	(ee_ro-a*2ic __u
;uee_rc=g	iu
aee_rc*=FFER_SIZE	64 /* the devicly
ns &= UM_URB This itrdbg("%sly
rol_mss %d",divFUNCl wN__,see_r);rivol_msg(ee_r);c}isorite =ack =	ee_rc*_pudtr(struct u
	.re=	ftdi_chars_in_al_port *port)
{
	char buf[1];
	isorite =		ftdi_chars_in_g last_dtr_rts;	/*ASYNC_2	;
	ci;la(structrdc=g	iuvate * priv = (struct tdi_o=dvate *)port->private;
	char buf[1];
	un;	/*d				 This p= ts &= UM_URB This itprdbg("%sly
ned  %u",TivFUNCl wN__,n=, 0),urb bu)ue
u_urbce_ba_;rqrol  (&== FT2ock;

	int force_ba,*ASYNCt u__aretd sosor =d o rb buffer yy sfr TI foli_p	fstati0
	if i <dlock_t	w && ts &= UM_URBS];
	spini,; i++t (__u {
	== FT2UM_URBS];
	spini,),* Usedc==g-EINPROGRErSu (__uuuctrdc+=FFER_SIZE	64 /* the devicly

				 This _
;u}co}csa_urbcune_ba_;rqe etor  (&== FT2ock;

	int force_ba,*ASYNCt u__dbg("%sly
rol_mss %d",divFUNCl wN__,suctrdt u__rol_msg(uctrdt u_}isorite =		ftdi_chars_in_g l
d short iwn		(strucck =	ftdi_read_bulk);
static void ftprisorite =ck =	ftdi_read_bulki_pvate * p*port)
{
	char buf[1]o=dal_port *port, int from_u)16)),*/
 extdivate * p*port)
{
	c int  f;laate * pstyfollowst_styiuvate * priv = (struct tdi_	unsigneeal.r_8400ri_offsetnuf, int count);
			e= *rb),ed_ta_cabulk_ca;p2	;
	ci;la(stre e*/
ius;	/*Ra b_84ipius;	/*p* ConB This itpr x7)16)), rb buB T_p* Consk>x80 (__ueal("%sled_ta_cabulk_ca_lengtho%de is a _lengtho%de rb bufferp* Consk%d",ivFUNCl wN__,
 urb_inde),ed_ta_cabulk_ca_lengthOinde), is a _lengthOinde), rb buB T_p* Consk0;p_ueal("%sled_ta_cabD_MASK%x	,
	.  FUE_BULKK%x	",divFUNCl wN__,16)),ed_ta_cabD_MAS,	,
	.  FUE_BULKKt uo}ipvdbg("%s",TivFUNCl wN__t uuv {
	from_ comnoia_ ieck (tdi_fiivFUNCl wN__tt {p_urol_ms;p	}
o {
	=, 0),en,
_nt  fk<=__u
;ueol_ms;pudint  fo=d */
*port)
{
	(tdi_fivFUNCl wN__t uo {
	!int  ft(__udbg("%sly
badou see.
=o * cao- exit fo",ivFUNCl wN__t uvurol_ms;p	}
o
	is o= t, 0),e
	 uo {
	!e
	= (__udbg("%sly
badois o=o * cao- exit fo",ivFUNCl wN__t uvurol_ms;p	}
co=s &o=dvate *)port->private;
	 __u32 div_valueu	 x7)16)),* Used0 (__uciaet inwill happ nkas
		ftdsver yoe+movsofit ky sidbgncan an ealci_p		dbg("(_base (dokhichd	ftd) nonzero	ine Bneria* Usedcreble =d: %d",d16)),* Used0;p_urol_ms;p	}
_ s the offsTr Sfir/
	twor yy sfferver yoine Bp* Con>termi UsedcRBS	 {
	nde), is a _lengthk>x2= (__u1porpe ftdi_ebug;
			ex_vFILE__,nivFUNCl wN__,n*rb), is a _lengthOi
			t uo}iex = (_               tdbg("S Usedcr lD: %03oo %03oo",d			[0],d			[1])ex       t}whiuciaeO DO --  ieck  rateur a*pfl ***e thhe tc iapprodivrucly: i_pvch  his thlt u*pf i_pvch See acmally
/* 1do a ttyflt u*pf - eg ttyflt u*p(e
	= i_pvch  {
CD weenrodp   l thek tli***weecan CLOCAL t_spowe *    splt u*pfhe baRa b_84ipc=g	iuvfstatp* ConB This =if p* ConB This  <d*rb), is a _lengthf p* ConB This  +=FPKTSZ0 (__uciad_tabr o **#li***i Usedcisor = olwhice
stagnact {
dik_ca)n

he nu {
	== Fc!=gNULLt (__u	ount) ** e Usedc=gd			[p* ConB This +0] &UDRATE_TATUS_B0PD_CU prru0x7) ** e Usedc!=t== FT2f_st_* Used0 (__uET=	}	
	dik_ e Usedc|=) ** e Usedc^t== FT2f_st_* Used uo		rwake_up0,
	.num_be =	(&== FT2/* Used for TI)speuET=	}	
	f_st_* Used =) ** e Used;__ur}__u}
__uare a tc ieal.rs l thrtup 
he nueal.r_8400 =)TTY_NORMAL__uo stAlth	ugh ck tiO or  usrate bitmaskse thhenr  plithol  multiplt tdiovch eal.rs ich rp* Con>-or = ordcaoher  o (HI_beepriortandaht tdiovch eal.rpweee l_ms100ard, this olaycaodhe ba 0x7)gd			[p* ConB This +1] &UDRATERS_OE t (__uveal.r_8400 =)TTY_OVERRUN;s_u	dbg("OVERRRUN eal.r")ex;u}coa0x7)gd			[p* ConB This +1] &UDRATERS_BI t (__uveal.r_8400 =)TTY_BREAK;s_u	dbg("BREAKcreble =d")ex;u}coa0x7)gd			[p* ConB This +1] &UDRATERS_PE t (__uveal.r_8400 =)TTY_PARITY;s_u	dbg("PARITY eal.r")ex;u}coa0x7)gd			[p* ConB This +1] &UDRATERS_FE t (__uveal.r_8400 =)TTY_FRAME;s_u	dbg("FRAMING eal.r")ex;u}coa0x7)nde), is a _lengthk>xp* ConB This  +x2= (__u	fstati0
	2;ati0<FPKTSZ0 && ((i+p* ConB This ) <d*rb), is a _length); ++i= (__uauch hol  ardmake_surovwef co'/
oer fET_Dck tilk_ca
 uET_Bial_sttyfinpe t_84ip=		ft' !== 1uauif(e
	->84ip.nt  fk>=)TTY_FLIP* tdevic= (__uau	is _84ip=ulk_ca_push(e
	= pr		r}__ua	sorNot16thas
er Seal.r I400 weenuly every fsta
 uET_Brver yo ltractUMcreble =ditionalw,  co'/
know
 uET_BrTS-CTScltractUMcit appli100ard== 1uauttyfinpe t_84ip=		ft(e
	,gd			[p* ConB This +i],eeal.r_8400);
		r}__uaRa b_84ipc=g1 uou}
_#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOWiovch 0x7 rp*rtandeal.rpweedete* 10
/* 1n
	 * Used p* Conskfo	uvca
 ub_inntil7 rcltractUMcisde)n

ial_and  rp*rtandeal.r.
 ub_iet in#define worklw,ll sionalrate ply eveor areble =ate nuvca
 ub_is t folateeamffer e B
			e-rverpock	ugh  **#				ehafine beende)n
.
 ub_ieter fo	unI (bill) hol  aakenlt_speeu
.
 ub_iHowuvcam-tckweemightsmake_sen,
	 ratfram foleal.rs l thsofr a
 ub_isofI amfleavaud rate, it in	 ratnow.
 uhe nuex = (__u	 {
	eal.r_8400 !=)TTY_NORMALu(__uu	dbg("eal.r_8400 weecan normar")iuo		aud If> 64 ! itdsit ky ts a * Used -sifd_bhipweean ealase / sea  e BcltractUMc== 1uauif(e
	->84ip.nt  fk>=)TTY_FLIP* tdevic= (__uau	is _84ip=ulk_ca_push(e
	= pr		r}__ua	ttyfinpe t_84ip=		ft(e
	,g0xff,eeal.r_8400);
		raRa b_84ipc=g1 uour}__u}
#s t fba}isor"falue* ConB This =i..c"
he baud LT_DlrucncipRBS	 {
	Ra b_84ip= (__uis _84ip=ulk_ca_push(e
	= pr}ipvch ither Sf[1] weeose,
* stopledyaud roaine Bi_pr {
	=, 0),en,
_nt  fk>__u(__uciad_seinndledyaud roaalwaysaine Bpi_pr	FILL_BULKk_t		=, 0),ck,
	d f, 
			    FTDI_
	)) < 0 n1po
rcvnum_l->de
			    FTDI_ , 0),num_bulbd spo * Adde esIO_SEE < 0 n=, 0),ck,
	d f),ed_ta_cabulk_ca,n=, 0),ck,
	d f),ed_ta_cabulk_ca_lengthO_SEE < 0 nallback,
	.write_bulk_ca int cha
a	e e*/

=d1po
eubmit
	in(t, 0),ck,
	d ftdi		 {
	e e*/
)
u		eal("%sly
faitru e e*bmitsor aine BUFS, eal.r %d",divFUNCl wN__,se e*/
) uontsaol_msg;c}isorite =ck =	ftdi_read_bulki_pd short iwn		(strucrtup =		f(al_device_type ftdihar buf[1]tatic ctup =shore tprivate * p*port)
{
	c int  fo=d , 0),et as rivate * priv = (struct =s &o=dvate *)port->private;
	__u32 div_value = 0_u16 urb_ind0
	if unsigned ftdi_hipvch ctup =shore = -10ard,_msgr actup ,il th0 ard,_msgrffhrtup 
he nsors*e,	 */

s/sign/ttyfioallard bdsit u,
* iednsor~TIOCsb_se				6 urb_ind0NEVERehafDck titup 
bitmios->c_itli_pud {
	ctup =shore= (__u16)(b_ind0
	=	}	
	~TIOCsb_se				6 urb_ind0|UDRATE_REQUEST_REAK;s_ndex = (__u16)(b_ind0
	=	}	
	~TIOCsb_se				6 urb_indf un}
e u	 x7)1ort->serial->de
			    FTDI_port->serial->de
			    FTDI_SIO_SET_BAUDRATE_REQUESTDATA     FTDI_SIO_SET_DRATE_REQUESTDATA     FTDb_value, urb_index,
			 e, 
			       buf,e, urb_iOUT));
}


static __c __u (__ueal("%slFAILEDlardic str/dis strsitup 
shore (shore waof%d)", ivFUNCl wN__,ctup =shore=;s_n	BAU
__dbg("%slitup 
shore iof%d - uefibsS%d",divFUNCl wN__,ctup =shore,index,
			)ue u}which old=_ctl =	 */
 ablsor = originact_ctl =	 bserves  l the
	->set_term*/
 abls
nt er S **#rate can ot in
	.d
nt WARNING: reak_ctl =	 calls ckweewal_sold=_ctl =	 >c_kernelfse* eigned short iwn		(structeak_ctl =	 al *serial);
statiuct file *filp);
sta_ctl =	 *old=_ctl =	tprisorite =_ctl =	 *_pvate * p*port)
{
	c int  fo=d , 0),et as rivst_dtr_rt(stru8400rivate * priv = (struct =s &o=dvate *)port->private;
	char buf[1];
		e = 0_u16 urb_ind;offswill holwher S **#D_MASK*_pvruct ftdi_pr ud Perhaps
	 *    spdynam cd sosalloc ckwe?
he nco// Addry fstaxon/xrffh igned ivst_dtr_rt(stri8400
= t, 0),e
	->set_terto Bi8400rivuf, int count)vstoprivuf, int count)vstart;contdbg("%s",TivFUNCl wN__t uuvch Ff nolittle trickftckweenO or   to be enifilunl estit ky  / yourB0.URBS	 {
	== FT2Df non-zero&& ((t, 0),e
	->set_terto B38400 &UC_TYP)S!=rB0)= (__udbg("%s: fstc folbe tty settratckweenO or ",divFUNCl wN__t uo	t, 0),e
	->set_terto B38400 &= ~C_TYP uo	t, 0),e
	->set_terto B38400 ce;
	}	
	Df non-zer pr}ipvch Ff nolRTS-CTSckftckweenO or   to be enif.URBS	 {
	== FT2Df nonn-zero= (__udbg("%s: fstc foln-zeroptratckweenO or ",divFUNCl wN__t uo	t, 0),e
	->set_terto B38400 ce;CRTSCsb_contpvr8400
= t, 0),e
	->set_terto B38400ri
aud FIXME -Fratckweecnd If co'/
ubr oither Sli***weeend so6 lt u folsta
 BAUcan ios-o ts a do__u16 lt useengardl estios-    sp in strs
	i
WDR_hatabr oold=_ctl =	 l the
	->set_termiednsorNOTEiete = rout **s plitge Ti	retum_b1000yi
WDR_;

#deio_ck =	ftdi_read_bulkly
n*    - exam ferschipckwee_           me_taly

co'/
 bdsalt_hroblems ye

he ncoch Sete rb buffer				ebits,rp*rtan, stoplbits
he nco6 urb_ind0
	ifco6 urb_ind0ce;(38400 &UCSTOPB ?_DRATE_REQUESTDATA STOP_BITS_2 :
EE < 0 nDRATE_REQUESTDATA STOP_BITS_1)fco6 urb_ind0ce;(38400 &UPARENB ?_
EE < 0 n(38400 &UPARODD ?_DRATE_REQUESTDATA PARITY_ODD :_
EE < 0 n_DRATE_REQUESTDATA PARITY_EVEN) :
EE < 0 nDRATE_REQUESTDATA PARITY_NONEt uo {
	38400 &UCSvic= (__uaialch
	38400 &UCSvic= (__u itdsCS5: 6 urb_ind0ce;5;tdbg("Sate canCS5")ifrtup ;__u baudCS6: 6 urb_ind0ce;6;tdbg("Sate canCS6")ifrtup ;__u baudCS7: 6 urb_ind0ce;7;tdbg("Sate canCS7")ifrtup ;__u baudCS8: 6 urb_ind0ce;8;tdbg("Sate canCS8")ifrtup ;__uout */
:
u		eal("CSvic waofios-butecan CS5-CS8")i
;u}co}csaud et in thRa breabyDck titup 
	 ial thsionalit u,
st 6estame
	 ial th--buteated in or' - tal_stt inb_ind0	i_pvts &= ~TIOCsb_se				6 urb_ind0=16 urb_index;u	 x7)1ort->serial->de
			    FTDI_port->serial->de
			    FTDI_SIO_SET_BAUDRATE_REQUESTDATA     FTDI_SIO_SET_DRATE_REQUESTDATA     FTDb_value, urb_index,
			e, 
			       buf,e, urb_iOUT));
}tatic __u (__ueal("%slFAILEDlardios-e			bits/stopbits/p*rtan",divFUNCl wN__t uo}	BAU
__sorNow do__u16000
nly sRBS	 {
	(38400 &UC_TYP)S==rB0 0 (__uciaDis strsfET_D*/
     == 1u x7)1ort->serial->de
			    FTDI_port->serial->de
			    FTDI_SIO_SETT_BAUDRATE_REQUESTFLOW_		       FTDI _SETT_BAUDRATE_REQUESTFLOW_		       FTDb_value, uE_BAU0e, 
			       buf, e, uE_BAUOUT));
}


static __c __u (__uueal("%sleal.r I shodis strsfET_*/
     d f",divFUNCl wN__t uo	}T_BAU
_uciaDropodefil thDTRi== 1u x7)sb_seriae *filLOWic __u(__uueal("%s Eal.r I shoDTRi****d f",divFUNCl wN__t uo	} 1u x7)sb_seriae *filLOWic __u(__uueal("%s Eal.r I shodefi****d f",divFUNCl wN__t uo	}T
riba}iex = (__usors*t__u16000
nly sdeterm fedcbefo	un== 1u x7)uct usb_seriae = (u (__uueal("%slooloIaitru tby settinr
nly ",divFUNCl wN__t uo	} 1usorEnsurovodefil thDTRibr orai,
* iedniex =  {
	sb_seriae *filst_dic __u(__uueal("%s Eal.r I shoDTRiOW 0
d f",divFUNCl wN__t uo	} 1uex =  {
	sb_seriae *filst_dic __u(__uueal("%s Eal.r I shodefiOW 0
d f",divFUNCl wN__t uou}co}csaud SetefET_D*/
     == 1sorNot16nO or  te by igned ssDTR/CD7)1gh)il thXon/Xrffhinnltrdwar sRBS	 {
	38400 &UCRTSCsb= (__udbg("%slSate can otCRTSCsbefET_D*/
    ",divFUNCl wN__t uou {
	sort->serial->de
			    FTDI_uo		r 0 n1po
->serial->de
			    FTDI_SIO_SETT_BAUDRATE_REQUESTFLOW_		       FTDI _SETT_BAUDRATE_REQUESTFLOW_		       FTDb_value, uE_BAU0 , (DRATE_REQRTS_Csb_HS |, 
			       bufIO_SETT_BAUOUT));
}


static __c __u (__uueal("ooloIaitru tby setroaits/eroptET_D*/
    "t uo	}TT
riba}iex = (U
_uci
	red Xon/Xrffh, it
	red
	red Cieck _u16IXOFF * Used block ti8400
hataone fkoff_bee_ctl =	 bte *)uro
	red  {
IXOFF ss can ss ,F_beepre-xon/xrffh, it issexecutdd.
 uhe nu {
	i8400 &UIXOFFt (__u	dbg("%sl# to ese ardic straxonxrffhi8400=%04x",ivFUNCl wN__,i8400);
		r// T yoerdic stra_beeXON/XOFF olock t;

#deio
		r// S*t__u16vstartil thvstop --     spltve beend codeupn scodewter 
		r// a lofkoffo herader fca)nc fol of codebute_bhipw   sp iner y
		r//  fefficie fkaofvstartil thvstop you can alwaysaRa bre
		rvstart=t, 0),e
	->set_terto B3c[VSTART,;
datvstop=t, 0),e
	->set_terto B3c[VSTOP,;
datndex,
			=(vstop << 8) | (vstartcha
a	u {
	sort->serial->de
			    FTDI
	o		r 0 n1po
->serial->de
			    FTDI_SIO_SETTT_BAUDRATE_REQUESTFLOW_		       FTDI_SETET_BAUDRATE_REQUESTFLOW_		       FTDb_value, uET_BAUndex,
			 e,(DRATE_REQXON_XOFF_HS |, 
			       bufIO_SETTT_BAUOUT));
}


static __c __u (__uuueal("ooloIaitru tby setroaxon/xrffhtET_D*/
    "t uo	r}__u}iex = (__u	ch ex = clavneftonr lDErun  {
cf00 !tCRTSCsbel thi8400 ! XOFF == 1uaud CHECKME Assum folXON/XOFF he tc eabyDcty * Uck - can bynou or  tdiou	dbg("%slT_ms fogrffhltrdwar sfET_D*/
    ",divFUNCl wN__t uoua {
	sort->serial->de
			    FTDI_uo		rpipe(port->serial->de
			    FTDI_SIO_SETET_BAUDRATE_REQUESTFLOW_		       FTDI _SETET_BAUDRATE_REQUESTFLOW_		       FTDb_value, uET_BAU0e, 
			       buf, e, uET_BAUOUT));
}


static __c __u (__uuueal("ooloIaitru tby 3 sr tET_D*/
    "t uo	r}_uuu
;u}coa
u}saol_msg;c}isorite =set_termiedudtr(struct u
	.reioctlsal *serial);
statiuct file *filp);
static inatic , st_dtr_rt(strumd, st_dtr_rts;	/*argtprivate * p*port)
{
	c int  fo=d , 0),et as rivate * priv = (struct =s &o=dvate *)port->private;
	__u32 div_valuee = 0_u16 urb_ind=if MIWWill holwher S **#D_MASK*_pvruct ftdi2i_hi * Tee l, mask;contdbg("%srumds0x%04x",TivFUNCl wN__,rumdt uuvch Ba,
* ichd it I shoacmalll tho her	 *_pvaialch
	3mdt (_pr baudl wCMGET:__udbg("%sll wCMGET",divFUNCl wN__t uouaialch
	== FT2232C) {
	= (__u itds_RE: 1uaud Rto ese ah**i Usedc ings, thnO or  tdio_u0x7) re

=d1po
->serial->de
			    FTDI_uo		rp	0 n1po
rcverial->de
			    FTDI_SIO_SETET	BAUDRATE_REQGET_MODEME_TATUS_    FTDI _SETET	BAUDRATE_REQGET_MODEME_TATUS_    FTDb_value, uET	BAU0e, 
			       buf, e, uET	BAUOUT))1
}


static ___c __ u (__uuueal("%slC   spcan ge Tm itm*i Usedc fmou or  -leal: %d",divFUNCl wN__,_SETT_BAUreI)speuETol_msg(eeI)speuE}__uartup ;__u baudt baud_ba:__u baudt ires : 1uaud ck tle",
	.irol_mss a	twor yy nb_ind0( 6estao ky si1r yy nb_ind)m-tblock ttamee, urb_formafkaofck t neede l_ms100 ings, thinepo * Ttdio_u0x7) re

=d1po
->serial->de
			    FTDI_uo		rp	0 n1po
rcverial->de
			    FTDI_SIO_SETET	BAUDRATE_REQGET_MODEME_TATUS_    FTDI _SETET	BAUDRATE_REQGET_MODEME_TATUS_    FTDb_value, uET	BAU0e, 
			       buf, e, uET	BAUOUT))2
}


static ___c __ u (__uuueal("%slC   spcan ge Tm itm*i Usedc fmou or  -leal: %d",divFUNCl wN__,_SETT_BAUreI)speuETol_msg(eeI)speuE}__uartup ;__uout */
:
u		rol_msg-EFAULTue 	rrtup ;__u}
__urol_msgputigned((ftdi0] &UDRATE_REQDSRPD_CU ?ll wCMQDSR :g	)S|0, W	(ftdi0] &UDRATE_REQCsb_D_CU ?ll wCMQCsbe:g	)S|0, W	(ftdi0]  &UDRATE_REQRI_D_CU  ?ll wCMQRI e:g	)S|0, W	(ftdi0]  &UDRATE_REQRLSD_D_CU ?ll wCMQCD e:g	)S|0, W	ts &= ~TIOCeriseri,_SETTlg);
static vo;
	 argt;__urtup ;_pr baudl wCMUES: ch T_mss ich  seofther Sli**saaof
 Product byDck tmasksi_p		dbg("%sll wCMSET",divFUNCl wN__t uou0x7) */
*ped(mask, lg);
static vo;
	 argt)
u		rol_msg-EFAULTue 	6 urb_ind0=1((mask &Ul wCMQDTR) ? OW 0
:lLOWi uou0x7) re

=dsb_seriae *filndex,
			)ic __u(__uueal("Eal.r I shoDTRi bau16) (l wCMSET)"t uo	rol_msg(eeI)speu}e 	6 urb_ind0=1((mask &Ul wCMQRsb= ? OW 0
:lLOWi uou0x7) re

=dsb_seriae *filndex,
			)ic __u(__uueal("Eal.r I shodefi bau16) (l wCMSET)"t uo	rol_msg(eeI)speu}e 	ol_msg(0t;__urtup ;_	_uuu
; baudl wCMBIS: ch t_mss ich(S*ts)her Sli**saaof
 Product byDck tmasksi_p		dbg("%sll wCMBIS",divFUNCl wN__t u ,        0x7) */
*ped(mask, lg);
static vo;
	 argt)
u		rol_msg-EFAULTue  ,        0x7)mask &Ul wCMQDTR)(__u	 {
	 re

=dsb_seriae *filst_di_c __u (__uuueal("U6) tby setDTRiIaitru")speuETol_msg(eeI)speuE}__u} 1u x7)mask &Ul wCMQRsb= (__u	 {
	 re

=dsb_seriae *filst_diic __u(__uu	eal("U6) tby setdefiIaitru")speuETol_msg(eeI)speuE}__u} 1uol_msg(0t;__urtup ;_
; baudl wCMBIC: ch t_mss ifth(C3 srs)her Sli**saaof
 Product byDck tmasksi_p		dbg("%sll wCMBIC",divFUNCl wN__t u ,        0x7) */
*ped(mask, lg);
static vo;
	 argt)
u		rol_msg-EFAULTue  ,        0x7)mask &Ul wCMQDTR)(__u	 {
	 re

=dsb_seriae *filLOWiic __u(__uu	eal("U6) tbyg);setDTRiIaitru")speuETol_msg(eeI)speuE}__u}	 1u x7)mask &Ul wCMQRsb= (__u	 {
	 re

=dsb_seriae *filLOWiic __u(__uu	eal("U6) tbyg);setdefiIaitru")speuETol_msg(eeI)speuE}__u} 1uol_msg(0t;__urtup ;_
;uci
	red Ihltd originaclDEimplsm)n
atiTCSET{A,S}{,F,W}h  s
	red TCGET{A,S}oher  o  comucly, howuvcamt_spocessor aI
	red fou thekas
er Shigheralaycase is a lDEdo__u16set_ter
	red ->s/

s****	 hemsel =aten Bp*sofck t ioctonto
	red f

#deio_teak_ctl =	. 
	red
	red/_
; baudl wCGSERIAL: ch n
	 *u see.
=ortn needhe 		rol_msgg*/
et as finfoae *filvate *)pet as followst_	 argt;_
; baudl wCSSERIAL: ch s
	 *u see.
=ortn needhe 		rol_msgs*/
et as finfoae *filvate *)pet as followst_	 argt;_
;ci
	nt Wai   ratalt_off_bee4Tm itm*inpusof(DCD,RI,DSR,Csb= tby ct us
) * -lmask p*so_rt(s arg  ratli**saofTi	retessed in 
	soe |' - l wCMQRNG/DSR/CD/Csbefratmaskor )ed indall rs-    spuaudl wCGICOUNTlard bdsTS-CTScodebetwas.
) i
	nt et in, it issboal.w100 ingsli*ux/	 */

s/sign/
			  .ct the ; baudl wCMIWAIT:__uwhic i	== Fc!=gNULLt (__u	,
	.num_be =	_sleep_on(&== FT2/* Used for TI)speuEsors*e,0x7 rtagnactdithi pi_pr	u x7)sagnac_ps t fo(curicest)
u			rol_msg-ERESTARTSYS;
datex = (__u	vruct dik_0
	=	}	
	dik_ e Usedha
a	u	 {
	
ik_0
=__u (__uuu	rol_msg-EIOf MIWnby ct us =>leal.r == 1uau}a
a	u	ciad_ssume ioctverpt !== 1uau=	}	
	dik_ e Usedc=g	iu
a	uaud Rtl_msg0  {
call rswan
atiardknown scute_be = bits
he n	u	 {
	
	 arg & l wCMQRNG0 && (
ik_0&UDRATERS0QRIiic||_SETT_BAU
	 arg & l wCMQDSR0 && (
ik_0&UDRATERS0QDSR0ic||_SETT_BAU
	 arg & l wCMQCD)  && (
ik_0&UDRATERS0QRLSD0ic||_SETT_BAU
	 arg & l wCMQCsb= && (
ik_0&UDRATERS0QCsb=) u (__uuu	rol_msg0 pr		r}__ua	ci
	r	red O herwio >call rscao'/
ubr ol est scuteschiphapp ned,
	r	red l thsofw
	*/
 inndleofr TIefratmo	unverpt .
	r	red/peuE}__u} 1uol_msg(0t;__urtup ;_uout */
:
u	rtup ;_	_co}cssaud et in thRan nacessa_isosan ealase- t_mss ius
er Shigheralaycasewill d	i
WD*_isome ioctlenifsel{
	sbe
	 iae fkascod)t the ;dbg("%slarg can signed iso-ebetwass0x%04x -  ieck /usr/include/asm/ioctle.h",TivFUNCl wN__,rumdt uuvol_msg(-ENO wCTLCMD);c}isorite =ioctlsi_pd short iwn		(structhrottl
#al_port *port, int from_user,tprivdbg("%sly
ned  %u",TivFUNCl wN__,n=, 0),urb bu)ue *porunlink
	ino(t, 0),ck,
	d ftdi}pd short iwn		(strucunthrottl
#al_port *port, int from_user,tpriv(stre e*/
iusate * p*port)
{
	c int  fo=d , 0),et as riprdbg("%sly
ned  %u",TivFUNCl wN__,n=, 0),urb bu)ue
u=, 0),ck,
	d f),nO o=d
			    FTDue
uFILL_BULKk_t		=, 0),ck,
	d f, 
			    FTDI_
	) < 0 n1po
rcvnum_l->de
			    FTDI_ , 0),num_bulbd spo * Adde esIO_SE < 0 n=, 0),ck,
	d f),ed_ta_cabulk_ca,n=, 0),ck,
	d f),ed_ta_cabulk_ca_lengthO_SE < 0 nallback,
	.write_bulk_ca int chaa	e e*/

=d1po
eubmit
	in(t, 0),ck,
	d ftdi	 {
	e e*/
)
u	eal("%sly
faitru eubmitsor aine BUFS, eal.r %d",divFUNCl wN__,se e*/
) u}udtr(struct u_finitrite =initr(wn		tprintdbg("%s",TivFUNCl wN__t uu1porpe ftdiregistUMc(&ite =hutdou or t uu1porpe ftdiregistUMc(&ite =
	.shutdou or t uu1porpe ftdiregistUMc(&ite =
	.shutdou or t uu1porpe ftdiregistUMc(&ite =
	.shutdou or t uu1porpe ftdiregistUMc(&ite =
	.shRdou or t uu1porpe ftdiregistUMc(&ite =,
	.shutdou or t uu1porpe ftdiregistUMc(&ite =,
	.shutdou or t ui	 {
	erpdolc!=g-10 (__uciaUsednd Product ,
	 erpdolcl thiO or  wd tdiovch Tk tmacro initftdizct "matcherpdol"kaofck tmatchi	/*ASYNCn== 1u d_t str=
	.shut[0].idVrpdolc= erpdol_ sau d_t str=
	.shut[0].idProd * p
	=	od * ue 	6porpe ftdiregistUMc(&ite =
	.shutdou or t uu}
o
iv(sfoaDRIVER_VERhutN ":" DRIVER_DESCcha	e l_msg0di}pd short iwn		(__exitrite =exitr(wn		tprintdbg("%s",TivFUNCl wN__t ui	 {
	erpdolc!=g-10
_u1porpe ftdi_eregistUMc(&ite =
	.shutdou or t uu1porpe ftdi_eregistUMc(&ite =,
	.shutdou or t uu1porpe ftdi_eregistUMc(&ite =,
	.shutdou or t uu1porpe ftdi_eregistUMc(&ite =
	.shRdou or t uu1porpe ftdi_eregistUMc(&ite =
	.shutdou or t uu1porpe ftdi_eregistUMc(&ite =
	.shutdou or t uu1porpe ftdi_eregistUMc(&ite =
	.shutdou or t uu1porpe ftdi_eregistUMc(&ite =hutdou or t ui}pd m iutr=init(ite =initt um iutr=exit(ite =exitt uiMODULE_AUTHOR( DRIVER_AUTHORKt uMODULE_DESCRIPl wN( DRIVER_DESCKt uMODULE_LICENSE("GPL"t uiMODULE_PARM(_ebug, "i"t uMODULE_PARM_DESC(_ebug, "Debugtic stru ratnot"t uiMODULE_PARM(erpdol, "i"t uMODULE_PARM_DESC(erpdol, "Usednd Product ,
	 idVrpdol"t uiMODULE_PARM(=	od * , "i"t uMODULE_PARM_DESC(=	od * , "Usednd Product ,