diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/usb/serial/ftdi_sio.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 2496 |
1 files changed, 2496 insertions, 0 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c new file mode 100644 index 000000000000..4afd905fe2fe --- /dev/null +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -0,0 +1,2496 @@ | |||
1 | /* | ||
2 | * USB FTDI SIO driver | ||
3 | * | ||
4 | * Copyright (C) 1999 - 2001 | ||
5 | * Greg Kroah-Hartman (greg@kroah.com) | ||
6 | * Bill Ryder (bryder@sgi.com) | ||
7 | * Copyright (C) 2002 | ||
8 | * Kuba Ober (kuba@mareimbrium.org) | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * See Documentation/usb/usb-serial.txt for more information on using this driver | ||
16 | * | ||
17 | * See http://ftdi-usb-sio.sourceforge.net for upto date testing info | ||
18 | * and extra documentation | ||
19 | * | ||
20 | * (21/Jul/2004) Ian Abbott | ||
21 | * Incorporated Steven Turner's code to add support for the FT2232C chip. | ||
22 | * The prelimilary port to the 2.6 kernel was by Rus V. Brushkoff. I have | ||
23 | * fixed a couple of things. | ||
24 | * | ||
25 | * (27/May/2004) Ian Abbott | ||
26 | * Improved throttling code, mostly stolen from the WhiteHEAT driver. | ||
27 | * | ||
28 | * (26/Mar/2004) Jan Capek | ||
29 | * Added PID's for ICD-U20/ICD-U40 - incircuit PIC debuggers from CCS Inc. | ||
30 | * | ||
31 | * (09/Feb/2004) Ian Abbott | ||
32 | * Changed full name of USB-UIRT device to avoid "/" character. | ||
33 | * Added FTDI's alternate PID (0x6006) for FT232/245 devices. | ||
34 | * Added PID for "ELV USB Module UO100" from Stefan Frings. | ||
35 | * | ||
36 | * (21/Oct/2003) Ian Abbott | ||
37 | * Renamed some VID/PID macros for Matrix Orbital and Perle Systems | ||
38 | * devices. Removed Matrix Orbital and Perle Systems devices from the | ||
39 | * 8U232AM device table, but left them in the FT232BM table, as they are | ||
40 | * known to use only FT232BM. | ||
41 | * | ||
42 | * (17/Oct/2003) Scott Allen | ||
43 | * Added vid/pid for Perle Systems UltraPort USB serial converters | ||
44 | * | ||
45 | * (21/Sep/2003) Ian Abbott | ||
46 | * Added VID/PID for Omnidirectional Control Technology US101 USB to | ||
47 | * RS-232 adapter (also rebadged as Dick Smith Electronics XH6381). | ||
48 | * VID/PID supplied by Donald Gordon. | ||
49 | * | ||
50 | * (19/Aug/2003) Ian Abbott | ||
51 | * Freed urb's transfer buffer in write bulk callback. | ||
52 | * Omitted some paranoid checks in write bulk callback that don't matter. | ||
53 | * Scheduled work in write bulk callback regardless of port's open count. | ||
54 | * | ||
55 | * (05/Aug/2003) Ian Abbott | ||
56 | * Added VID/PID for ID TECH IDT1221U USB to RS-232 adapter. | ||
57 | * VID/PID provided by Steve Briggs. | ||
58 | * | ||
59 | * (23/Jul/2003) Ian Abbott | ||
60 | * Added PIDs for CrystalFontz 547, 633, 631, 635, 640 and 640 from | ||
61 | * Wayne Wylupski. | ||
62 | * | ||
63 | * (10/Jul/2003) David Glance | ||
64 | * Added PID for DSS-20 SyncStation cradle for Sony-Ericsson P800. | ||
65 | * | ||
66 | * (27/Jun/2003) Ian Abbott | ||
67 | * Reworked the urb handling logic. We have no more pool, but dynamically | ||
68 | * allocate the urb and the transfer buffer on the fly. In testing this | ||
69 | * does not incure any measurable overhead. This also relies on the fact | ||
70 | * that we have proper reference counting logic for urbs. I nicked this | ||
71 | * from Greg KH's Visor driver. | ||
72 | * | ||
73 | * (23/Jun/2003) Ian Abbott | ||
74 | * Reduced flip buffer pushes and corrected a data length test in | ||
75 | * ftdi_read_bulk_callback. | ||
76 | * Defererence pointers after any paranoid checks, not before. | ||
77 | * | ||
78 | * (21/Jun/2003) Erik Nygren | ||
79 | * Added support for Home Electronics Tira-1 IR tranceiver using FT232BM chip. | ||
80 | * See <http://www.home-electro.com/tira1.htm>. Only operates properly | ||
81 | * at 100000 and RTS-CTS, so set custom divisor mode on startup. | ||
82 | * Also force the Tira-1 and USB-UIRT to only use their custom baud rates. | ||
83 | * | ||
84 | * (18/Jun/2003) Ian Abbott | ||
85 | * Added Device ID of the USB relais from Rudolf Gugler (backported from | ||
86 | * Philipp Gühring's patch for 2.5.x kernel). | ||
87 | * Moved read transfer buffer reallocation into startup function. | ||
88 | * Free existing write urb and transfer buffer in startup function. | ||
89 | * Only use urbs in write urb pool that were successfully allocated. | ||
90 | * Moved some constant macros out of functions. | ||
91 | * Minor whitespace and comment changes. | ||
92 | * | ||
93 | * (12/Jun/2003) David Norwood | ||
94 | * Added support for USB-UIRT IR tranceiver using 8U232AM chip. | ||
95 | * See <http://home.earthlink.net/~jrhees/USBUIRT/index.htm>. Only | ||
96 | * operates properly at 312500, so set custom divisor mode on startup. | ||
97 | * | ||
98 | * (12/Jun/2003) Ian Abbott | ||
99 | * Added Sealevel SeaLINK+ 210x, 220x, 240x, 280x vid/pids from Tuan Hoang | ||
100 | * - I've eliminated some that don't seem to exist! | ||
101 | * Added Home Electronics Tira-1 IR transceiver pid from Chris Horn | ||
102 | * Some whitespace/coding-style cleanups | ||
103 | * | ||
104 | * (11/Jun/2003) Ian Abbott | ||
105 | * Fixed unsafe spinlock usage in ftdi_write | ||
106 | * | ||
107 | * (24/Feb/2003) Richard Shooter | ||
108 | * Increase read buffer size to improve read speeds at higher baud rates | ||
109 | * (specifically tested with up to 1Mb/sec at 1.5M baud) | ||
110 | * | ||
111 | * (23/Feb/2003) John Wilkins | ||
112 | * Added Xon/xoff flow control (activating support in the ftdi device) | ||
113 | * Added vid/pid for Videonetworks/Homechoice (UK ISP) | ||
114 | * | ||
115 | * (23/Feb/2003) Bill Ryder | ||
116 | * Added matrix orb device vid/pids from Wayne Wylupski | ||
117 | * | ||
118 | * (19/Feb/2003) Ian Abbott | ||
119 | * For TIOCSSERIAL, set alt_speed to 0 when ASYNC_SPD_MASK value has | ||
120 | * changed to something other than ASYNC_SPD_HI, ASYNC_SPD_VHI, | ||
121 | * ASYNC_SPD_SHI or ASYNC_SPD_WARP. Also, unless ASYNC_SPD_CUST is in | ||
122 | * force, don't bother changing baud rate when custom_divisor has changed. | ||
123 | * | ||
124 | * (18/Feb/2003) Ian Abbott | ||
125 | * Fixed TIOCMGET handling to include state of DTR and RTS, the state | ||
126 | * of which are now saved by set_dtr() and set_rts(). | ||
127 | * Fixed improper storage class for buf in set_dtr() and set_rts(). | ||
128 | * Added FT232BM chip type and support for its extra baud rates (compared | ||
129 | * to FT8U232AM). | ||
130 | * Took account of special case divisor values for highest baud rates of | ||
131 | * FT8U232AM and FT232BM. | ||
132 | * For TIOCSSERIAL, forced alt_speed to 0 when ASYNC_SPD_CUST kludge used, | ||
133 | * as previous alt_speed setting is now stale. | ||
134 | * Moved startup code common between the startup routines for the | ||
135 | * different chip types into a common subroutine. | ||
136 | * | ||
137 | * (17/Feb/2003) Bill Ryder | ||
138 | * Added write urb buffer pool on a per device basis | ||
139 | * Added more checking for open file on callbacks (fixed OOPS) | ||
140 | * Added CrystalFontz 632 and 634 PIDs | ||
141 | * (thanx to CrystalFontz for the sample devices - they flushed out | ||
142 | * some driver bugs) | ||
143 | * Minor debugging message changes | ||
144 | * Added throttle, unthrottle and chars_in_buffer functions | ||
145 | * Fixed FTDI_SIO (the original device) bug | ||
146 | * Fixed some shutdown handling | ||
147 | * | ||
148 | * | ||
149 | * | ||
150 | * | ||
151 | * (07/Jun/2002) Kuba Ober | ||
152 | * Changed FTDI_SIO_BASE_BAUD_TO_DIVISOR macro into ftdi_baud_to_divisor | ||
153 | * function. It was getting too complex. | ||
154 | * Fix the divisor calculation logic which was setting divisor of 0.125 | ||
155 | * instead of 0.5 for fractional parts of divisor equal to 5/8, 6/8, 7/8. | ||
156 | * Also make it bump up the divisor to next integer in case of 7/8 - it's | ||
157 | * a better approximation. | ||
158 | * | ||
159 | * (25/Jul/2002) Bill Ryder inserted Dmitri's TIOCMIWAIT patch | ||
160 | * Not tested by me but it doesn't break anything I use. | ||
161 | * | ||
162 | * (04/Jan/2002) Kuba Ober | ||
163 | * Implemented 38400 baudrate kludge, where it can be substituted with other | ||
164 | * values. That's the only way to set custom baudrates. | ||
165 | * Implemented TIOCSSERIAL, TIOCGSERIAL ioctl's so that setserial is happy. | ||
166 | * FIXME: both baudrate things should eventually go to usbserial.c as other | ||
167 | * devices may need that functionality too. Actually, it can probably be | ||
168 | * merged in serial.c somehow - too many drivers repeat this code over | ||
169 | * and over. | ||
170 | * Fixed baudrate forgetfulness - open() used to reset baudrate to 9600 every time. | ||
171 | * Divisors for baudrates are calculated by a macro. | ||
172 | * Small code cleanups. Ugly whitespace changes for Plato's sake only ;-]. | ||
173 | * | ||
174 | * (04/Nov/2001) Bill Ryder | ||
175 | * Fixed bug in read_bulk_callback where incorrect urb buffer was used. | ||
176 | * Cleaned up write offset calculation | ||
177 | * Added write_room since default values can be incorrect for sio | ||
178 | * Changed write_bulk_callback to use same queue_task as other drivers | ||
179 | * (the previous version caused panics) | ||
180 | * Removed port iteration code since the device only has one I/O port and it | ||
181 | * was wrong anyway. | ||
182 | * | ||
183 | * (31/May/2001) gkh | ||
184 | * Switched from using spinlock to a semaphore, which fixes lots of problems. | ||
185 | * | ||
186 | * (23/May/2001) Bill Ryder | ||
187 | * Added runtime debug patch (thanx Tyson D Sawyer). | ||
188 | * Cleaned up comments for 8U232 | ||
189 | * Added parity, framing and overrun error handling | ||
190 | * Added receive break handling. | ||
191 | * | ||
192 | * (04/08/2001) gb | ||
193 | * Identify version on module load. | ||
194 | * | ||
195 | * (18/March/2001) Bill Ryder | ||
196 | * (Not released) | ||
197 | * Added send break handling. (requires kernel patch too) | ||
198 | * Fixed 8U232AM hardware RTS/CTS etc status reporting. | ||
199 | * Added flipbuf fix copied from generic device | ||
200 | * | ||
201 | * (12/3/2000) Bill Ryder | ||
202 | * Added support for 8U232AM device. | ||
203 | * Moved PID and VIDs into header file only. | ||
204 | * Turned on low-latency for the tty (device will do high baudrates) | ||
205 | * Added shutdown routine to close files when device removed. | ||
206 | * More debug and error message cleanups. | ||
207 | * | ||
208 | * (11/13/2000) Bill Ryder | ||
209 | * Added spinlock protected open code and close code. | ||
210 | * Multiple opens work (sort of - see webpage mentioned above). | ||
211 | * Cleaned up comments. Removed multiple PID/VID definitions. | ||
212 | * Factorised cts/dtr code | ||
213 | * Made use of __FUNCTION__ in dbg's | ||
214 | * | ||
215 | * (11/01/2000) Adam J. Richter | ||
216 | * usb_device_id table support | ||
217 | * | ||
218 | * (10/05/2000) gkh | ||
219 | * Fixed bug with urb->dev not being set properly, now that the usb | ||
220 | * core needs it. | ||
221 | * | ||
222 | * (09/11/2000) gkh | ||
223 | * Removed DEBUG #ifdefs with call to usb_serial_debug_data | ||
224 | * | ||
225 | * (07/19/2000) gkh | ||
226 | * Added module_init and module_exit functions to handle the fact that this | ||
227 | * driver is a loadable module now. | ||
228 | * | ||
229 | * (04/04/2000) Bill Ryder | ||
230 | * Fixed bugs in TCGET/TCSET ioctls (by removing them - they are | ||
231 | * handled elsewhere in the tty io driver chain). | ||
232 | * | ||
233 | * (03/30/2000) Bill Ryder | ||
234 | * Implemented lots of ioctls | ||
235 | * Fixed a race condition in write | ||
236 | * Changed some dbg's to errs | ||
237 | * | ||
238 | * (03/26/2000) gkh | ||
239 | * Split driver up into device specific pieces. | ||
240 | * | ||
241 | */ | ||
242 | |||
243 | /* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */ | ||
244 | /* Thanx to FTDI for so kindly providing details of the protocol required */ | ||
245 | /* to talk to the device */ | ||
246 | /* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */ | ||
247 | |||
248 | #include <linux/config.h> | ||
249 | #include <linux/kernel.h> | ||
250 | #include <linux/errno.h> | ||
251 | #include <linux/init.h> | ||
252 | #include <linux/slab.h> | ||
253 | #include <linux/tty.h> | ||
254 | #include <linux/tty_driver.h> | ||
255 | #include <linux/tty_flip.h> | ||
256 | #include <linux/module.h> | ||
257 | #include <linux/spinlock.h> | ||
258 | #include <asm/uaccess.h> | ||
259 | #include <linux/usb.h> | ||
260 | #include <linux/serial.h> | ||
261 | #include "usb-serial.h" | ||
262 | #include "ftdi_sio.h" | ||
263 | |||
264 | /* | ||
265 | * Version Information | ||
266 | */ | ||
267 | #define DRIVER_VERSION "v1.4.1" | ||
268 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>" | ||
269 | #define DRIVER_DESC "USB FTDI Serial Converters Driver" | ||
270 | |||
271 | static int debug; | ||
272 | |||
273 | static struct usb_device_id id_table_sio [] = { | ||
274 | { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, | ||
275 | { } /* Terminating entry */ | ||
276 | }; | ||
277 | |||
278 | /* | ||
279 | * The 8U232AM has the same API as the sio except for: | ||
280 | * - it can support MUCH higher baudrates; up to: | ||
281 | * o 921600 for RS232 and 2000000 for RS422/485 at 48MHz | ||
282 | * o 230400 at 12MHz | ||
283 | * so .. 8U232AM's baudrate setting codes are different | ||
284 | * - it has a two byte status code. | ||
285 | * - it returns characters every 16ms (the FTDI does it every 40ms) | ||
286 | * | ||
287 | * the bcdDevice value is used to differentiate FT232BM and FT245BM from | ||
288 | * the earlier FT8U232AM and FT8U232BM. For now, include all known VID/PID | ||
289 | * combinations in both tables. | ||
290 | * FIXME: perhaps bcdDevice can also identify 12MHz devices, but I don't know | ||
291 | * if those ever went into mass production. [Ian Abbott] | ||
292 | */ | ||
293 | |||
294 | |||
295 | static struct usb_device_id id_table_8U232AM [] = { | ||
296 | { USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0, 0x3ff) }, | ||
297 | { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) }, | ||
298 | { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) }, | ||
299 | { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID, 0, 0x3ff) }, | ||
300 | { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) }, | ||
301 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, | ||
302 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, | ||
303 | { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0, 0x3ff) }, | ||
304 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) }, | ||
305 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) }, | ||
306 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_547_PID, 0, 0x3ff) }, | ||
307 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_633_PID, 0, 0x3ff) }, | ||
308 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_631_PID, 0, 0x3ff) }, | ||
309 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_635_PID, 0, 0x3ff) }, | ||
310 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_640_PID, 0, 0x3ff) }, | ||
311 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_642_PID, 0, 0x3ff) }, | ||
312 | { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0, 0x3ff) }, | ||
313 | { USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0, 0x3ff) }, | ||
314 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0, 0x3ff) }, | ||
315 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0, 0x3ff) }, | ||
316 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0, 0x3ff) }, | ||
317 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0, 0x3ff) }, | ||
318 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0, 0x3ff) }, | ||
319 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0, 0x3ff) }, | ||
320 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0, 0x3ff) }, | ||
321 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0, 0x3ff) }, | ||
322 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0, 0x3ff) }, | ||
323 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0, 0x3ff) }, | ||
324 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0, 0x3ff) }, | ||
325 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0, 0x3ff) }, | ||
326 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0, 0x3ff) }, | ||
327 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0, 0x3ff) }, | ||
328 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0, 0x3ff) }, | ||
329 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0, 0x3ff) }, | ||
330 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0, 0x3ff) }, | ||
331 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0, 0x3ff) }, | ||
332 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0, 0x3ff) }, | ||
333 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0, 0x3ff) }, | ||
334 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0, 0x3ff) }, | ||
335 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0, 0x3ff) }, | ||
336 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0, 0x3ff) }, | ||
337 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0, 0x3ff) }, | ||
338 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0, 0x3ff) }, | ||
339 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0, 0x3ff) }, | ||
340 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0, 0x3ff) }, | ||
341 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0, 0x3ff) }, | ||
342 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0, 0x3ff) }, | ||
343 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0, 0x3ff) }, | ||
344 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0, 0x3ff) }, | ||
345 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0, 0x3ff) }, | ||
346 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0, 0x3ff) }, | ||
347 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0, 0x3ff) }, | ||
348 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0, 0x3ff) }, | ||
349 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0, 0x3ff) }, | ||
350 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0, 0x3ff) }, | ||
351 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0, 0x3ff) }, | ||
352 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0, 0x3ff) }, | ||
353 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0, 0x3ff) }, | ||
354 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0, 0x3ff) }, | ||
355 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0, 0x3ff) }, | ||
356 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0, 0x3ff) }, | ||
357 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0, 0x3ff) }, | ||
358 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0, 0x3ff) }, | ||
359 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0, 0x3ff) }, | ||
360 | { USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0, 0x3ff) }, | ||
361 | { USB_DEVICE_VER(OCT_VID, OCT_US101_PID, 0, 0x3ff) }, | ||
362 | { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_1, 0, 0x3ff) }, | ||
363 | { USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0, 0x3ff) }, | ||
364 | { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) }, | ||
365 | { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) }, | ||
366 | { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) }, | ||
367 | { USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0, 0x3ff) }, | ||
368 | { USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0, 0x3ff) }, | ||
369 | { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) }, | ||
370 | { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0, 0x3ff) }, | ||
371 | { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0, 0x3ff) }, | ||
372 | { USB_DEVICE_VER(FTDI_RM_VID, FTDI_RMCANVIEW_PID, 0, 0x3ff) }, | ||
373 | { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0, 0x3ff) }, | ||
374 | { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0, 0x3ff) }, | ||
375 | { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0, 0x3ff) }, | ||
376 | { USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0, 0x3ff) }, | ||
377 | { } /* Terminating entry */ | ||
378 | }; | ||
379 | |||
380 | |||
381 | static struct usb_device_id id_table_FT232BM [] = { | ||
382 | { USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0x400, 0xffff) }, | ||
383 | { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) }, | ||
384 | { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) }, | ||
385 | { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID, 0x400, 0xffff) }, | ||
386 | { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) }, | ||
387 | { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) }, | ||
388 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) }, | ||
389 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0x400, 0xffff) }, | ||
390 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_547_PID, 0x400, 0xffff) }, | ||
391 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_633_PID, 0x400, 0xffff) }, | ||
392 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_631_PID, 0x400, 0xffff) }, | ||
393 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_635_PID, 0x400, 0xffff) }, | ||
394 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_640_PID, 0x400, 0xffff) }, | ||
395 | { USB_DEVICE_VER(FTDI_VID, FTDI_XF_642_PID, 0x400, 0xffff) }, | ||
396 | { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0x400, 0xffff) }, | ||
397 | { USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0x400, 0xffff) }, | ||
398 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) }, | ||
399 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) }, | ||
400 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) }, | ||
401 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_3_PID, 0x400, 0xffff) }, | ||
402 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_4_PID, 0x400, 0xffff) }, | ||
403 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) }, | ||
404 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) }, | ||
405 | { USB_DEVICE_VER(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID, 0x400, 0xffff) }, | ||
406 | { USB_DEVICE_VER(FTDI_VID, FTDI_PIEGROUP_PID, 0x400, 0xffff) }, | ||
407 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0x400, 0xffff) }, | ||
408 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0x400, 0xffff) }, | ||
409 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0x400, 0xffff) }, | ||
410 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0x400, 0xffff) }, | ||
411 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0x400, 0xffff) }, | ||
412 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0x400, 0xffff) }, | ||
413 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0x400, 0xffff) }, | ||
414 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0x400, 0xffff) }, | ||
415 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0x400, 0xffff) }, | ||
416 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0x400, 0xffff) }, | ||
417 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0x400, 0xffff) }, | ||
418 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0x400, 0xffff) }, | ||
419 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0x400, 0xffff) }, | ||
420 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0x400, 0xffff) }, | ||
421 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0x400, 0xffff) }, | ||
422 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0x400, 0xffff) }, | ||
423 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0x400, 0xffff) }, | ||
424 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0x400, 0xffff) }, | ||
425 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0x400, 0xffff) }, | ||
426 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0x400, 0xffff) }, | ||
427 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0x400, 0xffff) }, | ||
428 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0x400, 0xffff) }, | ||
429 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0x400, 0xffff) }, | ||
430 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0x400, 0xffff) }, | ||
431 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0x400, 0xffff) }, | ||
432 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0x400, 0xffff) }, | ||
433 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0x400, 0xffff) }, | ||
434 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0x400, 0xffff) }, | ||
435 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0x400, 0xffff) }, | ||
436 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0x400, 0xffff) }, | ||
437 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0x400, 0xffff) }, | ||
438 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0x400, 0xffff) }, | ||
439 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0x400, 0xffff) }, | ||
440 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0x400, 0xffff) }, | ||
441 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0x400, 0xffff) }, | ||
442 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0x400, 0xffff) }, | ||
443 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0x400, 0xffff) }, | ||
444 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0x400, 0xffff) }, | ||
445 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0x400, 0xffff) }, | ||
446 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0x400, 0xffff) }, | ||
447 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0x400, 0xffff) }, | ||
448 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0x400, 0xffff) }, | ||
449 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0x400, 0xffff) }, | ||
450 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0x400, 0xffff) }, | ||
451 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0x400, 0xffff) }, | ||
452 | { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0x400, 0xffff) }, | ||
453 | { USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0x400, 0xffff) }, | ||
454 | { USB_DEVICE_VER(OCT_VID, OCT_US101_PID, 0x400, 0xffff) }, | ||
455 | { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_1, 0x400, 0xffff) }, | ||
456 | { USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0x400, 0xffff) }, | ||
457 | { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0x400, 0xffff) }, | ||
458 | { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0x400, 0xffff) }, | ||
459 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E808_PID, 0x400, 0xffff) }, | ||
460 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E809_PID, 0x400, 0xffff) }, | ||
461 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80A_PID, 0x400, 0xffff) }, | ||
462 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80B_PID, 0x400, 0xffff) }, | ||
463 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80C_PID, 0x400, 0xffff) }, | ||
464 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80D_PID, 0x400, 0xffff) }, | ||
465 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80E_PID, 0x400, 0xffff) }, | ||
466 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80F_PID, 0x400, 0xffff) }, | ||
467 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E888_PID, 0x400, 0xffff) }, | ||
468 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E889_PID, 0x400, 0xffff) }, | ||
469 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88A_PID, 0x400, 0xffff) }, | ||
470 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88B_PID, 0x400, 0xffff) }, | ||
471 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88C_PID, 0x400, 0xffff) }, | ||
472 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88D_PID, 0x400, 0xffff) }, | ||
473 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) }, | ||
474 | { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) }, | ||
475 | { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) }, | ||
476 | { USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) }, | ||
477 | { USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) }, | ||
478 | { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) }, | ||
479 | { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_1_PID, 0x400, 0xffff) }, | ||
480 | { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_2_PID, 0x400, 0xffff) }, | ||
481 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, | ||
482 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, | ||
483 | { USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0x400, 0xffff) }, | ||
484 | { USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0x400, 0xffff) }, | ||
485 | { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0x400, 0xffff) }, | ||
486 | { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0x400, 0xffff) }, | ||
487 | { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0x400, 0xffff) }, | ||
488 | { USB_DEVICE_VER(FTDI_RM_VID, FTDI_RMCANVIEW_PID, 0x400, 0xffff) }, | ||
489 | { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0x400, 0xffff) }, | ||
490 | { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0x400, 0xffff) }, | ||
491 | { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0x400, 0xffff) }, | ||
492 | { USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0x400, 0xffff) }, | ||
493 | { } /* Terminating entry */ | ||
494 | }; | ||
495 | |||
496 | |||
497 | static struct usb_device_id id_table_USB_UIRT [] = { | ||
498 | { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) }, | ||
499 | { } /* Terminating entry */ | ||
500 | }; | ||
501 | |||
502 | |||
503 | static struct usb_device_id id_table_HE_TIRA1 [] = { | ||
504 | { USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) }, | ||
505 | { } /* Terminating entry */ | ||
506 | }; | ||
507 | |||
508 | |||
509 | static struct usb_device_id id_table_FT2232C[] = { | ||
510 | { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, | ||
511 | { } /* Terminating entry */ | ||
512 | }; | ||
513 | |||
514 | |||
515 | static struct usb_device_id id_table_combined [] = { | ||
516 | { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, | ||
517 | { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, | ||
518 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, | ||
519 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, | ||
520 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID) }, | ||
521 | { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, | ||
522 | { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, | ||
523 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, | ||
524 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, | ||
525 | { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, | ||
526 | { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, | ||
527 | { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) }, | ||
528 | { USB_DEVICE(FTDI_VID, FTDI_XF_633_PID) }, | ||
529 | { USB_DEVICE(FTDI_VID, FTDI_XF_631_PID) }, | ||
530 | { USB_DEVICE(FTDI_VID, FTDI_XF_635_PID) }, | ||
531 | { USB_DEVICE(FTDI_VID, FTDI_XF_640_PID) }, | ||
532 | { USB_DEVICE(FTDI_VID, FTDI_XF_642_PID) }, | ||
533 | { USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) }, | ||
534 | { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, | ||
535 | { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) }, | ||
536 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) }, | ||
537 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) }, | ||
538 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) }, | ||
539 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_3_PID, 0x400, 0xffff) }, | ||
540 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_4_PID, 0x400, 0xffff) }, | ||
541 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) }, | ||
542 | { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) }, | ||
543 | { USB_DEVICE_VER(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID, 0x400, 0xffff) }, | ||
544 | { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, | ||
545 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, | ||
546 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, | ||
547 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, | ||
548 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) }, | ||
549 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) }, | ||
550 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) }, | ||
551 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) }, | ||
552 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_2_PID) }, | ||
553 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_1_PID) }, | ||
554 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_2_PID) }, | ||
555 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_1_PID) }, | ||
556 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_2_PID) }, | ||
557 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_3_PID) }, | ||
558 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_4_PID) }, | ||
559 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_1_PID) }, | ||
560 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_2_PID) }, | ||
561 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_3_PID) }, | ||
562 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_4_PID) }, | ||
563 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_1_PID) }, | ||
564 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_2_PID) }, | ||
565 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_3_PID) }, | ||
566 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_4_PID) }, | ||
567 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_1_PID) }, | ||
568 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_2_PID) }, | ||
569 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_3_PID) }, | ||
570 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_4_PID) }, | ||
571 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_5_PID) }, | ||
572 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_6_PID) }, | ||
573 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_7_PID) }, | ||
574 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_8_PID) }, | ||
575 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_1_PID) }, | ||
576 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_2_PID) }, | ||
577 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_3_PID) }, | ||
578 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_4_PID) }, | ||
579 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_5_PID) }, | ||
580 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_6_PID) }, | ||
581 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_7_PID) }, | ||
582 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_8_PID) }, | ||
583 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_1_PID) }, | ||
584 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_2_PID) }, | ||
585 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_3_PID) }, | ||
586 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_4_PID) }, | ||
587 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_5_PID) }, | ||
588 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) }, | ||
589 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) }, | ||
590 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, | ||
591 | { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, | ||
592 | { USB_DEVICE(OCT_VID, OCT_US101_PID) }, | ||
593 | { USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) }, | ||
594 | { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) }, | ||
595 | { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_1) }, | ||
596 | { USB_DEVICE(FTDI_VID, PROTEGO_R2X0) }, | ||
597 | { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) }, | ||
598 | { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) }, | ||
599 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) }, | ||
600 | { USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) }, | ||
601 | { USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) }, | ||
602 | { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) }, | ||
603 | { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_1_PID, 0x400, 0xffff) }, | ||
604 | { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_2_PID, 0x400, 0xffff) }, | ||
605 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, | ||
606 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, | ||
607 | { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) }, | ||
608 | { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) }, | ||
609 | { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, | ||
610 | { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, | ||
611 | { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, | ||
612 | { USB_DEVICE(FTDI_RM_VID, FTDI_RMCANVIEW_PID) }, | ||
613 | { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, | ||
614 | { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, | ||
615 | { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, | ||
616 | { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, | ||
617 | { } /* Terminating entry */ | ||
618 | }; | ||
619 | |||
620 | MODULE_DEVICE_TABLE (usb, id_table_combined); | ||
621 | |||
622 | static struct usb_driver ftdi_driver = { | ||
623 | .name = "ftdi_sio", | ||
624 | .probe = usb_serial_probe, | ||
625 | .disconnect = usb_serial_disconnect, | ||
626 | .id_table = id_table_combined, | ||
627 | }; | ||
628 | |||
629 | static char *ftdi_chip_name[] = { | ||
630 | [SIO] = "SIO", /* the serial part of FT8U100AX */ | ||
631 | [FT8U232AM] = "FT8U232AM", | ||
632 | [FT232BM] = "FT232BM", | ||
633 | [FT2232C] = "FT2232C", | ||
634 | }; | ||
635 | |||
636 | |||
637 | /* Constants for read urb and write urb */ | ||
638 | #define BUFSZ 512 | ||
639 | #define PKTSZ 64 | ||
640 | |||
641 | /* rx_flags */ | ||
642 | #define THROTTLED 0x01 | ||
643 | #define ACTUALLY_THROTTLED 0x02 | ||
644 | |||
645 | struct ftdi_private { | ||
646 | ftdi_chip_type_t chip_type; | ||
647 | /* type of the device, either SIO or FT8U232AM */ | ||
648 | int baud_base; /* baud base clock for divisor setting */ | ||
649 | int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */ | ||
650 | __u16 last_set_data_urb_value ; | ||
651 | /* the last data state set - needed for doing a break */ | ||
652 | int write_offset; /* This is the offset in the usb data block to write the serial data - | ||
653 | * it is different between devices | ||
654 | */ | ||
655 | int flags; /* some ASYNC_xxxx flags are supported */ | ||
656 | unsigned long last_dtr_rts; /* saved modem control outputs */ | ||
657 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | ||
658 | char prev_status, diff_status; /* Used for TIOCMIWAIT */ | ||
659 | __u8 rx_flags; /* receive state flags (throttling) */ | ||
660 | spinlock_t rx_lock; /* spinlock for receive state */ | ||
661 | |||
662 | __u16 interface; /* FT2232C port interface (0 for FT232/245) */ | ||
663 | |||
664 | int force_baud; /* if non-zero, force the baud rate to this value */ | ||
665 | int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ | ||
666 | }; | ||
667 | |||
668 | /* Used for TIOCMIWAIT */ | ||
669 | #define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD) | ||
670 | #define FTDI_STATUS_B1_MASK (FTDI_RS_BI) | ||
671 | /* End TIOCMIWAIT */ | ||
672 | |||
673 | #define FTDI_IMPL_ASYNC_FLAGS = ( ASYNC_SPD_HI | ASYNC_SPD_VHI \ | ||
674 | ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP ) | ||
675 | |||
676 | /* function prototypes for a FTDI serial converter */ | ||
677 | static int ftdi_SIO_startup (struct usb_serial *serial); | ||
678 | static int ftdi_8U232AM_startup (struct usb_serial *serial); | ||
679 | static int ftdi_FT232BM_startup (struct usb_serial *serial); | ||
680 | static int ftdi_FT2232C_startup (struct usb_serial *serial); | ||
681 | static int ftdi_USB_UIRT_startup (struct usb_serial *serial); | ||
682 | static int ftdi_HE_TIRA1_startup (struct usb_serial *serial); | ||
683 | static void ftdi_shutdown (struct usb_serial *serial); | ||
684 | static int ftdi_open (struct usb_serial_port *port, struct file *filp); | ||
685 | static void ftdi_close (struct usb_serial_port *port, struct file *filp); | ||
686 | static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count); | ||
687 | static int ftdi_write_room (struct usb_serial_port *port); | ||
688 | static int ftdi_chars_in_buffer (struct usb_serial_port *port); | ||
689 | static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs); | ||
690 | static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs); | ||
691 | static void ftdi_process_read (struct usb_serial_port *port); | ||
692 | static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old); | ||
693 | static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file); | ||
694 | static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear); | ||
695 | static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); | ||
696 | static void ftdi_break_ctl (struct usb_serial_port *port, int break_state ); | ||
697 | static void ftdi_throttle (struct usb_serial_port *port); | ||
698 | static void ftdi_unthrottle (struct usb_serial_port *port); | ||
699 | |||
700 | static unsigned short int ftdi_232am_baud_base_to_divisor (int baud, int base); | ||
701 | static unsigned short int ftdi_232am_baud_to_divisor (int baud); | ||
702 | static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base); | ||
703 | static __u32 ftdi_232bm_baud_to_divisor (int baud); | ||
704 | |||
705 | static struct usb_serial_device_type ftdi_SIO_device = { | ||
706 | .owner = THIS_MODULE, | ||
707 | .name = "FTDI SIO", | ||
708 | .id_table = id_table_sio, | ||
709 | .num_interrupt_in = 0, | ||
710 | .num_bulk_in = 1, | ||
711 | .num_bulk_out = 1, | ||
712 | .num_ports = 1, | ||
713 | .open = ftdi_open, | ||
714 | .close = ftdi_close, | ||
715 | .throttle = ftdi_throttle, | ||
716 | .unthrottle = ftdi_unthrottle, | ||
717 | .write = ftdi_write, | ||
718 | .write_room = ftdi_write_room, | ||
719 | .chars_in_buffer = ftdi_chars_in_buffer, | ||
720 | .read_bulk_callback = ftdi_read_bulk_callback, | ||
721 | .write_bulk_callback = ftdi_write_bulk_callback, | ||
722 | .tiocmget = ftdi_tiocmget, | ||
723 | .tiocmset = ftdi_tiocmset, | ||
724 | .ioctl = ftdi_ioctl, | ||
725 | .set_termios = ftdi_set_termios, | ||
726 | .break_ctl = ftdi_break_ctl, | ||
727 | .attach = ftdi_SIO_startup, | ||
728 | .shutdown = ftdi_shutdown, | ||
729 | }; | ||
730 | |||
731 | static struct usb_serial_device_type ftdi_8U232AM_device = { | ||
732 | .owner = THIS_MODULE, | ||
733 | .name = "FTDI 8U232AM Compatible", | ||
734 | .id_table = id_table_8U232AM, | ||
735 | .num_interrupt_in = 0, | ||
736 | .num_bulk_in = 1, | ||
737 | .num_bulk_out = 1, | ||
738 | .num_ports = 1, | ||
739 | .open = ftdi_open, | ||
740 | .close = ftdi_close, | ||
741 | .throttle = ftdi_throttle, | ||
742 | .unthrottle = ftdi_unthrottle, | ||
743 | .write = ftdi_write, | ||
744 | .write_room = ftdi_write_room, | ||
745 | .chars_in_buffer = ftdi_chars_in_buffer, | ||
746 | .read_bulk_callback = ftdi_read_bulk_callback, | ||
747 | .write_bulk_callback = ftdi_write_bulk_callback, | ||
748 | .tiocmget = ftdi_tiocmget, | ||
749 | .tiocmset = ftdi_tiocmset, | ||
750 | .ioctl = ftdi_ioctl, | ||
751 | .set_termios = ftdi_set_termios, | ||
752 | .break_ctl = ftdi_break_ctl, | ||
753 | .attach = ftdi_8U232AM_startup, | ||
754 | .shutdown = ftdi_shutdown, | ||
755 | }; | ||
756 | |||
757 | static struct usb_serial_device_type ftdi_FT232BM_device = { | ||
758 | .owner = THIS_MODULE, | ||
759 | .name = "FTDI FT232BM Compatible", | ||
760 | .id_table = id_table_FT232BM, | ||
761 | .num_interrupt_in = 0, | ||
762 | .num_bulk_in = 1, | ||
763 | .num_bulk_out = 1, | ||
764 | .num_ports = 1, | ||
765 | .open = ftdi_open, | ||
766 | .close = ftdi_close, | ||
767 | .throttle = ftdi_throttle, | ||
768 | .unthrottle = ftdi_unthrottle, | ||
769 | .write = ftdi_write, | ||
770 | .write_room = ftdi_write_room, | ||
771 | .chars_in_buffer = ftdi_chars_in_buffer, | ||
772 | .read_bulk_callback = ftdi_read_bulk_callback, | ||
773 | .write_bulk_callback = ftdi_write_bulk_callback, | ||
774 | .tiocmget = ftdi_tiocmget, | ||
775 | .tiocmset = ftdi_tiocmset, | ||
776 | .ioctl = ftdi_ioctl, | ||
777 | .set_termios = ftdi_set_termios, | ||
778 | .break_ctl = ftdi_break_ctl, | ||
779 | .attach = ftdi_FT232BM_startup, | ||
780 | .shutdown = ftdi_shutdown, | ||
781 | }; | ||
782 | |||
783 | static struct usb_serial_device_type ftdi_FT2232C_device = { | ||
784 | .owner = THIS_MODULE, | ||
785 | .name = "FTDI FT2232C Compatible", | ||
786 | .id_table = id_table_FT2232C, | ||
787 | .num_interrupt_in = 0, | ||
788 | .num_bulk_in = 1, | ||
789 | .num_bulk_out = 1, | ||
790 | .num_ports = 1, | ||
791 | .open = ftdi_open, | ||
792 | .close = ftdi_close, | ||
793 | .throttle = ftdi_throttle, | ||
794 | .unthrottle = ftdi_unthrottle, | ||
795 | .write = ftdi_write, | ||
796 | .write_room = ftdi_write_room, | ||
797 | .chars_in_buffer = ftdi_chars_in_buffer, | ||
798 | .read_bulk_callback = ftdi_read_bulk_callback, | ||
799 | .write_bulk_callback = ftdi_write_bulk_callback, | ||
800 | .tiocmget = ftdi_tiocmget, | ||
801 | .tiocmset = ftdi_tiocmset, | ||
802 | .ioctl = ftdi_ioctl, | ||
803 | .set_termios = ftdi_set_termios, | ||
804 | .break_ctl = ftdi_break_ctl, | ||
805 | .attach = ftdi_FT2232C_startup, | ||
806 | .shutdown = ftdi_shutdown, | ||
807 | }; | ||
808 | |||
809 | static struct usb_serial_device_type ftdi_USB_UIRT_device = { | ||
810 | .owner = THIS_MODULE, | ||
811 | .name = "USB-UIRT Infrared Tranceiver", | ||
812 | .id_table = id_table_USB_UIRT, | ||
813 | .num_interrupt_in = 0, | ||
814 | .num_bulk_in = 1, | ||
815 | .num_bulk_out = 1, | ||
816 | .num_ports = 1, | ||
817 | .open = ftdi_open, | ||
818 | .close = ftdi_close, | ||
819 | .throttle = ftdi_throttle, | ||
820 | .unthrottle = ftdi_unthrottle, | ||
821 | .write = ftdi_write, | ||
822 | .write_room = ftdi_write_room, | ||
823 | .chars_in_buffer = ftdi_chars_in_buffer, | ||
824 | .read_bulk_callback = ftdi_read_bulk_callback, | ||
825 | .write_bulk_callback = ftdi_write_bulk_callback, | ||
826 | .tiocmget = ftdi_tiocmget, | ||
827 | .tiocmset = ftdi_tiocmset, | ||
828 | .ioctl = ftdi_ioctl, | ||
829 | .set_termios = ftdi_set_termios, | ||
830 | .break_ctl = ftdi_break_ctl, | ||
831 | .attach = ftdi_USB_UIRT_startup, | ||
832 | .shutdown = ftdi_shutdown, | ||
833 | }; | ||
834 | |||
835 | /* The TIRA1 is based on a FT232BM which requires a fixed baud rate of 100000 | ||
836 | * and which requires RTS-CTS to be enabled. */ | ||
837 | static struct usb_serial_device_type ftdi_HE_TIRA1_device = { | ||
838 | .owner = THIS_MODULE, | ||
839 | .name = "Home-Electronics TIRA-1 IR Transceiver", | ||
840 | .id_table = id_table_HE_TIRA1, | ||
841 | .num_interrupt_in = 0, | ||
842 | .num_bulk_in = 1, | ||
843 | .num_bulk_out = 1, | ||
844 | .num_ports = 1, | ||
845 | .open = ftdi_open, | ||
846 | .close = ftdi_close, | ||
847 | .throttle = ftdi_throttle, | ||
848 | .unthrottle = ftdi_unthrottle, | ||
849 | .write = ftdi_write, | ||
850 | .write_room = ftdi_write_room, | ||
851 | .chars_in_buffer = ftdi_chars_in_buffer, | ||
852 | .read_bulk_callback = ftdi_read_bulk_callback, | ||
853 | .write_bulk_callback = ftdi_write_bulk_callback, | ||
854 | .tiocmget = ftdi_tiocmget, | ||
855 | .tiocmset = ftdi_tiocmset, | ||
856 | .ioctl = ftdi_ioctl, | ||
857 | .set_termios = ftdi_set_termios, | ||
858 | .break_ctl = ftdi_break_ctl, | ||
859 | .attach = ftdi_HE_TIRA1_startup, | ||
860 | .shutdown = ftdi_shutdown, | ||
861 | }; | ||
862 | |||
863 | |||
864 | |||
865 | #define WDR_TIMEOUT 5000 /* default urb timeout */ | ||
866 | |||
867 | /* High and low are for DTR, RTS etc etc */ | ||
868 | #define HIGH 1 | ||
869 | #define LOW 0 | ||
870 | |||
871 | /* | ||
872 | * *************************************************************************** | ||
873 | * Utlity functions | ||
874 | * *************************************************************************** | ||
875 | */ | ||
876 | |||
877 | static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) | ||
878 | { | ||
879 | unsigned short int divisor; | ||
880 | int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left | ||
881 | if ((divisor3 & 0x7) == 7) divisor3 ++; // round x.7/8 up to x+1 | ||
882 | divisor = divisor3 >> 3; | ||
883 | divisor3 &= 0x7; | ||
884 | if (divisor3 == 1) divisor |= 0xc000; else // 0.125 | ||
885 | if (divisor3 >= 4) divisor |= 0x4000; else // 0.5 | ||
886 | if (divisor3 != 0) divisor |= 0x8000; // 0.25 | ||
887 | if (divisor == 1) divisor = 0; /* special case for maximum baud rate */ | ||
888 | return divisor; | ||
889 | } | ||
890 | |||
891 | static unsigned short int ftdi_232am_baud_to_divisor(int baud) | ||
892 | { | ||
893 | return(ftdi_232am_baud_base_to_divisor(baud, 48000000)); | ||
894 | } | ||
895 | |||
896 | static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) | ||
897 | { | ||
898 | static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; | ||
899 | __u32 divisor; | ||
900 | int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left | ||
901 | divisor = divisor3 >> 3; | ||
902 | divisor |= (__u32)divfrac[divisor3 & 0x7] << 14; | ||
903 | /* Deal with special cases for highest baud rates. */ | ||
904 | if (divisor == 1) divisor = 0; else // 1.0 | ||
905 | if (divisor == 0x4001) divisor = 1; // 1.5 | ||
906 | return divisor; | ||
907 | } | ||
908 | |||
909 | static __u32 ftdi_232bm_baud_to_divisor(int baud) | ||
910 | { | ||
911 | return(ftdi_232bm_baud_base_to_divisor(baud, 48000000)); | ||
912 | } | ||
913 | |||
914 | static int set_rts(struct usb_serial_port *port, int high_or_low) | ||
915 | { | ||
916 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
917 | char *buf; | ||
918 | unsigned ftdi_high_or_low; | ||
919 | int rv; | ||
920 | |||
921 | buf = kmalloc(1, GFP_NOIO); | ||
922 | if (!buf) | ||
923 | return -ENOMEM; | ||
924 | |||
925 | if (high_or_low) { | ||
926 | ftdi_high_or_low = FTDI_SIO_SET_RTS_HIGH; | ||
927 | priv->last_dtr_rts |= TIOCM_RTS; | ||
928 | } else { | ||
929 | ftdi_high_or_low = FTDI_SIO_SET_RTS_LOW; | ||
930 | priv->last_dtr_rts &= ~TIOCM_RTS; | ||
931 | } | ||
932 | rv = usb_control_msg(port->serial->dev, | ||
933 | usb_sndctrlpipe(port->serial->dev, 0), | ||
934 | FTDI_SIO_SET_MODEM_CTRL_REQUEST, | ||
935 | FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, | ||
936 | ftdi_high_or_low, priv->interface, | ||
937 | buf, 0, WDR_TIMEOUT); | ||
938 | |||
939 | kfree(buf); | ||
940 | return rv; | ||
941 | } | ||
942 | |||
943 | |||
944 | static int set_dtr(struct usb_serial_port *port, int high_or_low) | ||
945 | { | ||
946 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
947 | char *buf; | ||
948 | unsigned ftdi_high_or_low; | ||
949 | int rv; | ||
950 | |||
951 | buf = kmalloc(1, GFP_NOIO); | ||
952 | if (!buf) | ||
953 | return -ENOMEM; | ||
954 | |||
955 | if (high_or_low) { | ||
956 | ftdi_high_or_low = FTDI_SIO_SET_DTR_HIGH; | ||
957 | priv->last_dtr_rts |= TIOCM_DTR; | ||
958 | } else { | ||
959 | ftdi_high_or_low = FTDI_SIO_SET_DTR_LOW; | ||
960 | priv->last_dtr_rts &= ~TIOCM_DTR; | ||
961 | } | ||
962 | rv = usb_control_msg(port->serial->dev, | ||
963 | usb_sndctrlpipe(port->serial->dev, 0), | ||
964 | FTDI_SIO_SET_MODEM_CTRL_REQUEST, | ||
965 | FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, | ||
966 | ftdi_high_or_low, priv->interface, | ||
967 | buf, 0, WDR_TIMEOUT); | ||
968 | |||
969 | kfree(buf); | ||
970 | return rv; | ||
971 | } | ||
972 | |||
973 | |||
974 | static __u32 get_ftdi_divisor(struct usb_serial_port * port); | ||
975 | |||
976 | |||
977 | static int change_speed(struct usb_serial_port *port) | ||
978 | { | ||
979 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
980 | char *buf; | ||
981 | __u16 urb_value; | ||
982 | __u16 urb_index; | ||
983 | __u32 urb_index_value; | ||
984 | int rv; | ||
985 | |||
986 | buf = kmalloc(1, GFP_NOIO); | ||
987 | if (!buf) | ||
988 | return -ENOMEM; | ||
989 | |||
990 | urb_index_value = get_ftdi_divisor(port); | ||
991 | urb_value = (__u16)urb_index_value; | ||
992 | urb_index = (__u16)(urb_index_value >> 16); | ||
993 | if (priv->interface) { /* FT2232C */ | ||
994 | urb_index = (__u16)((urb_index << 8) | priv->interface); | ||
995 | } | ||
996 | |||
997 | rv = usb_control_msg(port->serial->dev, | ||
998 | usb_sndctrlpipe(port->serial->dev, 0), | ||
999 | FTDI_SIO_SET_BAUDRATE_REQUEST, | ||
1000 | FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, | ||
1001 | urb_value, urb_index, | ||
1002 | buf, 0, 100); | ||
1003 | |||
1004 | kfree(buf); | ||
1005 | return rv; | ||
1006 | } | ||
1007 | |||
1008 | |||
1009 | static __u32 get_ftdi_divisor(struct usb_serial_port * port) | ||
1010 | { /* get_ftdi_divisor */ | ||
1011 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1012 | __u32 div_value = 0; | ||
1013 | int div_okay = 1; | ||
1014 | int baud; | ||
1015 | |||
1016 | /* | ||
1017 | * The logic involved in setting the baudrate can be cleanly split in 3 steps. | ||
1018 | * Obtaining the actual baud rate is a little tricky since unix traditionally | ||
1019 | * somehow ignored the possibility to set non-standard baud rates. | ||
1020 | * 1. Standard baud rates are set in tty->termios->c_cflag | ||
1021 | * 2. If these are not enough, you can set any speed using alt_speed as follows: | ||
1022 | * - set tty->termios->c_cflag speed to B38400 | ||
1023 | * - set your real speed in tty->alt_speed; it gets ignored when | ||
1024 | * alt_speed==0, (or) | ||
1025 | * - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows: | ||
1026 | * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], this just | ||
1027 | * sets alt_speed to (HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800) | ||
1028 | * ** Steps 1, 2 are done courtesy of tty_get_baud_rate | ||
1029 | * 3. You can also set baud rate by setting custom divisor as follows | ||
1030 | * - set tty->termios->c_cflag speed to B38400 | ||
1031 | * - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows: | ||
1032 | * o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST | ||
1033 | * o custom_divisor set to baud_base / your_new_baudrate | ||
1034 | * ** Step 3 is done courtesy of code borrowed from serial.c - I should really | ||
1035 | * spend some time and separate+move this common code to serial.c, it is | ||
1036 | * replicated in nearly every serial driver you see. | ||
1037 | */ | ||
1038 | |||
1039 | /* 1. Get the baud rate from the tty settings, this observes alt_speed hack */ | ||
1040 | |||
1041 | baud = tty_get_baud_rate(port->tty); | ||
1042 | dbg("%s - tty_get_baud_rate reports speed %d", __FUNCTION__, baud); | ||
1043 | |||
1044 | /* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */ | ||
1045 | |||
1046 | if (baud == 38400 && | ||
1047 | ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && | ||
1048 | (priv->custom_divisor)) { | ||
1049 | baud = priv->baud_base / priv->custom_divisor; | ||
1050 | dbg("%s - custom divisor %d sets baud rate to %d", __FUNCTION__, priv->custom_divisor, baud); | ||
1051 | } | ||
1052 | |||
1053 | /* 3. Convert baudrate to device-specific divisor */ | ||
1054 | |||
1055 | if (!baud) baud = 9600; | ||
1056 | switch(priv->chip_type) { | ||
1057 | case SIO: /* SIO chip */ | ||
1058 | switch(baud) { | ||
1059 | case 300: div_value = ftdi_sio_b300; break; | ||
1060 | case 600: div_value = ftdi_sio_b600; break; | ||
1061 | case 1200: div_value = ftdi_sio_b1200; break; | ||
1062 | case 2400: div_value = ftdi_sio_b2400; break; | ||
1063 | case 4800: div_value = ftdi_sio_b4800; break; | ||
1064 | case 9600: div_value = ftdi_sio_b9600; break; | ||
1065 | case 19200: div_value = ftdi_sio_b19200; break; | ||
1066 | case 38400: div_value = ftdi_sio_b38400; break; | ||
1067 | case 57600: div_value = ftdi_sio_b57600; break; | ||
1068 | case 115200: div_value = ftdi_sio_b115200; break; | ||
1069 | } /* baud */ | ||
1070 | if (div_value == 0) { | ||
1071 | dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__, baud); | ||
1072 | div_value = ftdi_sio_b9600; | ||
1073 | div_okay = 0; | ||
1074 | } | ||
1075 | break; | ||
1076 | case FT8U232AM: /* 8U232AM chip */ | ||
1077 | if (baud <= 3000000) { | ||
1078 | div_value = ftdi_232am_baud_to_divisor(baud); | ||
1079 | } else { | ||
1080 | dbg("%s - Baud rate too high!", __FUNCTION__); | ||
1081 | div_value = ftdi_232am_baud_to_divisor(9600); | ||
1082 | div_okay = 0; | ||
1083 | } | ||
1084 | break; | ||
1085 | case FT232BM: /* FT232BM chip */ | ||
1086 | case FT2232C: /* FT2232C chip */ | ||
1087 | if (baud <= 3000000) { | ||
1088 | div_value = ftdi_232bm_baud_to_divisor(baud); | ||
1089 | } else { | ||
1090 | dbg("%s - Baud rate too high!", __FUNCTION__); | ||
1091 | div_value = ftdi_232bm_baud_to_divisor(9600); | ||
1092 | div_okay = 0; | ||
1093 | } | ||
1094 | break; | ||
1095 | } /* priv->chip_type */ | ||
1096 | |||
1097 | if (div_okay) { | ||
1098 | dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s", | ||
1099 | __FUNCTION__, baud, (unsigned long)div_value, | ||
1100 | ftdi_chip_name[priv->chip_type]); | ||
1101 | } | ||
1102 | |||
1103 | return(div_value); | ||
1104 | } | ||
1105 | |||
1106 | |||
1107 | static int get_serial_info(struct usb_serial_port * port, struct serial_struct __user * retinfo) | ||
1108 | { | ||
1109 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1110 | struct serial_struct tmp; | ||
1111 | |||
1112 | if (!retinfo) | ||
1113 | return -EFAULT; | ||
1114 | memset(&tmp, 0, sizeof(tmp)); | ||
1115 | tmp.flags = priv->flags; | ||
1116 | tmp.baud_base = priv->baud_base; | ||
1117 | tmp.custom_divisor = priv->custom_divisor; | ||
1118 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
1119 | return -EFAULT; | ||
1120 | return 0; | ||
1121 | } /* get_serial_info */ | ||
1122 | |||
1123 | |||
1124 | static int set_serial_info(struct usb_serial_port * port, struct serial_struct __user * newinfo) | ||
1125 | { /* set_serial_info */ | ||
1126 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1127 | struct serial_struct new_serial; | ||
1128 | struct ftdi_private old_priv; | ||
1129 | |||
1130 | if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) | ||
1131 | return -EFAULT; | ||
1132 | old_priv = * priv; | ||
1133 | |||
1134 | /* Do error checking and permission checking */ | ||
1135 | |||
1136 | if (!capable(CAP_SYS_ADMIN)) { | ||
1137 | if (((new_serial.flags & ~ASYNC_USR_MASK) != | ||
1138 | (priv->flags & ~ASYNC_USR_MASK))) | ||
1139 | return -EPERM; | ||
1140 | priv->flags = ((priv->flags & ~ASYNC_USR_MASK) | | ||
1141 | (new_serial.flags & ASYNC_USR_MASK)); | ||
1142 | priv->custom_divisor = new_serial.custom_divisor; | ||
1143 | goto check_and_exit; | ||
1144 | } | ||
1145 | |||
1146 | if ((new_serial.baud_base != priv->baud_base) && | ||
1147 | (new_serial.baud_base < 9600)) | ||
1148 | return -EINVAL; | ||
1149 | |||
1150 | /* Make the changes - these are privileged changes! */ | ||
1151 | |||
1152 | priv->flags = ((priv->flags & ~ASYNC_FLAGS) | | ||
1153 | (new_serial.flags & ASYNC_FLAGS)); | ||
1154 | priv->custom_divisor = new_serial.custom_divisor; | ||
1155 | |||
1156 | port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
1157 | |||
1158 | check_and_exit: | ||
1159 | if ((old_priv.flags & ASYNC_SPD_MASK) != | ||
1160 | (priv->flags & ASYNC_SPD_MASK)) { | ||
1161 | if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | ||
1162 | port->tty->alt_speed = 57600; | ||
1163 | else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | ||
1164 | port->tty->alt_speed = 115200; | ||
1165 | else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | ||
1166 | port->tty->alt_speed = 230400; | ||
1167 | else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | ||
1168 | port->tty->alt_speed = 460800; | ||
1169 | else | ||
1170 | port->tty->alt_speed = 0; | ||
1171 | } | ||
1172 | if (((old_priv.flags & ASYNC_SPD_MASK) != | ||
1173 | (priv->flags & ASYNC_SPD_MASK)) || | ||
1174 | (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && | ||
1175 | (old_priv.custom_divisor != priv->custom_divisor))) { | ||
1176 | change_speed(port); | ||
1177 | } | ||
1178 | |||
1179 | return (0); | ||
1180 | |||
1181 | } /* set_serial_info */ | ||
1182 | |||
1183 | |||
1184 | /* | ||
1185 | * *************************************************************************** | ||
1186 | * Sysfs Attribute | ||
1187 | * *************************************************************************** | ||
1188 | */ | ||
1189 | |||
1190 | static ssize_t show_latency_timer(struct device *dev, char *buf) | ||
1191 | { | ||
1192 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
1193 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1194 | struct usb_device *udev; | ||
1195 | unsigned short latency = 0; | ||
1196 | int rv = 0; | ||
1197 | |||
1198 | udev = to_usb_device(dev); | ||
1199 | |||
1200 | dbg("%s",__FUNCTION__); | ||
1201 | |||
1202 | rv = usb_control_msg(udev, | ||
1203 | usb_rcvctrlpipe(udev, 0), | ||
1204 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST, | ||
1205 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, | ||
1206 | 0, priv->interface, | ||
1207 | (char*) &latency, 1, WDR_TIMEOUT); | ||
1208 | |||
1209 | if (rv < 0) { | ||
1210 | dev_err(dev, "Unable to read latency timer: %i", rv); | ||
1211 | return -EIO; | ||
1212 | } | ||
1213 | return sprintf(buf, "%i\n", latency); | ||
1214 | } | ||
1215 | |||
1216 | /* Write a new value of the latency timer, in units of milliseconds. */ | ||
1217 | static ssize_t store_latency_timer(struct device *dev, const char *valbuf, | ||
1218 | size_t count) | ||
1219 | { | ||
1220 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
1221 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1222 | struct usb_device *udev; | ||
1223 | char buf[1]; | ||
1224 | int v = simple_strtoul(valbuf, NULL, 10); | ||
1225 | int rv = 0; | ||
1226 | |||
1227 | udev = to_usb_device(dev); | ||
1228 | |||
1229 | dbg("%s: setting latency timer = %i", __FUNCTION__, v); | ||
1230 | |||
1231 | rv = usb_control_msg(udev, | ||
1232 | usb_sndctrlpipe(udev, 0), | ||
1233 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST, | ||
1234 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, | ||
1235 | v, priv->interface, | ||
1236 | buf, 0, WDR_TIMEOUT); | ||
1237 | |||
1238 | if (rv < 0) { | ||
1239 | dev_err(dev, "Unable to write latency timer: %i", rv); | ||
1240 | return -EIO; | ||
1241 | } | ||
1242 | |||
1243 | return count; | ||
1244 | } | ||
1245 | |||
1246 | /* Write an event character directly to the FTDI register. The ASCII | ||
1247 | value is in the low 8 bits, with the enable bit in the 9th bit. */ | ||
1248 | static ssize_t store_event_char(struct device *dev, const char *valbuf, | ||
1249 | size_t count) | ||
1250 | { | ||
1251 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
1252 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1253 | struct usb_device *udev; | ||
1254 | char buf[1]; | ||
1255 | int v = simple_strtoul(valbuf, NULL, 10); | ||
1256 | int rv = 0; | ||
1257 | |||
1258 | udev = to_usb_device(dev); | ||
1259 | |||
1260 | dbg("%s: setting event char = %i", __FUNCTION__, v); | ||
1261 | |||
1262 | rv = usb_control_msg(udev, | ||
1263 | usb_sndctrlpipe(udev, 0), | ||
1264 | FTDI_SIO_SET_EVENT_CHAR_REQUEST, | ||
1265 | FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE, | ||
1266 | v, priv->interface, | ||
1267 | buf, 0, WDR_TIMEOUT); | ||
1268 | |||
1269 | if (rv < 0) { | ||
1270 | dbg("Unable to write event character: %i", rv); | ||
1271 | return -EIO; | ||
1272 | } | ||
1273 | |||
1274 | return count; | ||
1275 | } | ||
1276 | |||
1277 | static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); | ||
1278 | static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); | ||
1279 | |||
1280 | static void create_sysfs_attrs(struct usb_serial *serial) | ||
1281 | { | ||
1282 | struct ftdi_private *priv; | ||
1283 | struct usb_device *udev; | ||
1284 | |||
1285 | dbg("%s",__FUNCTION__); | ||
1286 | |||
1287 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1288 | udev = serial->dev; | ||
1289 | |||
1290 | /* XXX I've no idea if the original SIO supports the event_char | ||
1291 | * sysfs parameter, so I'm playing it safe. */ | ||
1292 | if (priv->chip_type != SIO) { | ||
1293 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); | ||
1294 | device_create_file(&udev->dev, &dev_attr_event_char); | ||
1295 | if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) { | ||
1296 | device_create_file(&udev->dev, &dev_attr_latency_timer); | ||
1297 | } | ||
1298 | } | ||
1299 | } | ||
1300 | |||
1301 | static void remove_sysfs_attrs(struct usb_serial *serial) | ||
1302 | { | ||
1303 | struct ftdi_private *priv; | ||
1304 | struct usb_device *udev; | ||
1305 | |||
1306 | dbg("%s",__FUNCTION__); | ||
1307 | |||
1308 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1309 | udev = serial->dev; | ||
1310 | |||
1311 | /* XXX see create_sysfs_attrs */ | ||
1312 | if (priv->chip_type != SIO) { | ||
1313 | device_remove_file(&udev->dev, &dev_attr_event_char); | ||
1314 | if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) { | ||
1315 | device_remove_file(&udev->dev, &dev_attr_latency_timer); | ||
1316 | } | ||
1317 | } | ||
1318 | |||
1319 | } | ||
1320 | |||
1321 | /* | ||
1322 | * *************************************************************************** | ||
1323 | * FTDI driver specific functions | ||
1324 | * *************************************************************************** | ||
1325 | */ | ||
1326 | |||
1327 | /* Common startup subroutine */ | ||
1328 | /* Called from ftdi_SIO_startup, etc. */ | ||
1329 | static int ftdi_common_startup (struct usb_serial *serial) | ||
1330 | { | ||
1331 | struct usb_serial_port *port = serial->port[0]; | ||
1332 | struct ftdi_private *priv; | ||
1333 | |||
1334 | dbg("%s",__FUNCTION__); | ||
1335 | |||
1336 | priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); | ||
1337 | if (!priv){ | ||
1338 | err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private)); | ||
1339 | return -ENOMEM; | ||
1340 | } | ||
1341 | memset(priv, 0, sizeof(*priv)); | ||
1342 | |||
1343 | spin_lock_init(&priv->rx_lock); | ||
1344 | init_waitqueue_head(&priv->delta_msr_wait); | ||
1345 | /* This will push the characters through immediately rather | ||
1346 | than queue a task to deliver them */ | ||
1347 | priv->flags = ASYNC_LOW_LATENCY; | ||
1348 | |||
1349 | /* Increase the size of read buffers */ | ||
1350 | if (port->bulk_in_buffer) { | ||
1351 | kfree (port->bulk_in_buffer); | ||
1352 | } | ||
1353 | port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL); | ||
1354 | if (!port->bulk_in_buffer) { | ||
1355 | kfree (priv); | ||
1356 | return -ENOMEM; | ||
1357 | } | ||
1358 | if (port->read_urb) { | ||
1359 | port->read_urb->transfer_buffer = port->bulk_in_buffer; | ||
1360 | port->read_urb->transfer_buffer_length = BUFSZ; | ||
1361 | } | ||
1362 | |||
1363 | /* Free port's existing write urb and transfer buffer. */ | ||
1364 | if (port->write_urb) { | ||
1365 | usb_free_urb (port->write_urb); | ||
1366 | port->write_urb = NULL; | ||
1367 | } | ||
1368 | if (port->bulk_out_buffer) { | ||
1369 | kfree (port->bulk_out_buffer); | ||
1370 | port->bulk_out_buffer = NULL; | ||
1371 | } | ||
1372 | |||
1373 | usb_set_serial_port_data(serial->port[0], priv); | ||
1374 | |||
1375 | return (0); | ||
1376 | } | ||
1377 | |||
1378 | |||
1379 | /* Startup for the SIO chip */ | ||
1380 | /* Called from usbserial:serial_probe */ | ||
1381 | static int ftdi_SIO_startup (struct usb_serial *serial) | ||
1382 | { | ||
1383 | struct ftdi_private *priv; | ||
1384 | int err; | ||
1385 | |||
1386 | dbg("%s",__FUNCTION__); | ||
1387 | |||
1388 | err = ftdi_common_startup(serial); | ||
1389 | if (err){ | ||
1390 | return (err); | ||
1391 | } | ||
1392 | |||
1393 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1394 | priv->chip_type = SIO; | ||
1395 | priv->baud_base = 12000000 / 16; | ||
1396 | priv->write_offset = 1; | ||
1397 | |||
1398 | return (0); | ||
1399 | } | ||
1400 | |||
1401 | /* Startup for the 8U232AM chip */ | ||
1402 | /* Called from usbserial:serial_probe */ | ||
1403 | static int ftdi_8U232AM_startup (struct usb_serial *serial) | ||
1404 | { /* ftdi_8U232AM_startup */ | ||
1405 | struct ftdi_private *priv; | ||
1406 | int err; | ||
1407 | |||
1408 | dbg("%s",__FUNCTION__); | ||
1409 | err = ftdi_common_startup(serial); | ||
1410 | if (err){ | ||
1411 | return (err); | ||
1412 | } | ||
1413 | |||
1414 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1415 | priv->chip_type = FT8U232AM; | ||
1416 | priv->baud_base = 48000000 / 2; /* Would be / 16, but FTDI supports 0.125, 0.25 and 0.5 divisor fractions! */ | ||
1417 | |||
1418 | create_sysfs_attrs(serial); | ||
1419 | |||
1420 | return (0); | ||
1421 | } /* ftdi_8U232AM_startup */ | ||
1422 | |||
1423 | /* Startup for the FT232BM chip */ | ||
1424 | /* Called from usbserial:serial_probe */ | ||
1425 | static int ftdi_FT232BM_startup (struct usb_serial *serial) | ||
1426 | { /* ftdi_FT232BM_startup */ | ||
1427 | struct ftdi_private *priv; | ||
1428 | int err; | ||
1429 | |||
1430 | dbg("%s",__FUNCTION__); | ||
1431 | err = ftdi_common_startup(serial); | ||
1432 | if (err){ | ||
1433 | return (err); | ||
1434 | } | ||
1435 | |||
1436 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1437 | priv->chip_type = FT232BM; | ||
1438 | priv->baud_base = 48000000 / 2; /* Would be / 16, but FT232BM supports multiple of 0.125 divisor fractions! */ | ||
1439 | |||
1440 | create_sysfs_attrs(serial); | ||
1441 | |||
1442 | return (0); | ||
1443 | } /* ftdi_FT232BM_startup */ | ||
1444 | |||
1445 | /* Startup for the FT2232C chip */ | ||
1446 | /* Called from usbserial:serial_probe */ | ||
1447 | static int ftdi_FT2232C_startup (struct usb_serial *serial) | ||
1448 | { /* ftdi_FT2232C_startup */ | ||
1449 | struct ftdi_private *priv; | ||
1450 | int err; | ||
1451 | int inter; | ||
1452 | |||
1453 | dbg("%s",__FUNCTION__); | ||
1454 | err = ftdi_common_startup(serial); | ||
1455 | if (err){ | ||
1456 | return (err); | ||
1457 | } | ||
1458 | |||
1459 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1460 | priv->chip_type = FT2232C; | ||
1461 | inter = serial->interface->altsetting->desc.bInterfaceNumber; | ||
1462 | |||
1463 | if (inter) { | ||
1464 | priv->interface = INTERFACE_B; | ||
1465 | } | ||
1466 | else { | ||
1467 | priv->interface = INTERFACE_A; | ||
1468 | } | ||
1469 | priv->baud_base = 48000000 / 2; /* Would be / 16, but FT2232C supports multiple of 0.125 divisor fractions! */ | ||
1470 | |||
1471 | create_sysfs_attrs(serial); | ||
1472 | |||
1473 | return (0); | ||
1474 | } /* ftdi_FT2232C_startup */ | ||
1475 | |||
1476 | /* Startup for the USB-UIRT device, which requires hardwired baudrate (38400 gets mapped to 312500) */ | ||
1477 | /* Called from usbserial:serial_probe */ | ||
1478 | static int ftdi_USB_UIRT_startup (struct usb_serial *serial) | ||
1479 | { /* ftdi_USB_UIRT_startup */ | ||
1480 | struct ftdi_private *priv; | ||
1481 | int err; | ||
1482 | |||
1483 | dbg("%s",__FUNCTION__); | ||
1484 | err = ftdi_8U232AM_startup(serial); | ||
1485 | if (err){ | ||
1486 | return (err); | ||
1487 | } | ||
1488 | |||
1489 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1490 | priv->flags |= ASYNC_SPD_CUST; | ||
1491 | priv->custom_divisor = 77; | ||
1492 | priv->force_baud = B38400; | ||
1493 | |||
1494 | return (0); | ||
1495 | } /* ftdi_USB_UIRT_startup */ | ||
1496 | |||
1497 | /* Startup for the HE-TIRA1 device, which requires hardwired | ||
1498 | * baudrate (38400 gets mapped to 100000) */ | ||
1499 | static int ftdi_HE_TIRA1_startup (struct usb_serial *serial) | ||
1500 | { /* ftdi_HE_TIRA1_startup */ | ||
1501 | struct ftdi_private *priv; | ||
1502 | int err; | ||
1503 | |||
1504 | dbg("%s",__FUNCTION__); | ||
1505 | err = ftdi_FT232BM_startup(serial); | ||
1506 | if (err){ | ||
1507 | return (err); | ||
1508 | } | ||
1509 | |||
1510 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1511 | priv->flags |= ASYNC_SPD_CUST; | ||
1512 | priv->custom_divisor = 240; | ||
1513 | priv->force_baud = B38400; | ||
1514 | priv->force_rtscts = 1; | ||
1515 | |||
1516 | return (0); | ||
1517 | } /* ftdi_HE_TIRA1_startup */ | ||
1518 | |||
1519 | |||
1520 | /* ftdi_shutdown is called from usbserial:usb_serial_disconnect | ||
1521 | * it is called when the usb device is disconnected | ||
1522 | * | ||
1523 | * usbserial:usb_serial_disconnect | ||
1524 | * calls __serial_close for each open of the port | ||
1525 | * shutdown is called then (ie ftdi_shutdown) | ||
1526 | */ | ||
1527 | |||
1528 | |||
1529 | static void ftdi_shutdown (struct usb_serial *serial) | ||
1530 | { /* ftdi_shutdown */ | ||
1531 | |||
1532 | struct usb_serial_port *port = serial->port[0]; | ||
1533 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1534 | |||
1535 | dbg("%s", __FUNCTION__); | ||
1536 | |||
1537 | remove_sysfs_attrs(serial); | ||
1538 | |||
1539 | /* all open ports are closed at this point | ||
1540 | * (by usbserial.c:__serial_close, which calls ftdi_close) | ||
1541 | */ | ||
1542 | |||
1543 | if (priv) { | ||
1544 | usb_set_serial_port_data(port, NULL); | ||
1545 | kfree(priv); | ||
1546 | } | ||
1547 | } /* ftdi_shutdown */ | ||
1548 | |||
1549 | |||
1550 | static int ftdi_open (struct usb_serial_port *port, struct file *filp) | ||
1551 | { /* ftdi_open */ | ||
1552 | struct termios tmp_termios; | ||
1553 | struct usb_device *dev = port->serial->dev; | ||
1554 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1555 | unsigned long flags; | ||
1556 | |||
1557 | int result = 0; | ||
1558 | char buf[1]; /* Needed for the usb_control_msg I think */ | ||
1559 | |||
1560 | dbg("%s", __FUNCTION__); | ||
1561 | |||
1562 | |||
1563 | port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
1564 | |||
1565 | /* No error checking for this (will get errors later anyway) */ | ||
1566 | /* See ftdi_sio.h for description of what is reset */ | ||
1567 | usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
1568 | FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, | ||
1569 | FTDI_SIO_RESET_SIO, | ||
1570 | priv->interface, buf, 0, WDR_TIMEOUT); | ||
1571 | |||
1572 | /* Termios defaults are set by usb_serial_init. We don't change | ||
1573 | port->tty->termios - this would loose speed settings, etc. | ||
1574 | This is same behaviour as serial.c/rs_open() - Kuba */ | ||
1575 | |||
1576 | /* ftdi_set_termios will send usb control messages */ | ||
1577 | ftdi_set_termios(port, &tmp_termios); | ||
1578 | |||
1579 | /* FIXME: Flow control might be enabled, so it should be checked - | ||
1580 | we have no control of defaults! */ | ||
1581 | /* Turn on RTS and DTR since we are not flow controlling by default */ | ||
1582 | if (set_dtr(port, HIGH) < 0) { | ||
1583 | err("%s Error from DTR HIGH urb", __FUNCTION__); | ||
1584 | } | ||
1585 | if (set_rts(port, HIGH) < 0){ | ||
1586 | err("%s Error from RTS HIGH urb", __FUNCTION__); | ||
1587 | } | ||
1588 | |||
1589 | /* Not throttled */ | ||
1590 | spin_lock_irqsave(&priv->rx_lock, flags); | ||
1591 | priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); | ||
1592 | spin_unlock_irqrestore(&priv->rx_lock, flags); | ||
1593 | |||
1594 | /* Start reading from the device */ | ||
1595 | usb_fill_bulk_urb(port->read_urb, dev, | ||
1596 | usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress), | ||
1597 | port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, | ||
1598 | ftdi_read_bulk_callback, port); | ||
1599 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
1600 | if (result) | ||
1601 | err("%s - failed submitting read urb, error %d", __FUNCTION__, result); | ||
1602 | |||
1603 | |||
1604 | return result; | ||
1605 | } /* ftdi_open */ | ||
1606 | |||
1607 | |||
1608 | |||
1609 | /* | ||
1610 | * usbserial:__serial_close only calls ftdi_close if the point is open | ||
1611 | * | ||
1612 | * This only gets called when it is the last close | ||
1613 | * | ||
1614 | * | ||
1615 | */ | ||
1616 | |||
1617 | static void ftdi_close (struct usb_serial_port *port, struct file *filp) | ||
1618 | { /* ftdi_close */ | ||
1619 | unsigned int c_cflag = port->tty->termios->c_cflag; | ||
1620 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1621 | char buf[1]; | ||
1622 | |||
1623 | dbg("%s", __FUNCTION__); | ||
1624 | |||
1625 | if (c_cflag & HUPCL){ | ||
1626 | /* Disable flow control */ | ||
1627 | if (usb_control_msg(port->serial->dev, | ||
1628 | usb_sndctrlpipe(port->serial->dev, 0), | ||
1629 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
1630 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
1631 | 0, priv->interface, buf, 0, | ||
1632 | WDR_TIMEOUT) < 0) { | ||
1633 | err("error from flowcontrol urb"); | ||
1634 | } | ||
1635 | |||
1636 | /* drop DTR */ | ||
1637 | if (set_dtr(port, LOW) < 0){ | ||
1638 | err("Error from DTR LOW urb"); | ||
1639 | } | ||
1640 | /* drop RTS */ | ||
1641 | if (set_rts(port, LOW) < 0) { | ||
1642 | err("Error from RTS LOW urb"); | ||
1643 | } | ||
1644 | } /* Note change no line if hupcl is off */ | ||
1645 | |||
1646 | /* shutdown our bulk read */ | ||
1647 | if (port->read_urb) | ||
1648 | usb_kill_urb(port->read_urb); | ||
1649 | } /* ftdi_close */ | ||
1650 | |||
1651 | |||
1652 | |||
1653 | /* The SIO requires the first byte to have: | ||
1654 | * B0 1 | ||
1655 | * B1 0 | ||
1656 | * B2..7 length of message excluding byte 0 | ||
1657 | * | ||
1658 | * The new devices do not require this byte | ||
1659 | */ | ||
1660 | static int ftdi_write (struct usb_serial_port *port, | ||
1661 | const unsigned char *buf, int count) | ||
1662 | { /* ftdi_write */ | ||
1663 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1664 | struct urb *urb; | ||
1665 | unsigned char *buffer; | ||
1666 | int data_offset ; /* will be 1 for the SIO and 0 otherwise */ | ||
1667 | int status; | ||
1668 | int transfer_size; | ||
1669 | |||
1670 | dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count); | ||
1671 | |||
1672 | if (count == 0) { | ||
1673 | dbg("write request of 0 bytes"); | ||
1674 | return 0; | ||
1675 | } | ||
1676 | |||
1677 | data_offset = priv->write_offset; | ||
1678 | dbg("data_offset set to %d",data_offset); | ||
1679 | |||
1680 | /* Determine total transfer size */ | ||
1681 | transfer_size = count; | ||
1682 | if (data_offset > 0) { | ||
1683 | /* Original sio needs control bytes too... */ | ||
1684 | transfer_size += (data_offset * | ||
1685 | ((count + (PKTSZ - 1 - data_offset)) / | ||
1686 | (PKTSZ - data_offset))); | ||
1687 | } | ||
1688 | |||
1689 | buffer = kmalloc (transfer_size, GFP_ATOMIC); | ||
1690 | if (!buffer) { | ||
1691 | err("%s ran out of kernel memory for urb ...", __FUNCTION__); | ||
1692 | return -ENOMEM; | ||
1693 | } | ||
1694 | |||
1695 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
1696 | if (!urb) { | ||
1697 | err("%s - no more free urbs", __FUNCTION__); | ||
1698 | kfree (buffer); | ||
1699 | return -ENOMEM; | ||
1700 | } | ||
1701 | |||
1702 | /* Copy data */ | ||
1703 | if (data_offset > 0) { | ||
1704 | /* Original sio requires control byte at start of each packet. */ | ||
1705 | int user_pktsz = PKTSZ - data_offset; | ||
1706 | int todo = count; | ||
1707 | unsigned char *first_byte = buffer; | ||
1708 | const unsigned char *current_position = buf; | ||
1709 | |||
1710 | while (todo > 0) { | ||
1711 | if (user_pktsz > todo) { | ||
1712 | user_pktsz = todo; | ||
1713 | } | ||
1714 | /* Write the control byte at the front of the packet*/ | ||
1715 | *first_byte = 1 | ((user_pktsz) << 2); | ||
1716 | /* Copy data for packet */ | ||
1717 | memcpy (first_byte + data_offset, | ||
1718 | current_position, user_pktsz); | ||
1719 | first_byte += user_pktsz + data_offset; | ||
1720 | current_position += user_pktsz; | ||
1721 | todo -= user_pktsz; | ||
1722 | } | ||
1723 | } else { | ||
1724 | /* No control byte required. */ | ||
1725 | /* Copy in the data to send */ | ||
1726 | memcpy (buffer, buf, count); | ||
1727 | } | ||
1728 | |||
1729 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, buffer); | ||
1730 | |||
1731 | /* fill the buffer and send it */ | ||
1732 | usb_fill_bulk_urb(urb, port->serial->dev, | ||
1733 | usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), | ||
1734 | buffer, transfer_size, | ||
1735 | ftdi_write_bulk_callback, port); | ||
1736 | |||
1737 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
1738 | if (status) { | ||
1739 | err("%s - failed submitting write urb, error %d", __FUNCTION__, status); | ||
1740 | count = status; | ||
1741 | kfree (buffer); | ||
1742 | } | ||
1743 | |||
1744 | /* we are done with this urb, so let the host driver | ||
1745 | * really free it when it is finished with it */ | ||
1746 | usb_free_urb (urb); | ||
1747 | |||
1748 | dbg("%s write returning: %d", __FUNCTION__, count); | ||
1749 | return count; | ||
1750 | } /* ftdi_write */ | ||
1751 | |||
1752 | |||
1753 | /* This function may get called when the device is closed */ | ||
1754 | |||
1755 | static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | ||
1756 | { | ||
1757 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | ||
1758 | |||
1759 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | ||
1760 | kfree (urb->transfer_buffer); | ||
1761 | |||
1762 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1763 | |||
1764 | if (urb->status) { | ||
1765 | dbg("nonzero write bulk status received: %d", urb->status); | ||
1766 | return; | ||
1767 | } | ||
1768 | |||
1769 | schedule_work(&port->work); | ||
1770 | } /* ftdi_write_bulk_callback */ | ||
1771 | |||
1772 | |||
1773 | static int ftdi_write_room( struct usb_serial_port *port ) | ||
1774 | { | ||
1775 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1776 | |||
1777 | /* | ||
1778 | * We really can take anything the user throws at us | ||
1779 | * but let's pick a nice big number to tell the tty | ||
1780 | * layer that we have lots of free space | ||
1781 | */ | ||
1782 | return 2048; | ||
1783 | } /* ftdi_write_room */ | ||
1784 | |||
1785 | |||
1786 | static int ftdi_chars_in_buffer (struct usb_serial_port *port) | ||
1787 | { /* ftdi_chars_in_buffer */ | ||
1788 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1789 | |||
1790 | /* | ||
1791 | * We can't really account for how much data we | ||
1792 | * have sent out, but hasn't made it through to the | ||
1793 | * device, so just tell the tty layer that everything | ||
1794 | * is flushed. | ||
1795 | */ | ||
1796 | return 0; | ||
1797 | } /* ftdi_chars_in_buffer */ | ||
1798 | |||
1799 | |||
1800 | |||
1801 | static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | ||
1802 | { /* ftdi_read_bulk_callback */ | ||
1803 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | ||
1804 | struct tty_struct *tty; | ||
1805 | struct ftdi_private *priv; | ||
1806 | |||
1807 | if (urb->number_of_packets > 0) { | ||
1808 | err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__, | ||
1809 | urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets ); | ||
1810 | err("%s transfer_flags %x ", __FUNCTION__,urb->transfer_flags ); | ||
1811 | } | ||
1812 | |||
1813 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1814 | |||
1815 | if (port->open_count <= 0) | ||
1816 | return; | ||
1817 | |||
1818 | tty = port->tty; | ||
1819 | if (!tty) { | ||
1820 | dbg("%s - bad tty pointer - exiting",__FUNCTION__); | ||
1821 | return; | ||
1822 | } | ||
1823 | |||
1824 | priv = usb_get_serial_port_data(port); | ||
1825 | if (!priv) { | ||
1826 | dbg("%s - bad port private data pointer - exiting", __FUNCTION__); | ||
1827 | return; | ||
1828 | } | ||
1829 | |||
1830 | if (urb != port->read_urb) { | ||
1831 | err("%s - Not my urb!", __FUNCTION__); | ||
1832 | } | ||
1833 | |||
1834 | if (urb->status) { | ||
1835 | /* This will happen at close every time so it is a dbg not an err */ | ||
1836 | dbg("(this is ok on close) nonzero read bulk status received: %d", urb->status); | ||
1837 | return; | ||
1838 | } | ||
1839 | |||
1840 | /* If throttled, delay receive processing until unthrottled. */ | ||
1841 | spin_lock(&priv->rx_lock); | ||
1842 | if (priv->rx_flags & THROTTLED) { | ||
1843 | dbg("Deferring read urb processing until unthrottled"); | ||
1844 | priv->rx_flags |= ACTUALLY_THROTTLED; | ||
1845 | spin_unlock(&priv->rx_lock); | ||
1846 | return; | ||
1847 | } | ||
1848 | spin_unlock(&priv->rx_lock); | ||
1849 | |||
1850 | ftdi_process_read(port); | ||
1851 | |||
1852 | } /* ftdi_read_bulk_callback */ | ||
1853 | |||
1854 | |||
1855 | static void ftdi_process_read (struct usb_serial_port *port) | ||
1856 | { /* ftdi_process_read */ | ||
1857 | struct urb *urb; | ||
1858 | struct tty_struct *tty; | ||
1859 | struct ftdi_private *priv; | ||
1860 | char error_flag; | ||
1861 | unsigned char *data; | ||
1862 | |||
1863 | int i; | ||
1864 | int result; | ||
1865 | int need_flip; | ||
1866 | int packet_offset; | ||
1867 | |||
1868 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1869 | |||
1870 | if (port->open_count <= 0) | ||
1871 | return; | ||
1872 | |||
1873 | tty = port->tty; | ||
1874 | if (!tty) { | ||
1875 | dbg("%s - bad tty pointer - exiting",__FUNCTION__); | ||
1876 | return; | ||
1877 | } | ||
1878 | |||
1879 | priv = usb_get_serial_port_data(port); | ||
1880 | if (!priv) { | ||
1881 | dbg("%s - bad port private data pointer - exiting", __FUNCTION__); | ||
1882 | return; | ||
1883 | } | ||
1884 | |||
1885 | urb = port->read_urb; | ||
1886 | if (!urb) { | ||
1887 | dbg("%s - bad read_urb pointer - exiting", __FUNCTION__); | ||
1888 | return; | ||
1889 | } | ||
1890 | |||
1891 | data = urb->transfer_buffer; | ||
1892 | |||
1893 | /* The first two bytes of every read packet are status */ | ||
1894 | if (urb->actual_length > 2) { | ||
1895 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | ||
1896 | } else { | ||
1897 | dbg("Status only: %03oo %03oo",data[0],data[1]); | ||
1898 | } | ||
1899 | |||
1900 | |||
1901 | /* TO DO -- check for hung up line and handle appropriately: */ | ||
1902 | /* send hangup */ | ||
1903 | /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */ | ||
1904 | /* if CD is dropped and the line is not CLOCAL then we should hangup */ | ||
1905 | |||
1906 | need_flip = 0; | ||
1907 | for (packet_offset=0; packet_offset < urb->actual_length; packet_offset += PKTSZ) { | ||
1908 | /* Compare new line status to the old one, signal if different */ | ||
1909 | if (priv != NULL) { | ||
1910 | char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK; | ||
1911 | if (new_status != priv->prev_status) { | ||
1912 | priv->diff_status |= new_status ^ priv->prev_status; | ||
1913 | wake_up_interruptible(&priv->delta_msr_wait); | ||
1914 | priv->prev_status = new_status; | ||
1915 | } | ||
1916 | } | ||
1917 | |||
1918 | /* Handle errors and break */ | ||
1919 | error_flag = TTY_NORMAL; | ||
1920 | /* Although the device uses a bitmask and hence can have multiple */ | ||
1921 | /* errors on a packet - the order here sets the priority the */ | ||
1922 | /* error is returned to the tty layer */ | ||
1923 | |||
1924 | if ( data[packet_offset+1] & FTDI_RS_OE ) { | ||
1925 | error_flag = TTY_OVERRUN; | ||
1926 | dbg("OVERRRUN error"); | ||
1927 | } | ||
1928 | if ( data[packet_offset+1] & FTDI_RS_BI ) { | ||
1929 | error_flag = TTY_BREAK; | ||
1930 | dbg("BREAK received"); | ||
1931 | } | ||
1932 | if ( data[packet_offset+1] & FTDI_RS_PE ) { | ||
1933 | error_flag = TTY_PARITY; | ||
1934 | dbg("PARITY error"); | ||
1935 | } | ||
1936 | if ( data[packet_offset+1] & FTDI_RS_FE ) { | ||
1937 | error_flag = TTY_FRAME; | ||
1938 | dbg("FRAMING error"); | ||
1939 | } | ||
1940 | if (urb->actual_length > packet_offset + 2) { | ||
1941 | for (i = 2; (i < PKTSZ) && ((i+packet_offset) < urb->actual_length); ++i) { | ||
1942 | /* have to make sure we don't overflow the buffer | ||
1943 | with tty_insert_flip_char's */ | ||
1944 | if(tty->flip.count >= TTY_FLIPBUF_SIZE) { | ||
1945 | tty_flip_buffer_push(tty); | ||
1946 | } | ||
1947 | /* Note that the error flag is duplicated for | ||
1948 | every character received since we don't know | ||
1949 | which character it applied to */ | ||
1950 | tty_insert_flip_char(tty, data[packet_offset+i], error_flag); | ||
1951 | } | ||
1952 | need_flip = 1; | ||
1953 | } | ||
1954 | |||
1955 | #ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW | ||
1956 | /* if a parity error is detected you get status packets forever | ||
1957 | until a character is sent without a parity error. | ||
1958 | This doesn't work well since the application receives a never | ||
1959 | ending stream of bad data - even though new data hasn't been sent. | ||
1960 | Therefore I (bill) have taken this out. | ||
1961 | However - this might make sense for framing errors and so on | ||
1962 | so I am leaving the code in for now. | ||
1963 | */ | ||
1964 | else { | ||
1965 | if (error_flag != TTY_NORMAL){ | ||
1966 | dbg("error_flag is not normal"); | ||
1967 | /* In this case it is just status - if that is an error send a bad character */ | ||
1968 | if(tty->flip.count >= TTY_FLIPBUF_SIZE) { | ||
1969 | tty_flip_buffer_push(tty); | ||
1970 | } | ||
1971 | tty_insert_flip_char(tty, 0xff, error_flag); | ||
1972 | need_flip = 1; | ||
1973 | } | ||
1974 | } | ||
1975 | #endif | ||
1976 | } /* "for(packet_offset=0..." */ | ||
1977 | |||
1978 | /* Low latency */ | ||
1979 | if (need_flip) { | ||
1980 | tty_flip_buffer_push(tty); | ||
1981 | } | ||
1982 | |||
1983 | /* if the port is closed stop trying to read */ | ||
1984 | if (port->open_count > 0){ | ||
1985 | /* Continue trying to always read */ | ||
1986 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | ||
1987 | usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), | ||
1988 | port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, | ||
1989 | ftdi_read_bulk_callback, port); | ||
1990 | |||
1991 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
1992 | if (result) | ||
1993 | err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); | ||
1994 | } | ||
1995 | |||
1996 | return; | ||
1997 | } /* ftdi_process_read */ | ||
1998 | |||
1999 | |||
2000 | static void ftdi_break_ctl( struct usb_serial_port *port, int break_state ) | ||
2001 | { | ||
2002 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
2003 | __u16 urb_value = 0; | ||
2004 | char buf[1]; | ||
2005 | |||
2006 | /* break_state = -1 to turn on break, and 0 to turn off break */ | ||
2007 | /* see drivers/char/tty_io.c to see it used */ | ||
2008 | /* last_set_data_urb_value NEVER has the break bit set in it */ | ||
2009 | |||
2010 | if (break_state) { | ||
2011 | urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK; | ||
2012 | } else { | ||
2013 | urb_value = priv->last_set_data_urb_value; | ||
2014 | } | ||
2015 | |||
2016 | |||
2017 | if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), | ||
2018 | FTDI_SIO_SET_DATA_REQUEST, | ||
2019 | FTDI_SIO_SET_DATA_REQUEST_TYPE, | ||
2020 | urb_value , priv->interface, | ||
2021 | buf, 0, WDR_TIMEOUT) < 0) { | ||
2022 | err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state); | ||
2023 | } | ||
2024 | |||
2025 | dbg("%s break state is %d - urb is %d", __FUNCTION__,break_state, urb_value); | ||
2026 | |||
2027 | } | ||
2028 | |||
2029 | |||
2030 | /* old_termios contains the original termios settings and tty->termios contains | ||
2031 | * the new setting to be used | ||
2032 | * WARNING: set_termios calls this with old_termios in kernel space | ||
2033 | */ | ||
2034 | |||
2035 | static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_termios) | ||
2036 | { /* ftdi_termios */ | ||
2037 | struct usb_device *dev = port->serial->dev; | ||
2038 | unsigned int cflag = port->tty->termios->c_cflag; | ||
2039 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
2040 | __u16 urb_value; /* will hold the new flags */ | ||
2041 | char buf[1]; /* Perhaps I should dynamically alloc this? */ | ||
2042 | |||
2043 | // Added for xon/xoff support | ||
2044 | unsigned int iflag = port->tty->termios->c_iflag; | ||
2045 | unsigned char vstop; | ||
2046 | unsigned char vstart; | ||
2047 | |||
2048 | dbg("%s", __FUNCTION__); | ||
2049 | |||
2050 | /* Force baud rate if this device requires it, unless it is set to B0. */ | ||
2051 | if (priv->force_baud && ((port->tty->termios->c_cflag & CBAUD) != B0)) { | ||
2052 | dbg("%s: forcing baud rate for this device", __FUNCTION__); | ||
2053 | port->tty->termios->c_cflag &= ~CBAUD; | ||
2054 | port->tty->termios->c_cflag |= priv->force_baud; | ||
2055 | } | ||
2056 | |||
2057 | /* Force RTS-CTS if this device requires it. */ | ||
2058 | if (priv->force_rtscts) { | ||
2059 | dbg("%s: forcing rtscts for this device", __FUNCTION__); | ||
2060 | port->tty->termios->c_cflag |= CRTSCTS; | ||
2061 | } | ||
2062 | |||
2063 | cflag = port->tty->termios->c_cflag; | ||
2064 | |||
2065 | /* FIXME -For this cut I don't care if the line is really changing or | ||
2066 | not - so just do the change regardless - should be able to | ||
2067 | compare old_termios and tty->termios */ | ||
2068 | /* NOTE These routines can get interrupted by | ||
2069 | ftdi_sio_read_bulk_callback - need to examine what this | ||
2070 | means - don't see any problems yet */ | ||
2071 | |||
2072 | /* Set number of data bits, parity, stop bits */ | ||
2073 | |||
2074 | urb_value = 0; | ||
2075 | urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 : | ||
2076 | FTDI_SIO_SET_DATA_STOP_BITS_1); | ||
2077 | urb_value |= (cflag & PARENB ? | ||
2078 | (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : | ||
2079 | FTDI_SIO_SET_DATA_PARITY_EVEN) : | ||
2080 | FTDI_SIO_SET_DATA_PARITY_NONE); | ||
2081 | if (cflag & CSIZE) { | ||
2082 | switch (cflag & CSIZE) { | ||
2083 | case CS5: urb_value |= 5; dbg("Setting CS5"); break; | ||
2084 | case CS6: urb_value |= 6; dbg("Setting CS6"); break; | ||
2085 | case CS7: urb_value |= 7; dbg("Setting CS7"); break; | ||
2086 | case CS8: urb_value |= 8; dbg("Setting CS8"); break; | ||
2087 | default: | ||
2088 | err("CSIZE was set but not CS5-CS8"); | ||
2089 | } | ||
2090 | } | ||
2091 | |||
2092 | /* This is needed by the break command since it uses the same command - but is | ||
2093 | * or'ed with this value */ | ||
2094 | priv->last_set_data_urb_value = urb_value; | ||
2095 | |||
2096 | if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
2097 | FTDI_SIO_SET_DATA_REQUEST, | ||
2098 | FTDI_SIO_SET_DATA_REQUEST_TYPE, | ||
2099 | urb_value , priv->interface, | ||
2100 | buf, 0, 100) < 0) { | ||
2101 | err("%s FAILED to set databits/stopbits/parity", __FUNCTION__); | ||
2102 | } | ||
2103 | |||
2104 | /* Now do the baudrate */ | ||
2105 | if ((cflag & CBAUD) == B0 ) { | ||
2106 | /* Disable flow control */ | ||
2107 | if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
2108 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
2109 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
2110 | 0, priv->interface, | ||
2111 | buf, 0, WDR_TIMEOUT) < 0) { | ||
2112 | err("%s error from disable flowcontrol urb", __FUNCTION__); | ||
2113 | } | ||
2114 | /* Drop RTS and DTR */ | ||
2115 | if (set_dtr(port, LOW) < 0){ | ||
2116 | err("%s Error from DTR LOW urb", __FUNCTION__); | ||
2117 | } | ||
2118 | if (set_rts(port, LOW) < 0){ | ||
2119 | err("%s Error from RTS LOW urb", __FUNCTION__); | ||
2120 | } | ||
2121 | |||
2122 | } else { | ||
2123 | /* set the baudrate determined before */ | ||
2124 | if (change_speed(port)) { | ||
2125 | err("%s urb failed to set baurdrate", __FUNCTION__); | ||
2126 | } | ||
2127 | /* Ensure RTS and DTR are raised */ | ||
2128 | else if (set_dtr(port, HIGH) < 0){ | ||
2129 | err("%s Error from DTR HIGH urb", __FUNCTION__); | ||
2130 | } | ||
2131 | else if (set_rts(port, HIGH) < 0){ | ||
2132 | err("%s Error from RTS HIGH urb", __FUNCTION__); | ||
2133 | } | ||
2134 | } | ||
2135 | |||
2136 | /* Set flow control */ | ||
2137 | /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ | ||
2138 | if (cflag & CRTSCTS) { | ||
2139 | dbg("%s Setting to CRTSCTS flow control", __FUNCTION__); | ||
2140 | if (usb_control_msg(dev, | ||
2141 | usb_sndctrlpipe(dev, 0), | ||
2142 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
2143 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
2144 | 0 , (FTDI_SIO_RTS_CTS_HS | priv->interface), | ||
2145 | buf, 0, WDR_TIMEOUT) < 0) { | ||
2146 | err("urb failed to set to rts/cts flow control"); | ||
2147 | } | ||
2148 | |||
2149 | } else { | ||
2150 | /* | ||
2151 | * Xon/Xoff code | ||
2152 | * | ||
2153 | * Check the IXOFF status in the iflag component of the termios structure | ||
2154 | * if IXOFF is not set, the pre-xon/xoff code is executed. | ||
2155 | */ | ||
2156 | if (iflag & IXOFF) { | ||
2157 | dbg("%s request to enable xonxoff iflag=%04x",__FUNCTION__,iflag); | ||
2158 | // Try to enable the XON/XOFF on the ftdi_sio | ||
2159 | // Set the vstart and vstop -- could have been done up above where | ||
2160 | // a lot of other dereferencing is done but that would be very | ||
2161 | // inefficient as vstart and vstop are not always needed | ||
2162 | vstart=port->tty->termios->c_cc[VSTART]; | ||
2163 | vstop=port->tty->termios->c_cc[VSTOP]; | ||
2164 | urb_value=(vstop << 8) | (vstart); | ||
2165 | |||
2166 | if (usb_control_msg(dev, | ||
2167 | usb_sndctrlpipe(dev, 0), | ||
2168 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
2169 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
2170 | urb_value , (FTDI_SIO_XON_XOFF_HS | ||
2171 | | priv->interface), | ||
2172 | buf, 0, WDR_TIMEOUT) < 0) { | ||
2173 | err("urb failed to set to xon/xoff flow control"); | ||
2174 | } | ||
2175 | } else { | ||
2176 | /* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */ | ||
2177 | /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */ | ||
2178 | dbg("%s Turning off hardware flow control", __FUNCTION__); | ||
2179 | if (usb_control_msg(dev, | ||
2180 | usb_sndctrlpipe(dev, 0), | ||
2181 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
2182 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
2183 | 0, priv->interface, | ||
2184 | buf, 0, WDR_TIMEOUT) < 0) { | ||
2185 | err("urb failed to clear flow control"); | ||
2186 | } | ||
2187 | } | ||
2188 | |||
2189 | } | ||
2190 | return; | ||
2191 | } /* ftdi_termios */ | ||
2192 | |||
2193 | |||
2194 | static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file) | ||
2195 | { | ||
2196 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
2197 | unsigned char buf[2]; | ||
2198 | int ret; | ||
2199 | |||
2200 | dbg("%s TIOCMGET", __FUNCTION__); | ||
2201 | switch (priv->chip_type) { | ||
2202 | case SIO: | ||
2203 | /* Request the status from the device */ | ||
2204 | if ((ret = usb_control_msg(port->serial->dev, | ||
2205 | usb_rcvctrlpipe(port->serial->dev, 0), | ||
2206 | FTDI_SIO_GET_MODEM_STATUS_REQUEST, | ||
2207 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, | ||
2208 | 0, 0, | ||
2209 | buf, 1, WDR_TIMEOUT)) < 0 ) { | ||
2210 | err("%s Could not get modem status of device - err: %d", __FUNCTION__, | ||
2211 | ret); | ||
2212 | return(ret); | ||
2213 | } | ||
2214 | break; | ||
2215 | case FT8U232AM: | ||
2216 | case FT232BM: | ||
2217 | case FT2232C: | ||
2218 | /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same | ||
2219 | format as the data returned from the in point */ | ||
2220 | if ((ret = usb_control_msg(port->serial->dev, | ||
2221 | usb_rcvctrlpipe(port->serial->dev, 0), | ||
2222 | FTDI_SIO_GET_MODEM_STATUS_REQUEST, | ||
2223 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, | ||
2224 | 0, priv->interface, | ||
2225 | buf, 2, WDR_TIMEOUT)) < 0 ) { | ||
2226 | err("%s Could not get modem status of device - err: %d", __FUNCTION__, | ||
2227 | ret); | ||
2228 | return(ret); | ||
2229 | } | ||
2230 | break; | ||
2231 | default: | ||
2232 | return -EFAULT; | ||
2233 | break; | ||
2234 | } | ||
2235 | |||
2236 | return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | | ||
2237 | (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | | ||
2238 | (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | | ||
2239 | (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | | ||
2240 | priv->last_dtr_rts; | ||
2241 | } | ||
2242 | |||
2243 | static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear) | ||
2244 | { | ||
2245 | int ret; | ||
2246 | |||
2247 | dbg("%s TIOCMSET", __FUNCTION__); | ||
2248 | if (set & TIOCM_DTR){ | ||
2249 | if ((ret = set_dtr(port, HIGH)) < 0) { | ||
2250 | err("Urb to set DTR failed"); | ||
2251 | return(ret); | ||
2252 | } | ||
2253 | } | ||
2254 | if (set & TIOCM_RTS) { | ||
2255 | if ((ret = set_rts(port, HIGH)) < 0){ | ||
2256 | err("Urb to set RTS failed"); | ||
2257 | return(ret); | ||
2258 | } | ||
2259 | } | ||
2260 | |||
2261 | if (clear & TIOCM_DTR){ | ||
2262 | if ((ret = set_dtr(port, LOW)) < 0){ | ||
2263 | err("Urb to unset DTR failed"); | ||
2264 | return(ret); | ||
2265 | } | ||
2266 | } | ||
2267 | if (clear & TIOCM_RTS) { | ||
2268 | if ((ret = set_rts(port, LOW)) < 0){ | ||
2269 | err("Urb to unset RTS failed"); | ||
2270 | return(ret); | ||
2271 | } | ||
2272 | } | ||
2273 | return(0); | ||
2274 | } | ||
2275 | |||
2276 | |||
2277 | static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) | ||
2278 | { | ||
2279 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
2280 | |||
2281 | int ret, mask; | ||
2282 | |||
2283 | dbg("%s cmd 0x%04x", __FUNCTION__, cmd); | ||
2284 | |||
2285 | /* Based on code from acm.c and others */ | ||
2286 | switch (cmd) { | ||
2287 | |||
2288 | case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ | ||
2289 | dbg("%s TIOCMBIS", __FUNCTION__); | ||
2290 | if (get_user(mask, (unsigned long __user *) arg)) | ||
2291 | return -EFAULT; | ||
2292 | if (mask & TIOCM_DTR){ | ||
2293 | if ((ret = set_dtr(port, HIGH)) < 0) { | ||
2294 | err("Urb to set DTR failed"); | ||
2295 | return(ret); | ||
2296 | } | ||
2297 | } | ||
2298 | if (mask & TIOCM_RTS) { | ||
2299 | if ((ret = set_rts(port, HIGH)) < 0){ | ||
2300 | err("Urb to set RTS failed"); | ||
2301 | return(ret); | ||
2302 | } | ||
2303 | } | ||
2304 | return(0); | ||
2305 | break; | ||
2306 | |||
2307 | case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ | ||
2308 | dbg("%s TIOCMBIC", __FUNCTION__); | ||
2309 | if (get_user(mask, (unsigned long __user *) arg)) | ||
2310 | return -EFAULT; | ||
2311 | if (mask & TIOCM_DTR){ | ||
2312 | if ((ret = set_dtr(port, LOW)) < 0){ | ||
2313 | err("Urb to unset DTR failed"); | ||
2314 | return(ret); | ||
2315 | } | ||
2316 | } | ||
2317 | if (mask & TIOCM_RTS) { | ||
2318 | if ((ret = set_rts(port, LOW)) < 0){ | ||
2319 | err("Urb to unset RTS failed"); | ||
2320 | return(ret); | ||
2321 | } | ||
2322 | } | ||
2323 | return(0); | ||
2324 | break; | ||
2325 | |||
2326 | /* | ||
2327 | * I had originally implemented TCSET{A,S}{,F,W} and | ||
2328 | * TCGET{A,S} here separately, however when testing I | ||
2329 | * found that the higher layers actually do the termios | ||
2330 | * conversions themselves and pass the call onto | ||
2331 | * ftdi_sio_set_termios. | ||
2332 | * | ||
2333 | */ | ||
2334 | |||
2335 | case TIOCGSERIAL: /* gets serial port data */ | ||
2336 | return get_serial_info(port, (struct serial_struct __user *) arg); | ||
2337 | |||
2338 | case TIOCSSERIAL: /* sets serial port data */ | ||
2339 | return set_serial_info(port, (struct serial_struct __user *) arg); | ||
2340 | |||
2341 | /* | ||
2342 | * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change | ||
2343 | * - mask passed in arg for lines of interest | ||
2344 | * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) | ||
2345 | * Caller should use TIOCGICOUNT to see which one it was. | ||
2346 | * | ||
2347 | * This code is borrowed from linux/drivers/char/serial.c | ||
2348 | */ | ||
2349 | case TIOCMIWAIT: | ||
2350 | while (priv != NULL) { | ||
2351 | interruptible_sleep_on(&priv->delta_msr_wait); | ||
2352 | /* see if a signal did it */ | ||
2353 | if (signal_pending(current)) | ||
2354 | return -ERESTARTSYS; | ||
2355 | else { | ||
2356 | char diff = priv->diff_status; | ||
2357 | |||
2358 | if (diff == 0) { | ||
2359 | return -EIO; /* no change => error */ | ||
2360 | } | ||
2361 | |||
2362 | /* Consume all events */ | ||
2363 | priv->diff_status = 0; | ||
2364 | |||
2365 | /* Return 0 if caller wanted to know about these bits */ | ||
2366 | if ( ((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) || | ||
2367 | ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) || | ||
2368 | ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) || | ||
2369 | ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS)) ) { | ||
2370 | return 0; | ||
2371 | } | ||
2372 | /* | ||
2373 | * Otherwise caller can't care less about what happened, | ||
2374 | * and so we continue to wait for more events. | ||
2375 | */ | ||
2376 | } | ||
2377 | } | ||
2378 | return(0); | ||
2379 | break; | ||
2380 | default: | ||
2381 | break; | ||
2382 | |||
2383 | } | ||
2384 | |||
2385 | |||
2386 | /* This is not necessarily an error - turns out the higher layers will do | ||
2387 | * some ioctls itself (see comment above) | ||
2388 | */ | ||
2389 | dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __FUNCTION__, cmd); | ||
2390 | |||
2391 | return(-ENOIOCTLCMD); | ||
2392 | } /* ftdi_ioctl */ | ||
2393 | |||
2394 | |||
2395 | static void ftdi_throttle (struct usb_serial_port *port) | ||
2396 | { | ||
2397 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
2398 | unsigned long flags; | ||
2399 | |||
2400 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2401 | |||
2402 | spin_lock_irqsave(&priv->rx_lock, flags); | ||
2403 | priv->rx_flags |= THROTTLED; | ||
2404 | spin_unlock_irqrestore(&priv->rx_lock, flags); | ||
2405 | } | ||
2406 | |||
2407 | |||
2408 | static void ftdi_unthrottle (struct usb_serial_port *port) | ||
2409 | { | ||
2410 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
2411 | int actually_throttled; | ||
2412 | unsigned long flags; | ||
2413 | |||
2414 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2415 | |||
2416 | spin_lock_irqsave(&priv->rx_lock, flags); | ||
2417 | actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; | ||
2418 | priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); | ||
2419 | spin_unlock_irqrestore(&priv->rx_lock, flags); | ||
2420 | |||
2421 | if (actually_throttled) | ||
2422 | ftdi_process_read(port); | ||
2423 | } | ||
2424 | |||
2425 | static int __init ftdi_init (void) | ||
2426 | { | ||
2427 | int retval; | ||
2428 | |||
2429 | dbg("%s", __FUNCTION__); | ||
2430 | retval = usb_serial_register(&ftdi_SIO_device); | ||
2431 | if (retval) | ||
2432 | goto failed_SIO_register; | ||
2433 | retval = usb_serial_register(&ftdi_8U232AM_device); | ||
2434 | if (retval) | ||
2435 | goto failed_8U232AM_register; | ||
2436 | retval = usb_serial_register(&ftdi_FT232BM_device); | ||
2437 | if (retval) | ||
2438 | goto failed_FT232BM_register; | ||
2439 | retval = usb_serial_register(&ftdi_FT2232C_device); | ||
2440 | if (retval) | ||
2441 | goto failed_FT2232C_register; | ||
2442 | retval = usb_serial_register(&ftdi_USB_UIRT_device); | ||
2443 | if (retval) | ||
2444 | goto failed_USB_UIRT_register; | ||
2445 | retval = usb_serial_register(&ftdi_HE_TIRA1_device); | ||
2446 | if (retval) | ||
2447 | goto failed_HE_TIRA1_register; | ||
2448 | retval = usb_register(&ftdi_driver); | ||
2449 | if (retval) | ||
2450 | goto failed_usb_register; | ||
2451 | |||
2452 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
2453 | return 0; | ||
2454 | failed_usb_register: | ||
2455 | usb_serial_deregister(&ftdi_HE_TIRA1_device); | ||
2456 | failed_HE_TIRA1_register: | ||
2457 | usb_serial_deregister(&ftdi_USB_UIRT_device); | ||
2458 | failed_USB_UIRT_register: | ||
2459 | usb_serial_deregister(&ftdi_FT2232C_device); | ||
2460 | failed_FT2232C_register: | ||
2461 | usb_serial_deregister(&ftdi_FT232BM_device); | ||
2462 | failed_FT232BM_register: | ||
2463 | usb_serial_deregister(&ftdi_8U232AM_device); | ||
2464 | failed_8U232AM_register: | ||
2465 | usb_serial_deregister(&ftdi_SIO_device); | ||
2466 | failed_SIO_register: | ||
2467 | return retval; | ||
2468 | } | ||
2469 | |||
2470 | |||
2471 | static void __exit ftdi_exit (void) | ||
2472 | { | ||
2473 | |||
2474 | dbg("%s", __FUNCTION__); | ||
2475 | |||
2476 | usb_deregister (&ftdi_driver); | ||
2477 | usb_serial_deregister (&ftdi_HE_TIRA1_device); | ||
2478 | usb_serial_deregister (&ftdi_USB_UIRT_device); | ||
2479 | usb_serial_deregister (&ftdi_FT2232C_device); | ||
2480 | usb_serial_deregister (&ftdi_FT232BM_device); | ||
2481 | usb_serial_deregister (&ftdi_8U232AM_device); | ||
2482 | usb_serial_deregister (&ftdi_SIO_device); | ||
2483 | |||
2484 | } | ||
2485 | |||
2486 | |||
2487 | module_init(ftdi_init); | ||
2488 | module_exit(ftdi_exit); | ||
2489 | |||
2490 | MODULE_AUTHOR( DRIVER_AUTHOR ); | ||
2491 | MODULE_DESCRIPTION( DRIVER_DESC ); | ||
2492 | MODULE_LICENSE("GPL"); | ||
2493 | |||
2494 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
2495 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
2496 | |||