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/visor.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/visor.c')
-rw-r--r-- | drivers/usb/serial/visor.c | 1161 |
1 files changed, 1161 insertions, 0 deletions
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c new file mode 100644 index 000000000000..69d313e98fad --- /dev/null +++ b/drivers/usb/serial/visor.c | |||
@@ -0,0 +1,1161 @@ | |||
1 | /* | ||
2 | * USB HandSpring Visor, Palm m50x, and Sony Clie driver | ||
3 | * (supports all of the Palm OS USB devices) | ||
4 | * | ||
5 | * Copyright (C) 1999 - 2004 | ||
6 | * Greg Kroah-Hartman (greg@kroah.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * See Documentation/usb/usb-serial.txt for more information on using this driver | ||
14 | * | ||
15 | * (06/03/2003) Judd Montgomery <judd at jpilot.org> | ||
16 | * Added support for module parameter options for untested/unknown | ||
17 | * devices. | ||
18 | * | ||
19 | * (03/09/2003) gkh | ||
20 | * Added support for the Sony Clie NZ90V device. Thanks to Martin Brachtl | ||
21 | * <brachtl@redgrep.cz> for the information. | ||
22 | * | ||
23 | * (03/05/2003) gkh | ||
24 | * Think Treo support is now working. | ||
25 | * | ||
26 | * (04/03/2002) gkh | ||
27 | * Added support for the Sony OS 4.1 devices. Thanks to Hiroyuki ARAKI | ||
28 | * <hiro@zob.ne.jp> for the information. | ||
29 | * | ||
30 | * (03/27/2002) gkh | ||
31 | * Removed assumptions that port->tty was always valid (is not true | ||
32 | * for usb serial console devices.) | ||
33 | * | ||
34 | * (03/23/2002) gkh | ||
35 | * Added support for the Palm i705 device, thanks to Thomas Riemer | ||
36 | * <tom@netmech.com> for the information. | ||
37 | * | ||
38 | * (03/21/2002) gkh | ||
39 | * Added support for the Palm m130 device, thanks to Udo Eisenbarth | ||
40 | * <udo.eisenbarth@web.de> for the information. | ||
41 | * | ||
42 | * (02/27/2002) gkh | ||
43 | * Reworked the urb handling logic. We have no more pool, but dynamically | ||
44 | * allocate the urb and the transfer buffer on the fly. In testing this | ||
45 | * does not incure any measurable overhead. This also relies on the fact | ||
46 | * that we have proper reference counting logic for urbs. | ||
47 | * | ||
48 | * (02/21/2002) SilaS | ||
49 | * Added initial support for the Palm m515 devices. | ||
50 | * | ||
51 | * (02/14/2002) gkh | ||
52 | * Added support for the Clie S-360 device. | ||
53 | * | ||
54 | * (12/18/2001) gkh | ||
55 | * Added better Clie support for 3.5 devices. Thanks to Geoffrey Levand | ||
56 | * for the patch. | ||
57 | * | ||
58 | * (11/11/2001) gkh | ||
59 | * Added support for the m125 devices, and added check to prevent oopses | ||
60 | * for Clié devices that lie about the number of ports they have. | ||
61 | * | ||
62 | * (08/30/2001) gkh | ||
63 | * Added support for the Clie devices, both the 3.5 and 4.0 os versions. | ||
64 | * Many thanks to Daniel Burke, and Bryan Payne for helping with this. | ||
65 | * | ||
66 | * (08/23/2001) gkh | ||
67 | * fixed a few potential bugs pointed out by Oliver Neukum. | ||
68 | * | ||
69 | * (05/30/2001) gkh | ||
70 | * switched from using spinlock to a semaphore, which fixes lots of problems. | ||
71 | * | ||
72 | * (05/28/2000) gkh | ||
73 | * Added initial support for the Palm m500 and Palm m505 devices. | ||
74 | * | ||
75 | * (04/08/2001) gb | ||
76 | * Identify version on module load. | ||
77 | * | ||
78 | * (01/21/2000) gkh | ||
79 | * Added write_room and chars_in_buffer, as they were previously using the | ||
80 | * generic driver versions which is all wrong now that we are using an urb | ||
81 | * pool. Thanks to Wolfgang Grandegger for pointing this out to me. | ||
82 | * Removed count assignment in the write function, which was not needed anymore | ||
83 | * either. Thanks to Al Borchers for pointing this out. | ||
84 | * | ||
85 | * (12/12/2000) gkh | ||
86 | * Moved MOD_DEC to end of visor_close to be nicer, as the final write | ||
87 | * message can sleep. | ||
88 | * | ||
89 | * (11/12/2000) gkh | ||
90 | * Fixed bug with data being dropped on the floor by forcing tty->low_latency | ||
91 | * to be on. Hopefully this fixes the OHCI issue! | ||
92 | * | ||
93 | * (11/01/2000) Adam J. Richter | ||
94 | * usb_device_id table support | ||
95 | * | ||
96 | * (10/05/2000) gkh | ||
97 | * Fixed bug with urb->dev not being set properly, now that the usb | ||
98 | * core needs it. | ||
99 | * | ||
100 | * (09/11/2000) gkh | ||
101 | * Got rid of always calling kmalloc for every urb we wrote out to the | ||
102 | * device. | ||
103 | * Added visor_read_callback so we can keep track of bytes in and out for | ||
104 | * those people who like to know the speed of their device. | ||
105 | * Removed DEBUG #ifdefs with call to usb_serial_debug_data | ||
106 | * | ||
107 | * (09/06/2000) gkh | ||
108 | * Fixed oops in visor_exit. Need to uncomment usb_unlink_urb call _after_ | ||
109 | * the host controller drivers set urb->dev = NULL when the urb is finished. | ||
110 | * | ||
111 | * (08/28/2000) gkh | ||
112 | * Added locks for SMP safeness. | ||
113 | * | ||
114 | * (08/08/2000) gkh | ||
115 | * Fixed endian problem in visor_startup. | ||
116 | * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more | ||
117 | * than once. | ||
118 | * | ||
119 | * (07/23/2000) gkh | ||
120 | * Added pool of write urbs to speed up transfers to the visor. | ||
121 | * | ||
122 | * (07/19/2000) gkh | ||
123 | * Added module_init and module_exit functions to handle the fact that this | ||
124 | * driver is a loadable module now. | ||
125 | * | ||
126 | * (07/03/2000) gkh | ||
127 | * Added visor_set_ioctl and visor_set_termios functions (they don't do much | ||
128 | * of anything, but are good for debugging.) | ||
129 | * | ||
130 | * (06/25/2000) gkh | ||
131 | * Fixed bug in visor_unthrottle that should help with the disconnect in PPP | ||
132 | * bug that people have been reporting. | ||
133 | * | ||
134 | * (06/23/2000) gkh | ||
135 | * Cleaned up debugging statements in a quest to find UHCI timeout bug. | ||
136 | * | ||
137 | * (04/27/2000) Ryan VanderBijl | ||
138 | * Fixed memory leak in visor_close | ||
139 | * | ||
140 | * (03/26/2000) gkh | ||
141 | * Split driver up into device specific pieces. | ||
142 | * | ||
143 | */ | ||
144 | |||
145 | #include <linux/config.h> | ||
146 | #include <linux/kernel.h> | ||
147 | #include <linux/errno.h> | ||
148 | #include <linux/init.h> | ||
149 | #include <linux/slab.h> | ||
150 | #include <linux/tty.h> | ||
151 | #include <linux/tty_driver.h> | ||
152 | #include <linux/tty_flip.h> | ||
153 | #include <linux/module.h> | ||
154 | #include <linux/moduleparam.h> | ||
155 | #include <linux/spinlock.h> | ||
156 | #include <asm/uaccess.h> | ||
157 | #include <linux/usb.h> | ||
158 | #include "usb-serial.h" | ||
159 | #include "visor.h" | ||
160 | |||
161 | /* | ||
162 | * Version Information | ||
163 | */ | ||
164 | #define DRIVER_VERSION "v2.1" | ||
165 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>" | ||
166 | #define DRIVER_DESC "USB HandSpring Visor / Palm OS driver" | ||
167 | |||
168 | /* function prototypes for a handspring visor */ | ||
169 | static int visor_open (struct usb_serial_port *port, struct file *filp); | ||
170 | static void visor_close (struct usb_serial_port *port, struct file *filp); | ||
171 | static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count); | ||
172 | static int visor_write_room (struct usb_serial_port *port); | ||
173 | static int visor_chars_in_buffer (struct usb_serial_port *port); | ||
174 | static void visor_throttle (struct usb_serial_port *port); | ||
175 | static void visor_unthrottle (struct usb_serial_port *port); | ||
176 | static int visor_probe (struct usb_serial *serial, const struct usb_device_id *id); | ||
177 | static int visor_calc_num_ports(struct usb_serial *serial); | ||
178 | static void visor_shutdown (struct usb_serial *serial); | ||
179 | static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); | ||
180 | static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios); | ||
181 | static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs); | ||
182 | static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs); | ||
183 | static void visor_read_int_callback (struct urb *urb, struct pt_regs *regs); | ||
184 | static int clie_3_5_startup (struct usb_serial *serial); | ||
185 | static int treo_attach (struct usb_serial *serial); | ||
186 | static int clie_5_attach (struct usb_serial *serial); | ||
187 | static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id); | ||
188 | static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id); | ||
189 | |||
190 | /* Parameters that may be passed into the module. */ | ||
191 | static int debug; | ||
192 | static __u16 vendor; | ||
193 | static __u16 product; | ||
194 | |||
195 | static struct usb_device_id id_table [] = { | ||
196 | { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID), | ||
197 | .driver_info = (kernel_ulong_t)&palm_os_3_probe }, | ||
198 | { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID), | ||
199 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
200 | { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID), | ||
201 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
202 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID), | ||
203 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
204 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID), | ||
205 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
206 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID), | ||
207 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
208 | { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID), | ||
209 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
210 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M100_ID), | ||
211 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
212 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID), | ||
213 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
214 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID), | ||
215 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
216 | { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID), | ||
217 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
218 | { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID), | ||
219 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
220 | { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID), | ||
221 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
222 | { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID), | ||
223 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
224 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID), | ||
225 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
226 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID), | ||
227 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
228 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID), | ||
229 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
230 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID), | ||
231 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
232 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID), | ||
233 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
234 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID), | ||
235 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
236 | { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), | ||
237 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
238 | { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), | ||
239 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
240 | { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID), | ||
241 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
242 | { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID), | ||
243 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
244 | { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID), | ||
245 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
246 | { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID), | ||
247 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
248 | { }, /* optional parameter entry */ | ||
249 | { } /* Terminating entry */ | ||
250 | }; | ||
251 | |||
252 | static struct usb_device_id clie_id_5_table [] = { | ||
253 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID), | ||
254 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }, | ||
255 | { }, /* optional parameter entry */ | ||
256 | { } /* Terminating entry */ | ||
257 | }; | ||
258 | |||
259 | static struct usb_device_id clie_id_3_5_table [] = { | ||
260 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, | ||
261 | { } /* Terminating entry */ | ||
262 | }; | ||
263 | |||
264 | static struct usb_device_id id_table_combined [] = { | ||
265 | { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) }, | ||
266 | { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID) }, | ||
267 | { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID) }, | ||
268 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) }, | ||
269 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) }, | ||
270 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) }, | ||
271 | { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) }, | ||
272 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M100_ID) }, | ||
273 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) }, | ||
274 | { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) }, | ||
275 | { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) }, | ||
276 | { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) }, | ||
277 | { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID) }, | ||
278 | { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) }, | ||
279 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, | ||
280 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, | ||
281 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) }, | ||
282 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) }, | ||
283 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID) }, | ||
284 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID) }, | ||
285 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) }, | ||
286 | { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) }, | ||
287 | { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) }, | ||
288 | { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID) }, | ||
289 | { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) }, | ||
290 | { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) }, | ||
291 | { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) }, | ||
292 | { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID) }, | ||
293 | { }, /* optional parameter entry */ | ||
294 | { } /* Terminating entry */ | ||
295 | }; | ||
296 | |||
297 | MODULE_DEVICE_TABLE (usb, id_table_combined); | ||
298 | |||
299 | static struct usb_driver visor_driver = { | ||
300 | .owner = THIS_MODULE, | ||
301 | .name = "visor", | ||
302 | .probe = usb_serial_probe, | ||
303 | .disconnect = usb_serial_disconnect, | ||
304 | .id_table = id_table_combined, | ||
305 | }; | ||
306 | |||
307 | /* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */ | ||
308 | static struct usb_serial_device_type handspring_device = { | ||
309 | .owner = THIS_MODULE, | ||
310 | .name = "Handspring Visor / Palm OS", | ||
311 | .short_name = "visor", | ||
312 | .id_table = id_table, | ||
313 | .num_interrupt_in = NUM_DONT_CARE, | ||
314 | .num_bulk_in = 2, | ||
315 | .num_bulk_out = 2, | ||
316 | .num_ports = 2, | ||
317 | .open = visor_open, | ||
318 | .close = visor_close, | ||
319 | .throttle = visor_throttle, | ||
320 | .unthrottle = visor_unthrottle, | ||
321 | .attach = treo_attach, | ||
322 | .probe = visor_probe, | ||
323 | .calc_num_ports = visor_calc_num_ports, | ||
324 | .shutdown = visor_shutdown, | ||
325 | .ioctl = visor_ioctl, | ||
326 | .set_termios = visor_set_termios, | ||
327 | .write = visor_write, | ||
328 | .write_room = visor_write_room, | ||
329 | .chars_in_buffer = visor_chars_in_buffer, | ||
330 | .write_bulk_callback = visor_write_bulk_callback, | ||
331 | .read_bulk_callback = visor_read_bulk_callback, | ||
332 | .read_int_callback = visor_read_int_callback, | ||
333 | }; | ||
334 | |||
335 | /* All of the device info needed for the Clie UX50, TH55 Palm 5.0 devices */ | ||
336 | static struct usb_serial_device_type clie_5_device = { | ||
337 | .owner = THIS_MODULE, | ||
338 | .name = "Sony Clie 5.0", | ||
339 | .short_name = "clie_5", | ||
340 | .id_table = clie_id_5_table, | ||
341 | .num_interrupt_in = NUM_DONT_CARE, | ||
342 | .num_bulk_in = 2, | ||
343 | .num_bulk_out = 2, | ||
344 | .num_ports = 2, | ||
345 | .open = visor_open, | ||
346 | .close = visor_close, | ||
347 | .throttle = visor_throttle, | ||
348 | .unthrottle = visor_unthrottle, | ||
349 | .attach = clie_5_attach, | ||
350 | .probe = visor_probe, | ||
351 | .calc_num_ports = visor_calc_num_ports, | ||
352 | .shutdown = visor_shutdown, | ||
353 | .ioctl = visor_ioctl, | ||
354 | .set_termios = visor_set_termios, | ||
355 | .write = visor_write, | ||
356 | .write_room = visor_write_room, | ||
357 | .chars_in_buffer = visor_chars_in_buffer, | ||
358 | .write_bulk_callback = visor_write_bulk_callback, | ||
359 | .read_bulk_callback = visor_read_bulk_callback, | ||
360 | .read_int_callback = visor_read_int_callback, | ||
361 | }; | ||
362 | |||
363 | /* device info for the Sony Clie OS version 3.5 */ | ||
364 | static struct usb_serial_device_type clie_3_5_device = { | ||
365 | .owner = THIS_MODULE, | ||
366 | .name = "Sony Clie 3.5", | ||
367 | .short_name = "clie_3.5", | ||
368 | .id_table = clie_id_3_5_table, | ||
369 | .num_interrupt_in = 0, | ||
370 | .num_bulk_in = 1, | ||
371 | .num_bulk_out = 1, | ||
372 | .num_ports = 1, | ||
373 | .open = visor_open, | ||
374 | .close = visor_close, | ||
375 | .throttle = visor_throttle, | ||
376 | .unthrottle = visor_unthrottle, | ||
377 | .attach = clie_3_5_startup, | ||
378 | .ioctl = visor_ioctl, | ||
379 | .set_termios = visor_set_termios, | ||
380 | .write = visor_write, | ||
381 | .write_room = visor_write_room, | ||
382 | .chars_in_buffer = visor_chars_in_buffer, | ||
383 | .write_bulk_callback = visor_write_bulk_callback, | ||
384 | .read_bulk_callback = visor_read_bulk_callback, | ||
385 | }; | ||
386 | |||
387 | struct visor_private { | ||
388 | spinlock_t lock; | ||
389 | int bytes_in; | ||
390 | int bytes_out; | ||
391 | int outstanding_urbs; | ||
392 | int throttled; | ||
393 | }; | ||
394 | |||
395 | /* number of outstanding urbs to prevent userspace DoS from happening */ | ||
396 | #define URB_UPPER_LIMIT 42 | ||
397 | |||
398 | static int stats; | ||
399 | |||
400 | /****************************************************************************** | ||
401 | * Handspring Visor specific driver functions | ||
402 | ******************************************************************************/ | ||
403 | static int visor_open (struct usb_serial_port *port, struct file *filp) | ||
404 | { | ||
405 | struct usb_serial *serial = port->serial; | ||
406 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
407 | unsigned long flags; | ||
408 | int result = 0; | ||
409 | |||
410 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
411 | |||
412 | if (!port->read_urb) { | ||
413 | /* this is needed for some brain dead Sony devices */ | ||
414 | dev_err(&port->dev, "Device lied about number of ports, please use a lower one.\n"); | ||
415 | return -ENODEV; | ||
416 | } | ||
417 | |||
418 | spin_lock_irqsave(&priv->lock, flags); | ||
419 | priv->bytes_in = 0; | ||
420 | priv->bytes_out = 0; | ||
421 | priv->outstanding_urbs = 0; | ||
422 | priv->throttled = 0; | ||
423 | spin_unlock_irqrestore(&priv->lock, flags); | ||
424 | |||
425 | /* | ||
426 | * Force low_latency on so that our tty_push actually forces the data | ||
427 | * through, otherwise it is scheduled, and with high data rates (like | ||
428 | * with OHCI) data can get lost. | ||
429 | */ | ||
430 | if (port->tty) | ||
431 | port->tty->low_latency = 1; | ||
432 | |||
433 | /* Start reading from the device */ | ||
434 | usb_fill_bulk_urb (port->read_urb, serial->dev, | ||
435 | usb_rcvbulkpipe (serial->dev, | ||
436 | port->bulk_in_endpointAddress), | ||
437 | port->read_urb->transfer_buffer, | ||
438 | port->read_urb->transfer_buffer_length, | ||
439 | visor_read_bulk_callback, port); | ||
440 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
441 | if (result) { | ||
442 | dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", | ||
443 | __FUNCTION__, result); | ||
444 | goto exit; | ||
445 | } | ||
446 | |||
447 | if (port->interrupt_in_urb) { | ||
448 | dbg("%s - adding interrupt input for treo", __FUNCTION__); | ||
449 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | ||
450 | if (result) | ||
451 | dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n", | ||
452 | __FUNCTION__, result); | ||
453 | } | ||
454 | exit: | ||
455 | return result; | ||
456 | } | ||
457 | |||
458 | |||
459 | static void visor_close (struct usb_serial_port *port, struct file * filp) | ||
460 | { | ||
461 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
462 | unsigned char *transfer_buffer; | ||
463 | |||
464 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
465 | |||
466 | /* shutdown our urbs */ | ||
467 | usb_kill_urb(port->read_urb); | ||
468 | if (port->interrupt_in_urb) | ||
469 | usb_kill_urb(port->interrupt_in_urb); | ||
470 | |||
471 | /* Try to send shutdown message, if the device is gone, this will just fail. */ | ||
472 | transfer_buffer = kmalloc (0x12, GFP_KERNEL); | ||
473 | if (transfer_buffer) { | ||
474 | usb_control_msg (port->serial->dev, | ||
475 | usb_rcvctrlpipe(port->serial->dev, 0), | ||
476 | VISOR_CLOSE_NOTIFICATION, 0xc2, | ||
477 | 0x0000, 0x0000, | ||
478 | transfer_buffer, 0x12, 300); | ||
479 | kfree (transfer_buffer); | ||
480 | } | ||
481 | |||
482 | if (stats) | ||
483 | dev_info(&port->dev, "Bytes In = %d Bytes Out = %d\n", | ||
484 | priv->bytes_in, priv->bytes_out); | ||
485 | } | ||
486 | |||
487 | |||
488 | static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count) | ||
489 | { | ||
490 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
491 | struct usb_serial *serial = port->serial; | ||
492 | struct urb *urb; | ||
493 | unsigned char *buffer; | ||
494 | unsigned long flags; | ||
495 | int status; | ||
496 | |||
497 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
498 | |||
499 | spin_lock_irqsave(&priv->lock, flags); | ||
500 | if (priv->outstanding_urbs > URB_UPPER_LIMIT) { | ||
501 | spin_unlock_irqrestore(&priv->lock, flags); | ||
502 | dbg("%s - write limit hit\n", __FUNCTION__); | ||
503 | return 0; | ||
504 | } | ||
505 | spin_unlock_irqrestore(&priv->lock, flags); | ||
506 | |||
507 | buffer = kmalloc (count, GFP_ATOMIC); | ||
508 | if (!buffer) { | ||
509 | dev_err(&port->dev, "out of memory\n"); | ||
510 | return -ENOMEM; | ||
511 | } | ||
512 | |||
513 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
514 | if (!urb) { | ||
515 | dev_err(&port->dev, "no more free urbs\n"); | ||
516 | kfree (buffer); | ||
517 | return -ENOMEM; | ||
518 | } | ||
519 | |||
520 | memcpy (buffer, buf, count); | ||
521 | |||
522 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer); | ||
523 | |||
524 | usb_fill_bulk_urb (urb, serial->dev, | ||
525 | usb_sndbulkpipe (serial->dev, | ||
526 | port->bulk_out_endpointAddress), | ||
527 | buffer, count, | ||
528 | visor_write_bulk_callback, port); | ||
529 | |||
530 | /* send it down the pipe */ | ||
531 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
532 | if (status) { | ||
533 | dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", | ||
534 | __FUNCTION__, status); | ||
535 | count = status; | ||
536 | kfree (buffer); | ||
537 | } else { | ||
538 | spin_lock_irqsave(&priv->lock, flags); | ||
539 | ++priv->outstanding_urbs; | ||
540 | priv->bytes_out += count; | ||
541 | spin_unlock_irqrestore(&priv->lock, flags); | ||
542 | } | ||
543 | |||
544 | /* we are done with this urb, so let the host driver | ||
545 | * really free it when it is finished with it */ | ||
546 | usb_free_urb (urb); | ||
547 | |||
548 | return count; | ||
549 | } | ||
550 | |||
551 | |||
552 | static int visor_write_room (struct usb_serial_port *port) | ||
553 | { | ||
554 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
555 | |||
556 | /* | ||
557 | * We really can take anything the user throws at us | ||
558 | * but let's pick a nice big number to tell the tty | ||
559 | * layer that we have lots of free space | ||
560 | */ | ||
561 | return 2048; | ||
562 | } | ||
563 | |||
564 | |||
565 | static int visor_chars_in_buffer (struct usb_serial_port *port) | ||
566 | { | ||
567 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
568 | |||
569 | /* | ||
570 | * We can't really account for how much data we | ||
571 | * have sent out, but hasn't made it through to the | ||
572 | * device, so just tell the tty layer that everything | ||
573 | * is flushed. | ||
574 | */ | ||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | |||
579 | static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | ||
580 | { | ||
581 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | ||
582 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
583 | unsigned long flags; | ||
584 | |||
585 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | ||
586 | kfree (urb->transfer_buffer); | ||
587 | |||
588 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
589 | |||
590 | if (urb->status) | ||
591 | dbg("%s - nonzero write bulk status received: %d", | ||
592 | __FUNCTION__, urb->status); | ||
593 | |||
594 | spin_lock_irqsave(&priv->lock, flags); | ||
595 | --priv->outstanding_urbs; | ||
596 | spin_unlock_irqrestore(&priv->lock, flags); | ||
597 | |||
598 | schedule_work(&port->work); | ||
599 | } | ||
600 | |||
601 | |||
602 | static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | ||
603 | { | ||
604 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | ||
605 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
606 | unsigned char *data = urb->transfer_buffer; | ||
607 | struct tty_struct *tty; | ||
608 | unsigned long flags; | ||
609 | int i; | ||
610 | int throttled; | ||
611 | int result; | ||
612 | |||
613 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
614 | |||
615 | if (urb->status) { | ||
616 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | ||
617 | return; | ||
618 | } | ||
619 | |||
620 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | ||
621 | |||
622 | tty = port->tty; | ||
623 | if (tty && urb->actual_length) { | ||
624 | for (i = 0; i < urb->actual_length ; ++i) { | ||
625 | /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ | ||
626 | if(tty->flip.count >= TTY_FLIPBUF_SIZE) { | ||
627 | tty_flip_buffer_push(tty); | ||
628 | } | ||
629 | /* this doesn't actually push the data through unless tty->low_latency is set */ | ||
630 | tty_insert_flip_char(tty, data[i], 0); | ||
631 | } | ||
632 | tty_flip_buffer_push(tty); | ||
633 | } | ||
634 | spin_lock_irqsave(&priv->lock, flags); | ||
635 | priv->bytes_in += urb->actual_length; | ||
636 | throttled = priv->throttled; | ||
637 | spin_unlock_irqrestore(&priv->lock, flags); | ||
638 | |||
639 | /* Continue trying to always read if we should */ | ||
640 | if (!throttled) { | ||
641 | usb_fill_bulk_urb (port->read_urb, port->serial->dev, | ||
642 | usb_rcvbulkpipe(port->serial->dev, | ||
643 | port->bulk_in_endpointAddress), | ||
644 | port->read_urb->transfer_buffer, | ||
645 | port->read_urb->transfer_buffer_length, | ||
646 | visor_read_bulk_callback, port); | ||
647 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
648 | if (result) | ||
649 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); | ||
650 | } | ||
651 | return; | ||
652 | } | ||
653 | |||
654 | static void visor_read_int_callback (struct urb *urb, struct pt_regs *regs) | ||
655 | { | ||
656 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | ||
657 | int result; | ||
658 | |||
659 | switch (urb->status) { | ||
660 | case 0: | ||
661 | /* success */ | ||
662 | break; | ||
663 | case -ECONNRESET: | ||
664 | case -ENOENT: | ||
665 | case -ESHUTDOWN: | ||
666 | /* this urb is terminated, clean up */ | ||
667 | dbg("%s - urb shutting down with status: %d", | ||
668 | __FUNCTION__, urb->status); | ||
669 | return; | ||
670 | default: | ||
671 | dbg("%s - nonzero urb status received: %d", | ||
672 | __FUNCTION__, urb->status); | ||
673 | goto exit; | ||
674 | } | ||
675 | |||
676 | /* | ||
677 | * This information is still unknown what it can be used for. | ||
678 | * If anyone has an idea, please let the author know... | ||
679 | * | ||
680 | * Rumor has it this endpoint is used to notify when data | ||
681 | * is ready to be read from the bulk ones. | ||
682 | */ | ||
683 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, | ||
684 | urb->actual_length, urb->transfer_buffer); | ||
685 | |||
686 | exit: | ||
687 | result = usb_submit_urb (urb, GFP_ATOMIC); | ||
688 | if (result) | ||
689 | dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n", | ||
690 | __FUNCTION__, result); | ||
691 | } | ||
692 | |||
693 | static void visor_throttle (struct usb_serial_port *port) | ||
694 | { | ||
695 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
696 | unsigned long flags; | ||
697 | |||
698 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
699 | spin_lock_irqsave(&priv->lock, flags); | ||
700 | priv->throttled = 1; | ||
701 | spin_unlock_irqrestore(&priv->lock, flags); | ||
702 | } | ||
703 | |||
704 | |||
705 | static void visor_unthrottle (struct usb_serial_port *port) | ||
706 | { | ||
707 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
708 | unsigned long flags; | ||
709 | int result; | ||
710 | |||
711 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
712 | spin_lock_irqsave(&priv->lock, flags); | ||
713 | priv->throttled = 0; | ||
714 | spin_unlock_irqrestore(&priv->lock, flags); | ||
715 | |||
716 | port->read_urb->dev = port->serial->dev; | ||
717 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
718 | if (result) | ||
719 | dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result); | ||
720 | } | ||
721 | |||
722 | static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id) | ||
723 | { | ||
724 | struct device *dev = &serial->dev->dev; | ||
725 | struct visor_connection_info *connection_info; | ||
726 | unsigned char *transfer_buffer; | ||
727 | char *string; | ||
728 | int retval = 0; | ||
729 | int i; | ||
730 | int num_ports = 0; | ||
731 | |||
732 | dbg("%s", __FUNCTION__); | ||
733 | |||
734 | transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL); | ||
735 | if (!transfer_buffer) { | ||
736 | dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __FUNCTION__, | ||
737 | sizeof(*connection_info)); | ||
738 | return -ENOMEM; | ||
739 | } | ||
740 | |||
741 | /* send a get connection info request */ | ||
742 | retval = usb_control_msg (serial->dev, | ||
743 | usb_rcvctrlpipe(serial->dev, 0), | ||
744 | VISOR_GET_CONNECTION_INFORMATION, | ||
745 | 0xc2, 0x0000, 0x0000, transfer_buffer, | ||
746 | sizeof(*connection_info), 300); | ||
747 | if (retval < 0) { | ||
748 | dev_err(dev, "%s - error %d getting connection information\n", | ||
749 | __FUNCTION__, retval); | ||
750 | goto exit; | ||
751 | } | ||
752 | |||
753 | if (retval == sizeof(*connection_info)) { | ||
754 | connection_info = (struct visor_connection_info *)transfer_buffer; | ||
755 | |||
756 | num_ports = le16_to_cpu(connection_info->num_ports); | ||
757 | for (i = 0; i < num_ports; ++i) { | ||
758 | switch (connection_info->connections[i].port_function_id) { | ||
759 | case VISOR_FUNCTION_GENERIC: | ||
760 | string = "Generic"; | ||
761 | break; | ||
762 | case VISOR_FUNCTION_DEBUGGER: | ||
763 | string = "Debugger"; | ||
764 | break; | ||
765 | case VISOR_FUNCTION_HOTSYNC: | ||
766 | string = "HotSync"; | ||
767 | break; | ||
768 | case VISOR_FUNCTION_CONSOLE: | ||
769 | string = "Console"; | ||
770 | break; | ||
771 | case VISOR_FUNCTION_REMOTE_FILE_SYS: | ||
772 | string = "Remote File System"; | ||
773 | break; | ||
774 | default: | ||
775 | string = "unknown"; | ||
776 | break; | ||
777 | } | ||
778 | dev_info(dev, "%s: port %d, is for %s use\n", | ||
779 | serial->type->name, | ||
780 | connection_info->connections[i].port, string); | ||
781 | } | ||
782 | } | ||
783 | /* | ||
784 | * Handle devices that report invalid stuff here. | ||
785 | */ | ||
786 | if (num_ports == 0 || num_ports > 2) { | ||
787 | dev_warn (dev, "%s: No valid connect info available\n", | ||
788 | serial->type->name); | ||
789 | num_ports = 2; | ||
790 | } | ||
791 | |||
792 | dev_info(dev, "%s: Number of ports: %d\n", serial->type->name, | ||
793 | num_ports); | ||
794 | |||
795 | /* | ||
796 | * save off our num_ports info so that we can use it in the | ||
797 | * calc_num_ports callback | ||
798 | */ | ||
799 | usb_set_serial_data(serial, (void *)(long)num_ports); | ||
800 | |||
801 | /* ask for the number of bytes available, but ignore the response as it is broken */ | ||
802 | retval = usb_control_msg (serial->dev, | ||
803 | usb_rcvctrlpipe(serial->dev, 0), | ||
804 | VISOR_REQUEST_BYTES_AVAILABLE, | ||
805 | 0xc2, 0x0000, 0x0005, transfer_buffer, | ||
806 | 0x02, 300); | ||
807 | if (retval < 0) | ||
808 | dev_err(dev, "%s - error %d getting bytes available request\n", | ||
809 | __FUNCTION__, retval); | ||
810 | retval = 0; | ||
811 | |||
812 | exit: | ||
813 | kfree (transfer_buffer); | ||
814 | |||
815 | return retval; | ||
816 | } | ||
817 | |||
818 | static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id) | ||
819 | { | ||
820 | struct device *dev = &serial->dev->dev; | ||
821 | struct palm_ext_connection_info *connection_info; | ||
822 | unsigned char *transfer_buffer; | ||
823 | int retval; | ||
824 | |||
825 | dbg("%s", __FUNCTION__); | ||
826 | |||
827 | transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL); | ||
828 | if (!transfer_buffer) { | ||
829 | dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __FUNCTION__, | ||
830 | sizeof(*connection_info)); | ||
831 | return -ENOMEM; | ||
832 | } | ||
833 | |||
834 | retval = usb_control_msg (serial->dev, | ||
835 | usb_rcvctrlpipe(serial->dev, 0), | ||
836 | PALM_GET_EXT_CONNECTION_INFORMATION, | ||
837 | 0xc2, 0x0000, 0x0000, transfer_buffer, | ||
838 | sizeof (*connection_info), 300); | ||
839 | if (retval < 0) | ||
840 | dev_err(dev, "%s - error %d getting connection info\n", | ||
841 | __FUNCTION__, retval); | ||
842 | else | ||
843 | usb_serial_debug_data(debug, &serial->dev->dev, __FUNCTION__, | ||
844 | retval, transfer_buffer); | ||
845 | |||
846 | kfree (transfer_buffer); | ||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | |||
851 | static int visor_probe (struct usb_serial *serial, const struct usb_device_id *id) | ||
852 | { | ||
853 | int retval = 0; | ||
854 | int (*startup) (struct usb_serial *serial, const struct usb_device_id *id); | ||
855 | |||
856 | dbg("%s", __FUNCTION__); | ||
857 | |||
858 | if (serial->dev->actconfig->desc.bConfigurationValue != 1) { | ||
859 | err("active config #%d != 1 ??", | ||
860 | serial->dev->actconfig->desc.bConfigurationValue); | ||
861 | return -ENODEV; | ||
862 | } | ||
863 | |||
864 | if (id->driver_info) { | ||
865 | startup = (void *)id->driver_info; | ||
866 | retval = startup(serial, id); | ||
867 | } | ||
868 | |||
869 | return retval; | ||
870 | } | ||
871 | |||
872 | static int visor_calc_num_ports (struct usb_serial *serial) | ||
873 | { | ||
874 | int num_ports = (int)(long)(usb_get_serial_data(serial)); | ||
875 | |||
876 | if (num_ports) | ||
877 | usb_set_serial_data(serial, NULL); | ||
878 | |||
879 | return num_ports; | ||
880 | } | ||
881 | |||
882 | static int generic_startup(struct usb_serial *serial) | ||
883 | { | ||
884 | struct visor_private *priv; | ||
885 | int i; | ||
886 | |||
887 | for (i = 0; i < serial->num_ports; ++i) { | ||
888 | priv = kmalloc (sizeof(*priv), GFP_KERNEL); | ||
889 | if (!priv) | ||
890 | return -ENOMEM; | ||
891 | memset (priv, 0x00, sizeof(*priv)); | ||
892 | spin_lock_init(&priv->lock); | ||
893 | usb_set_serial_port_data(serial->port[i], priv); | ||
894 | } | ||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | static int clie_3_5_startup (struct usb_serial *serial) | ||
899 | { | ||
900 | struct device *dev = &serial->dev->dev; | ||
901 | int result; | ||
902 | u8 data; | ||
903 | |||
904 | dbg("%s", __FUNCTION__); | ||
905 | |||
906 | /* | ||
907 | * Note that PEG-300 series devices expect the following two calls. | ||
908 | */ | ||
909 | |||
910 | /* get the config number */ | ||
911 | result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
912 | USB_REQ_GET_CONFIGURATION, USB_DIR_IN, | ||
913 | 0, 0, &data, 1, 3000); | ||
914 | if (result < 0) { | ||
915 | dev_err(dev, "%s: get config number failed: %d\n", __FUNCTION__, result); | ||
916 | return result; | ||
917 | } | ||
918 | if (result != 1) { | ||
919 | dev_err(dev, "%s: get config number bad return length: %d\n", __FUNCTION__, result); | ||
920 | return -EIO; | ||
921 | } | ||
922 | |||
923 | /* get the interface number */ | ||
924 | result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
925 | USB_REQ_GET_INTERFACE, | ||
926 | USB_DIR_IN | USB_RECIP_INTERFACE, | ||
927 | 0, 0, &data, 1, 3000); | ||
928 | if (result < 0) { | ||
929 | dev_err(dev, "%s: get interface number failed: %d\n", __FUNCTION__, result); | ||
930 | return result; | ||
931 | } | ||
932 | if (result != 1) { | ||
933 | dev_err(dev, "%s: get interface number bad return length: %d\n", __FUNCTION__, result); | ||
934 | return -EIO; | ||
935 | } | ||
936 | |||
937 | return generic_startup(serial); | ||
938 | } | ||
939 | |||
940 | static int treo_attach (struct usb_serial *serial) | ||
941 | { | ||
942 | struct usb_serial_port *swap_port; | ||
943 | |||
944 | /* Only do this endpoint hack for the Handspring devices with | ||
945 | * interrupt in endpoints, which for now are the Treo devices. */ | ||
946 | if (!((le16_to_cpu(serial->dev->descriptor.idVendor) == HANDSPRING_VENDOR_ID) || | ||
947 | (le16_to_cpu(serial->dev->descriptor.idVendor) == KYOCERA_VENDOR_ID)) || | ||
948 | (serial->num_interrupt_in == 0)) | ||
949 | goto generic_startup; | ||
950 | |||
951 | dbg("%s", __FUNCTION__); | ||
952 | |||
953 | /* | ||
954 | * It appears that Treos and Kyoceras want to use the | ||
955 | * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, | ||
956 | * so let's swap the 1st and 2nd bulk in and interrupt endpoints. | ||
957 | * Note that swapping the bulk out endpoints would break lots of | ||
958 | * apps that want to communicate on the second port. | ||
959 | */ | ||
960 | #define COPY_PORT(dest, src) \ | ||
961 | dest->read_urb = src->read_urb; \ | ||
962 | dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress; \ | ||
963 | dest->bulk_in_buffer = src->bulk_in_buffer; \ | ||
964 | dest->interrupt_in_urb = src->interrupt_in_urb; \ | ||
965 | dest->interrupt_in_endpointAddress = src->interrupt_in_endpointAddress; \ | ||
966 | dest->interrupt_in_buffer = src->interrupt_in_buffer; | ||
967 | |||
968 | swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL); | ||
969 | if (!swap_port) | ||
970 | return -ENOMEM; | ||
971 | COPY_PORT(swap_port, serial->port[0]); | ||
972 | COPY_PORT(serial->port[0], serial->port[1]); | ||
973 | COPY_PORT(serial->port[1], swap_port); | ||
974 | kfree(swap_port); | ||
975 | |||
976 | generic_startup: | ||
977 | return generic_startup(serial); | ||
978 | } | ||
979 | |||
980 | static int clie_5_attach (struct usb_serial *serial) | ||
981 | { | ||
982 | dbg("%s", __FUNCTION__); | ||
983 | |||
984 | /* TH55 registers 2 ports. | ||
985 | Communication in from the UX50/TH55 uses bulk_in_endpointAddress from port 0 | ||
986 | Communication out to the UX50/TH55 uses bulk_out_endpointAddress from port 1 | ||
987 | |||
988 | Lets do a quick and dirty mapping | ||
989 | */ | ||
990 | |||
991 | /* some sanity check */ | ||
992 | if (serial->num_ports < 2) | ||
993 | return -1; | ||
994 | |||
995 | /* port 0 now uses the modified endpoint Address */ | ||
996 | serial->port[0]->bulk_out_endpointAddress = serial->port[1]->bulk_out_endpointAddress; | ||
997 | |||
998 | return generic_startup(serial); | ||
999 | } | ||
1000 | |||
1001 | static void visor_shutdown (struct usb_serial *serial) | ||
1002 | { | ||
1003 | dbg("%s", __FUNCTION__); | ||
1004 | } | ||
1005 | |||
1006 | static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) | ||
1007 | { | ||
1008 | dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd); | ||
1009 | |||
1010 | return -ENOIOCTLCMD; | ||
1011 | } | ||
1012 | |||
1013 | |||
1014 | /* This function is all nice and good, but we don't change anything based on it :) */ | ||
1015 | static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios) | ||
1016 | { | ||
1017 | unsigned int cflag; | ||
1018 | |||
1019 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1020 | |||
1021 | if ((!port->tty) || (!port->tty->termios)) { | ||
1022 | dbg("%s - no tty structures", __FUNCTION__); | ||
1023 | return; | ||
1024 | } | ||
1025 | |||
1026 | cflag = port->tty->termios->c_cflag; | ||
1027 | /* check that they really want us to change something */ | ||
1028 | if (old_termios) { | ||
1029 | if ((cflag == old_termios->c_cflag) && | ||
1030 | (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { | ||
1031 | dbg("%s - nothing to change...", __FUNCTION__); | ||
1032 | return; | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | /* get the byte size */ | ||
1037 | switch (cflag & CSIZE) { | ||
1038 | case CS5: dbg("%s - data bits = 5", __FUNCTION__); break; | ||
1039 | case CS6: dbg("%s - data bits = 6", __FUNCTION__); break; | ||
1040 | case CS7: dbg("%s - data bits = 7", __FUNCTION__); break; | ||
1041 | default: | ||
1042 | case CS8: dbg("%s - data bits = 8", __FUNCTION__); break; | ||
1043 | } | ||
1044 | |||
1045 | /* determine the parity */ | ||
1046 | if (cflag & PARENB) | ||
1047 | if (cflag & PARODD) | ||
1048 | dbg("%s - parity = odd", __FUNCTION__); | ||
1049 | else | ||
1050 | dbg("%s - parity = even", __FUNCTION__); | ||
1051 | else | ||
1052 | dbg("%s - parity = none", __FUNCTION__); | ||
1053 | |||
1054 | /* figure out the stop bits requested */ | ||
1055 | if (cflag & CSTOPB) | ||
1056 | dbg("%s - stop bits = 2", __FUNCTION__); | ||
1057 | else | ||
1058 | dbg("%s - stop bits = 1", __FUNCTION__); | ||
1059 | |||
1060 | |||
1061 | /* figure out the flow control settings */ | ||
1062 | if (cflag & CRTSCTS) | ||
1063 | dbg("%s - RTS/CTS is enabled", __FUNCTION__); | ||
1064 | else | ||
1065 | dbg("%s - RTS/CTS is disabled", __FUNCTION__); | ||
1066 | |||
1067 | /* determine software flow control */ | ||
1068 | if (I_IXOFF(port->tty)) | ||
1069 | dbg("%s - XON/XOFF is enabled, XON = %2x, XOFF = %2x", | ||
1070 | __FUNCTION__, START_CHAR(port->tty), STOP_CHAR(port->tty)); | ||
1071 | else | ||
1072 | dbg("%s - XON/XOFF is disabled", __FUNCTION__); | ||
1073 | |||
1074 | /* get the baud rate wanted */ | ||
1075 | dbg("%s - baud rate = %d", __FUNCTION__, tty_get_baud_rate(port->tty)); | ||
1076 | |||
1077 | return; | ||
1078 | } | ||
1079 | |||
1080 | |||
1081 | static int __init visor_init (void) | ||
1082 | { | ||
1083 | int i, retval; | ||
1084 | /* Only if parameters were passed to us */ | ||
1085 | if ((vendor>0) && (product>0)) { | ||
1086 | struct usb_device_id usb_dev_temp[]= | ||
1087 | {{USB_DEVICE(vendor, product), | ||
1088 | .driver_info = (kernel_ulong_t)&palm_os_4_probe }}; | ||
1089 | |||
1090 | /* Find the last entry in id_table */ | ||
1091 | for (i=0; ; i++) { | ||
1092 | if (id_table[i].idVendor==0) { | ||
1093 | id_table[i] = usb_dev_temp[0]; | ||
1094 | break; | ||
1095 | } | ||
1096 | } | ||
1097 | /* Find the last entry in id_table_combined */ | ||
1098 | for (i=0; ; i++) { | ||
1099 | if (id_table_combined[i].idVendor==0) { | ||
1100 | id_table_combined[i] = usb_dev_temp[0]; | ||
1101 | break; | ||
1102 | } | ||
1103 | } | ||
1104 | info("Untested USB device specified at time of module insertion"); | ||
1105 | info("Warning: This is not guaranteed to work"); | ||
1106 | info("Using a newer kernel is preferred to this method"); | ||
1107 | info("Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x", | ||
1108 | vendor, product); | ||
1109 | } | ||
1110 | retval = usb_serial_register(&handspring_device); | ||
1111 | if (retval) | ||
1112 | goto failed_handspring_register; | ||
1113 | retval = usb_serial_register(&clie_3_5_device); | ||
1114 | if (retval) | ||
1115 | goto failed_clie_3_5_register; | ||
1116 | retval = usb_serial_register(&clie_5_device); | ||
1117 | if (retval) | ||
1118 | goto failed_clie_5_register; | ||
1119 | retval = usb_register(&visor_driver); | ||
1120 | if (retval) | ||
1121 | goto failed_usb_register; | ||
1122 | info(DRIVER_DESC " " DRIVER_VERSION); | ||
1123 | |||
1124 | return 0; | ||
1125 | failed_usb_register: | ||
1126 | usb_serial_deregister(&clie_5_device); | ||
1127 | failed_clie_5_register: | ||
1128 | usb_serial_deregister(&clie_3_5_device); | ||
1129 | failed_clie_3_5_register: | ||
1130 | usb_serial_deregister(&handspring_device); | ||
1131 | failed_handspring_register: | ||
1132 | return retval; | ||
1133 | } | ||
1134 | |||
1135 | |||
1136 | static void __exit visor_exit (void) | ||
1137 | { | ||
1138 | usb_deregister (&visor_driver); | ||
1139 | usb_serial_deregister (&handspring_device); | ||
1140 | usb_serial_deregister (&clie_3_5_device); | ||
1141 | usb_serial_deregister (&clie_5_device); | ||
1142 | } | ||
1143 | |||
1144 | |||
1145 | module_init(visor_init); | ||
1146 | module_exit(visor_exit); | ||
1147 | |||
1148 | MODULE_AUTHOR( DRIVER_AUTHOR ); | ||
1149 | MODULE_DESCRIPTION( DRIVER_DESC ); | ||
1150 | MODULE_LICENSE("GPL"); | ||
1151 | |||
1152 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
1153 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
1154 | module_param(stats, bool, S_IRUGO | S_IWUSR); | ||
1155 | MODULE_PARM_DESC(stats, "Enables statistics or not"); | ||
1156 | |||
1157 | module_param(vendor, ushort, 0); | ||
1158 | MODULE_PARM_DESC(vendor, "User specified vendor ID"); | ||
1159 | module_param(product, ushort, 0); | ||
1160 | MODULE_PARM_DESC(product, "User specified product ID"); | ||
1161 | |||