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/keyspan.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/keyspan.c')
-rw-r--r-- | drivers/usb/serial/keyspan.c | 2354 |
1 files changed, 2354 insertions, 0 deletions
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c new file mode 100644 index 000000000000..fb0926292228 --- /dev/null +++ b/drivers/usb/serial/keyspan.c | |||
@@ -0,0 +1,2354 @@ | |||
1 | /* | ||
2 | Keyspan USB to Serial Converter driver | ||
3 | |||
4 | (C) Copyright (C) 2000-2001 Hugh Blemings <hugh@blemings.org> | ||
5 | (C) Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | See http://misc.nu/hugh/keyspan.html for more information. | ||
13 | |||
14 | Code in this driver inspired by and in a number of places taken | ||
15 | from Brian Warner's original Keyspan-PDA driver. | ||
16 | |||
17 | This driver has been put together with the support of Innosys, Inc. | ||
18 | and Keyspan, Inc the manufacturers of the Keyspan USB-serial products. | ||
19 | Thanks Guys :) | ||
20 | |||
21 | Thanks to Paulus for miscellaneous tidy ups, some largish chunks | ||
22 | of much nicer and/or completely new code and (perhaps most uniquely) | ||
23 | having the patience to sit down and explain why and where he'd changed | ||
24 | stuff. | ||
25 | |||
26 | Tip 'o the hat to IBM (and previously Linuxcare :) for supporting | ||
27 | staff in their work on open source projects. | ||
28 | |||
29 | Change History | ||
30 | |||
31 | 2003sep04 LPM (Keyspan) add support for new single port product USA19HS. | ||
32 | Improve setup message handling for all devices. | ||
33 | |||
34 | Wed Feb 19 22:00:00 PST 2003 (Jeffrey S. Laing <keyspan@jsl.com>) | ||
35 | Merged the current (1/31/03) Keyspan code with the current (2.4.21-pre4) | ||
36 | Linux source tree. The Linux tree lacked support for the 49WLC and | ||
37 | others. The Keyspan patches didn't work with the current kernel. | ||
38 | |||
39 | 2003jan30 LPM add support for the 49WLC and MPR | ||
40 | |||
41 | Wed Apr 25 12:00:00 PST 2002 (Keyspan) | ||
42 | Started with Hugh Blemings' code dated Jan 17, 2002. All adapters | ||
43 | now supported (including QI and QW). Modified port open, port | ||
44 | close, and send setup() logic to fix various data and endpoint | ||
45 | synchronization bugs and device LED status bugs. Changed keyspan_ | ||
46 | write_room() to accurately return transmit buffer availability. | ||
47 | Changed forwardingLength from 1 to 16 for all adapters. | ||
48 | |||
49 | Fri Oct 12 16:45:00 EST 2001 | ||
50 | Preliminary USA-19QI and USA-28 support (both test OK for me, YMMV) | ||
51 | |||
52 | Wed Apr 25 12:00:00 PST 2002 (Keyspan) | ||
53 | Started with Hugh Blemings' code dated Jan 17, 2002. All adapters | ||
54 | now supported (including QI and QW). Modified port open, port | ||
55 | close, and send setup() logic to fix various data and endpoint | ||
56 | synchronization bugs and device LED status bugs. Changed keyspan_ | ||
57 | write_room() to accurately return transmit buffer availability. | ||
58 | Changed forwardingLength from 1 to 16 for all adapters. | ||
59 | |||
60 | Fri Oct 12 16:45:00 EST 2001 | ||
61 | Preliminary USA-19QI and USA-28 support (both test OK for me, YMMV) | ||
62 | |||
63 | Mon Oct 8 14:29:00 EST 2001 hugh | ||
64 | Fixed bug that prevented mulitport devices operating correctly | ||
65 | if they weren't the first unit attached. | ||
66 | |||
67 | Sat Oct 6 12:31:21 EST 2001 hugh | ||
68 | Added support for USA-28XA and -28XB, misc cleanups, break support | ||
69 | for usa26 based models thanks to David Gibson. | ||
70 | |||
71 | Thu May 31 11:56:42 PDT 2001 gkh | ||
72 | switched from using spinlock to a semaphore | ||
73 | |||
74 | (04/08/2001) gb | ||
75 | Identify version on module load. | ||
76 | |||
77 | (11/01/2000) Adam J. Richter | ||
78 | usb_device_id table support. | ||
79 | |||
80 | Tue Oct 10 23:15:33 EST 2000 Hugh | ||
81 | Merged Paul's changes with my USA-49W mods. Work in progress | ||
82 | still... | ||
83 | |||
84 | Wed Jul 19 14:00:42 EST 2000 gkh | ||
85 | Added module_init and module_exit functions to handle the fact that | ||
86 | this driver is a loadable module now. | ||
87 | |||
88 | Tue Jul 18 16:14:52 EST 2000 Hugh | ||
89 | Basic character input/output for USA-19 now mostly works, | ||
90 | fixed at 9600 baud for the moment. | ||
91 | |||
92 | Sat Jul 8 11:11:48 EST 2000 Hugh | ||
93 | First public release - nothing works except the firmware upload. | ||
94 | Tested on PPC and x86 architectures, seems to behave... | ||
95 | */ | ||
96 | |||
97 | |||
98 | #include <linux/config.h> | ||
99 | #include <linux/kernel.h> | ||
100 | #include <linux/jiffies.h> | ||
101 | #include <linux/errno.h> | ||
102 | #include <linux/init.h> | ||
103 | #include <linux/slab.h> | ||
104 | #include <linux/tty.h> | ||
105 | #include <linux/tty_driver.h> | ||
106 | #include <linux/tty_flip.h> | ||
107 | #include <linux/module.h> | ||
108 | #include <linux/spinlock.h> | ||
109 | #include <asm/uaccess.h> | ||
110 | #include <linux/usb.h> | ||
111 | #include "usb-serial.h" | ||
112 | #include "keyspan.h" | ||
113 | |||
114 | static int debug; | ||
115 | |||
116 | /* | ||
117 | * Version Information | ||
118 | */ | ||
119 | #define DRIVER_VERSION "v1.1.4" | ||
120 | #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu" | ||
121 | #define DRIVER_DESC "Keyspan USB to Serial Converter Driver" | ||
122 | |||
123 | #define INSTAT_BUFLEN 32 | ||
124 | #define GLOCONT_BUFLEN 64 | ||
125 | |||
126 | /* Per device and per port private data */ | ||
127 | struct keyspan_serial_private { | ||
128 | const struct keyspan_device_details *device_details; | ||
129 | |||
130 | struct urb *instat_urb; | ||
131 | char instat_buf[INSTAT_BUFLEN]; | ||
132 | |||
133 | /* XXX this one probably will need a lock */ | ||
134 | struct urb *glocont_urb; | ||
135 | char glocont_buf[GLOCONT_BUFLEN]; | ||
136 | }; | ||
137 | |||
138 | struct keyspan_port_private { | ||
139 | /* Keep track of which input & output endpoints to use */ | ||
140 | int in_flip; | ||
141 | int out_flip; | ||
142 | |||
143 | /* Keep duplicate of device details in each port | ||
144 | structure as well - simplifies some of the | ||
145 | callback functions etc. */ | ||
146 | const struct keyspan_device_details *device_details; | ||
147 | |||
148 | /* Input endpoints and buffer for this port */ | ||
149 | struct urb *in_urbs[2]; | ||
150 | char in_buffer[2][64]; | ||
151 | /* Output endpoints and buffer for this port */ | ||
152 | struct urb *out_urbs[2]; | ||
153 | char out_buffer[2][64]; | ||
154 | |||
155 | /* Input ack endpoint */ | ||
156 | struct urb *inack_urb; | ||
157 | char inack_buffer[1]; | ||
158 | |||
159 | /* Output control endpoint */ | ||
160 | struct urb *outcont_urb; | ||
161 | char outcont_buffer[64]; | ||
162 | |||
163 | /* Settings for the port */ | ||
164 | int baud; | ||
165 | int old_baud; | ||
166 | unsigned int cflag; | ||
167 | unsigned int old_cflag; | ||
168 | enum {flow_none, flow_cts, flow_xon} flow_control; | ||
169 | int rts_state; /* Handshaking pins (outputs) */ | ||
170 | int dtr_state; | ||
171 | int cts_state; /* Handshaking pins (inputs) */ | ||
172 | int dsr_state; | ||
173 | int dcd_state; | ||
174 | int ri_state; | ||
175 | int break_on; | ||
176 | |||
177 | unsigned long tx_start_time[2]; | ||
178 | int resend_cont; /* need to resend control packet */ | ||
179 | }; | ||
180 | |||
181 | |||
182 | /* Include Keyspan message headers. All current Keyspan Adapters | ||
183 | make use of one of four message formats which are referred | ||
184 | to as USA-26, USA-28 and USA-49, USA-90 by Keyspan and within this driver. */ | ||
185 | #include "keyspan_usa26msg.h" | ||
186 | #include "keyspan_usa28msg.h" | ||
187 | #include "keyspan_usa49msg.h" | ||
188 | #include "keyspan_usa90msg.h" | ||
189 | |||
190 | |||
191 | /* Functions used by new usb-serial code. */ | ||
192 | static int __init keyspan_init (void) | ||
193 | { | ||
194 | int retval; | ||
195 | retval = usb_serial_register(&keyspan_pre_device); | ||
196 | if (retval) | ||
197 | goto failed_pre_device_register; | ||
198 | retval = usb_serial_register(&keyspan_1port_device); | ||
199 | if (retval) | ||
200 | goto failed_1port_device_register; | ||
201 | retval = usb_serial_register(&keyspan_2port_device); | ||
202 | if (retval) | ||
203 | goto failed_2port_device_register; | ||
204 | retval = usb_serial_register(&keyspan_4port_device); | ||
205 | if (retval) | ||
206 | goto failed_4port_device_register; | ||
207 | retval = usb_register(&keyspan_driver); | ||
208 | if (retval) | ||
209 | goto failed_usb_register; | ||
210 | |||
211 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
212 | |||
213 | return 0; | ||
214 | failed_usb_register: | ||
215 | usb_serial_deregister(&keyspan_4port_device); | ||
216 | failed_4port_device_register: | ||
217 | usb_serial_deregister(&keyspan_2port_device); | ||
218 | failed_2port_device_register: | ||
219 | usb_serial_deregister(&keyspan_1port_device); | ||
220 | failed_1port_device_register: | ||
221 | usb_serial_deregister(&keyspan_pre_device); | ||
222 | failed_pre_device_register: | ||
223 | return retval; | ||
224 | } | ||
225 | |||
226 | static void __exit keyspan_exit (void) | ||
227 | { | ||
228 | usb_deregister (&keyspan_driver); | ||
229 | usb_serial_deregister (&keyspan_pre_device); | ||
230 | usb_serial_deregister (&keyspan_1port_device); | ||
231 | usb_serial_deregister (&keyspan_2port_device); | ||
232 | usb_serial_deregister (&keyspan_4port_device); | ||
233 | } | ||
234 | |||
235 | module_init(keyspan_init); | ||
236 | module_exit(keyspan_exit); | ||
237 | |||
238 | static void keyspan_rx_throttle (struct usb_serial_port *port) | ||
239 | { | ||
240 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
241 | } | ||
242 | |||
243 | |||
244 | static void keyspan_rx_unthrottle (struct usb_serial_port *port) | ||
245 | { | ||
246 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
247 | } | ||
248 | |||
249 | |||
250 | static void keyspan_break_ctl (struct usb_serial_port *port, int break_state) | ||
251 | { | ||
252 | struct keyspan_port_private *p_priv; | ||
253 | |||
254 | dbg("%s", __FUNCTION__); | ||
255 | |||
256 | p_priv = usb_get_serial_port_data(port); | ||
257 | |||
258 | if (break_state == -1) | ||
259 | p_priv->break_on = 1; | ||
260 | else | ||
261 | p_priv->break_on = 0; | ||
262 | |||
263 | keyspan_send_setup(port, 0); | ||
264 | } | ||
265 | |||
266 | |||
267 | static void keyspan_set_termios (struct usb_serial_port *port, | ||
268 | struct termios *old_termios) | ||
269 | { | ||
270 | int baud_rate, device_port; | ||
271 | struct keyspan_port_private *p_priv; | ||
272 | const struct keyspan_device_details *d_details; | ||
273 | unsigned int cflag; | ||
274 | |||
275 | dbg("%s", __FUNCTION__); | ||
276 | |||
277 | p_priv = usb_get_serial_port_data(port); | ||
278 | d_details = p_priv->device_details; | ||
279 | cflag = port->tty->termios->c_cflag; | ||
280 | device_port = port->number - port->serial->minor; | ||
281 | |||
282 | /* Baud rate calculation takes baud rate as an integer | ||
283 | so other rates can be generated if desired. */ | ||
284 | baud_rate = tty_get_baud_rate(port->tty); | ||
285 | /* If no match or invalid, don't change */ | ||
286 | if (baud_rate >= 0 | ||
287 | && d_details->calculate_baud_rate(baud_rate, d_details->baudclk, | ||
288 | NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { | ||
289 | /* FIXME - more to do here to ensure rate changes cleanly */ | ||
290 | p_priv->baud = baud_rate; | ||
291 | } | ||
292 | |||
293 | /* set CTS/RTS handshake etc. */ | ||
294 | p_priv->cflag = cflag; | ||
295 | p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none; | ||
296 | |||
297 | keyspan_send_setup(port, 0); | ||
298 | } | ||
299 | |||
300 | static int keyspan_tiocmget(struct usb_serial_port *port, struct file *file) | ||
301 | { | ||
302 | unsigned int value; | ||
303 | struct keyspan_port_private *p_priv; | ||
304 | |||
305 | p_priv = usb_get_serial_port_data(port); | ||
306 | |||
307 | value = ((p_priv->rts_state) ? TIOCM_RTS : 0) | | ||
308 | ((p_priv->dtr_state) ? TIOCM_DTR : 0) | | ||
309 | ((p_priv->cts_state) ? TIOCM_CTS : 0) | | ||
310 | ((p_priv->dsr_state) ? TIOCM_DSR : 0) | | ||
311 | ((p_priv->dcd_state) ? TIOCM_CAR : 0) | | ||
312 | ((p_priv->ri_state) ? TIOCM_RNG : 0); | ||
313 | |||
314 | return value; | ||
315 | } | ||
316 | |||
317 | static int keyspan_tiocmset(struct usb_serial_port *port, struct file *file, | ||
318 | unsigned int set, unsigned int clear) | ||
319 | { | ||
320 | struct keyspan_port_private *p_priv; | ||
321 | |||
322 | p_priv = usb_get_serial_port_data(port); | ||
323 | |||
324 | if (set & TIOCM_RTS) | ||
325 | p_priv->rts_state = 1; | ||
326 | if (set & TIOCM_DTR) | ||
327 | p_priv->dtr_state = 1; | ||
328 | |||
329 | if (clear & TIOCM_RTS) | ||
330 | p_priv->rts_state = 0; | ||
331 | if (clear & TIOCM_DTR) | ||
332 | p_priv->dtr_state = 0; | ||
333 | keyspan_send_setup(port, 0); | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static int keyspan_ioctl(struct usb_serial_port *port, struct file *file, | ||
338 | unsigned int cmd, unsigned long arg) | ||
339 | { | ||
340 | return -ENOIOCTLCMD; | ||
341 | } | ||
342 | |||
343 | /* Write function is similar for the four protocols used | ||
344 | with only a minor change for usa90 (usa19hs) required */ | ||
345 | static int keyspan_write(struct usb_serial_port *port, | ||
346 | const unsigned char *buf, int count) | ||
347 | { | ||
348 | struct keyspan_port_private *p_priv; | ||
349 | const struct keyspan_device_details *d_details; | ||
350 | int flip; | ||
351 | int left, todo; | ||
352 | struct urb *this_urb; | ||
353 | int err, maxDataLen, dataOffset; | ||
354 | |||
355 | p_priv = usb_get_serial_port_data(port); | ||
356 | d_details = p_priv->device_details; | ||
357 | |||
358 | if (d_details->msg_format == msg_usa90) { | ||
359 | maxDataLen = 64; | ||
360 | dataOffset = 0; | ||
361 | } else { | ||
362 | maxDataLen = 63; | ||
363 | dataOffset = 1; | ||
364 | } | ||
365 | |||
366 | dbg("%s - for port %d (%d chars), flip=%d", | ||
367 | __FUNCTION__, port->number, count, p_priv->out_flip); | ||
368 | |||
369 | for (left = count; left > 0; left -= todo) { | ||
370 | todo = left; | ||
371 | if (todo > maxDataLen) | ||
372 | todo = maxDataLen; | ||
373 | |||
374 | flip = p_priv->out_flip; | ||
375 | |||
376 | /* Check we have a valid urb/endpoint before we use it... */ | ||
377 | if ((this_urb = p_priv->out_urbs[flip]) == NULL) { | ||
378 | /* no bulk out, so return 0 bytes written */ | ||
379 | dbg("%s - no output urb :(", __FUNCTION__); | ||
380 | return count; | ||
381 | } | ||
382 | |||
383 | dbg("%s - endpoint %d flip %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), flip); | ||
384 | |||
385 | if (this_urb->status == -EINPROGRESS) { | ||
386 | if (this_urb->transfer_flags & URB_ASYNC_UNLINK) | ||
387 | break; | ||
388 | if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ)) | ||
389 | break; | ||
390 | this_urb->transfer_flags |= URB_ASYNC_UNLINK; | ||
391 | usb_unlink_urb(this_urb); | ||
392 | break; | ||
393 | } | ||
394 | |||
395 | /* First byte in buffer is "last flag" (except for usa19hx) - unused so | ||
396 | for now so set to zero */ | ||
397 | ((char *)this_urb->transfer_buffer)[0] = 0; | ||
398 | |||
399 | memcpy (this_urb->transfer_buffer + dataOffset, buf, todo); | ||
400 | buf += todo; | ||
401 | |||
402 | /* send the data out the bulk port */ | ||
403 | this_urb->transfer_buffer_length = todo + dataOffset; | ||
404 | |||
405 | this_urb->transfer_flags &= ~URB_ASYNC_UNLINK; | ||
406 | this_urb->dev = port->serial->dev; | ||
407 | if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { | ||
408 | dbg("usb_submit_urb(write bulk) failed (%d)", err); | ||
409 | } | ||
410 | p_priv->tx_start_time[flip] = jiffies; | ||
411 | |||
412 | /* Flip for next time if usa26 or usa28 interface | ||
413 | (not used on usa49) */ | ||
414 | p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip; | ||
415 | } | ||
416 | |||
417 | return count - left; | ||
418 | } | ||
419 | |||
420 | static void usa26_indat_callback(struct urb *urb, struct pt_regs *regs) | ||
421 | { | ||
422 | int i, err; | ||
423 | int endpoint; | ||
424 | struct usb_serial_port *port; | ||
425 | struct tty_struct *tty; | ||
426 | unsigned char *data = urb->transfer_buffer; | ||
427 | |||
428 | dbg ("%s", __FUNCTION__); | ||
429 | |||
430 | endpoint = usb_pipeendpoint(urb->pipe); | ||
431 | |||
432 | if (urb->status) { | ||
433 | dbg("%s - nonzero status: %x on endpoint %d.", | ||
434 | __FUNCTION__, urb->status, endpoint); | ||
435 | return; | ||
436 | } | ||
437 | |||
438 | port = (struct usb_serial_port *) urb->context; | ||
439 | tty = port->tty; | ||
440 | if (urb->actual_length) { | ||
441 | /* 0x80 bit is error flag */ | ||
442 | if ((data[0] & 0x80) == 0) { | ||
443 | /* no errors on individual bytes, only possible overrun err*/ | ||
444 | if (data[0] & RXERROR_OVERRUN) | ||
445 | err = TTY_OVERRUN; | ||
446 | else err = 0; | ||
447 | for (i = 1; i < urb->actual_length ; ++i) { | ||
448 | tty_insert_flip_char(tty, data[i], err); | ||
449 | } | ||
450 | } else { | ||
451 | /* some bytes had errors, every byte has status */ | ||
452 | dbg("%s - RX error!!!!", __FUNCTION__); | ||
453 | for (i = 0; i + 1 < urb->actual_length; i += 2) { | ||
454 | int stat = data[i], flag = 0; | ||
455 | if (stat & RXERROR_OVERRUN) | ||
456 | flag |= TTY_OVERRUN; | ||
457 | if (stat & RXERROR_FRAMING) | ||
458 | flag |= TTY_FRAME; | ||
459 | if (stat & RXERROR_PARITY) | ||
460 | flag |= TTY_PARITY; | ||
461 | /* XXX should handle break (0x10) */ | ||
462 | tty_insert_flip_char(tty, data[i+1], flag); | ||
463 | } | ||
464 | } | ||
465 | tty_flip_buffer_push(tty); | ||
466 | } | ||
467 | |||
468 | /* Resubmit urb so we continue receiving */ | ||
469 | urb->dev = port->serial->dev; | ||
470 | if (port->open_count) | ||
471 | if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { | ||
472 | dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); | ||
473 | } | ||
474 | return; | ||
475 | } | ||
476 | |||
477 | /* Outdat handling is common for all devices */ | ||
478 | static void usa2x_outdat_callback(struct urb *urb, struct pt_regs *regs) | ||
479 | { | ||
480 | struct usb_serial_port *port; | ||
481 | struct keyspan_port_private *p_priv; | ||
482 | |||
483 | port = (struct usb_serial_port *) urb->context; | ||
484 | p_priv = usb_get_serial_port_data(port); | ||
485 | dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]); | ||
486 | |||
487 | if (port->open_count) | ||
488 | schedule_work(&port->work); | ||
489 | } | ||
490 | |||
491 | static void usa26_inack_callback(struct urb *urb, struct pt_regs *regs) | ||
492 | { | ||
493 | dbg ("%s", __FUNCTION__); | ||
494 | |||
495 | } | ||
496 | |||
497 | static void usa26_outcont_callback(struct urb *urb, struct pt_regs *regs) | ||
498 | { | ||
499 | struct usb_serial_port *port; | ||
500 | struct keyspan_port_private *p_priv; | ||
501 | |||
502 | port = (struct usb_serial_port *) urb->context; | ||
503 | p_priv = usb_get_serial_port_data(port); | ||
504 | |||
505 | if (p_priv->resend_cont) { | ||
506 | dbg ("%s - sending setup", __FUNCTION__); | ||
507 | keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1); | ||
508 | } | ||
509 | } | ||
510 | |||
511 | static void usa26_instat_callback(struct urb *urb, struct pt_regs *regs) | ||
512 | { | ||
513 | unsigned char *data = urb->transfer_buffer; | ||
514 | struct keyspan_usa26_portStatusMessage *msg; | ||
515 | struct usb_serial *serial; | ||
516 | struct usb_serial_port *port; | ||
517 | struct keyspan_port_private *p_priv; | ||
518 | int old_dcd_state, err; | ||
519 | |||
520 | serial = (struct usb_serial *) urb->context; | ||
521 | |||
522 | if (urb->status) { | ||
523 | dbg("%s - nonzero status: %x", __FUNCTION__, urb->status); | ||
524 | return; | ||
525 | } | ||
526 | if (urb->actual_length != 9) { | ||
527 | dbg("%s - %d byte report??", __FUNCTION__, urb->actual_length); | ||
528 | goto exit; | ||
529 | } | ||
530 | |||
531 | msg = (struct keyspan_usa26_portStatusMessage *)data; | ||
532 | |||
533 | #if 0 | ||
534 | dbg("%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d", | ||
535 | __FUNCTION__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff, | ||
536 | msg->_txXoff, msg->rxEnabled, msg->controlResponse); | ||
537 | #endif | ||
538 | |||
539 | /* Now do something useful with the data */ | ||
540 | |||
541 | |||
542 | /* Check port number from message and retrieve private data */ | ||
543 | if (msg->port >= serial->num_ports) { | ||
544 | dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port); | ||
545 | goto exit; | ||
546 | } | ||
547 | port = serial->port[msg->port]; | ||
548 | p_priv = usb_get_serial_port_data(port); | ||
549 | |||
550 | /* Update handshaking pin state information */ | ||
551 | old_dcd_state = p_priv->dcd_state; | ||
552 | p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0); | ||
553 | p_priv->dsr_state = ((msg->dsr) ? 1 : 0); | ||
554 | p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); | ||
555 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | ||
556 | |||
557 | if (port->tty && !C_CLOCAL(port->tty) | ||
558 | && old_dcd_state != p_priv->dcd_state) { | ||
559 | if (old_dcd_state) | ||
560 | tty_hangup(port->tty); | ||
561 | /* else */ | ||
562 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
563 | } | ||
564 | |||
565 | /* Resubmit urb so we continue receiving */ | ||
566 | urb->dev = serial->dev; | ||
567 | if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { | ||
568 | dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); | ||
569 | } | ||
570 | exit: ; | ||
571 | } | ||
572 | |||
573 | static void usa26_glocont_callback(struct urb *urb, struct pt_regs *regs) | ||
574 | { | ||
575 | dbg ("%s", __FUNCTION__); | ||
576 | |||
577 | } | ||
578 | |||
579 | |||
580 | static void usa28_indat_callback(struct urb *urb, struct pt_regs *regs) | ||
581 | { | ||
582 | int i, err; | ||
583 | struct usb_serial_port *port; | ||
584 | struct tty_struct *tty; | ||
585 | unsigned char *data; | ||
586 | struct keyspan_port_private *p_priv; | ||
587 | |||
588 | dbg ("%s", __FUNCTION__); | ||
589 | |||
590 | port = (struct usb_serial_port *) urb->context; | ||
591 | p_priv = usb_get_serial_port_data(port); | ||
592 | data = urb->transfer_buffer; | ||
593 | |||
594 | if (urb != p_priv->in_urbs[p_priv->in_flip]) | ||
595 | return; | ||
596 | |||
597 | do { | ||
598 | if (urb->status) { | ||
599 | dbg("%s - nonzero status: %x on endpoint %d.", | ||
600 | __FUNCTION__, urb->status, usb_pipeendpoint(urb->pipe)); | ||
601 | return; | ||
602 | } | ||
603 | |||
604 | port = (struct usb_serial_port *) urb->context; | ||
605 | p_priv = usb_get_serial_port_data(port); | ||
606 | data = urb->transfer_buffer; | ||
607 | |||
608 | tty = port->tty; | ||
609 | if (urb->actual_length) { | ||
610 | for (i = 0; i < urb->actual_length ; ++i) { | ||
611 | tty_insert_flip_char(tty, data[i], 0); | ||
612 | } | ||
613 | tty_flip_buffer_push(tty); | ||
614 | } | ||
615 | |||
616 | /* Resubmit urb so we continue receiving */ | ||
617 | urb->dev = port->serial->dev; | ||
618 | if (port->open_count) | ||
619 | if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { | ||
620 | dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); | ||
621 | } | ||
622 | p_priv->in_flip ^= 1; | ||
623 | |||
624 | urb = p_priv->in_urbs[p_priv->in_flip]; | ||
625 | } while (urb->status != -EINPROGRESS); | ||
626 | } | ||
627 | |||
628 | static void usa28_inack_callback(struct urb *urb, struct pt_regs *regs) | ||
629 | { | ||
630 | dbg ("%s", __FUNCTION__); | ||
631 | } | ||
632 | |||
633 | static void usa28_outcont_callback(struct urb *urb, struct pt_regs *regs) | ||
634 | { | ||
635 | struct usb_serial_port *port; | ||
636 | struct keyspan_port_private *p_priv; | ||
637 | |||
638 | port = (struct usb_serial_port *) urb->context; | ||
639 | p_priv = usb_get_serial_port_data(port); | ||
640 | |||
641 | if (p_priv->resend_cont) { | ||
642 | dbg ("%s - sending setup", __FUNCTION__); | ||
643 | keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1); | ||
644 | } | ||
645 | } | ||
646 | |||
647 | static void usa28_instat_callback(struct urb *urb, struct pt_regs *regs) | ||
648 | { | ||
649 | int err; | ||
650 | unsigned char *data = urb->transfer_buffer; | ||
651 | struct keyspan_usa28_portStatusMessage *msg; | ||
652 | struct usb_serial *serial; | ||
653 | struct usb_serial_port *port; | ||
654 | struct keyspan_port_private *p_priv; | ||
655 | int old_dcd_state; | ||
656 | |||
657 | serial = (struct usb_serial *) urb->context; | ||
658 | |||
659 | if (urb->status) { | ||
660 | dbg("%s - nonzero status: %x", __FUNCTION__, urb->status); | ||
661 | return; | ||
662 | } | ||
663 | |||
664 | if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) { | ||
665 | dbg("%s - bad length %d", __FUNCTION__, urb->actual_length); | ||
666 | goto exit; | ||
667 | } | ||
668 | |||
669 | /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __FUNCTION__ | ||
670 | data[0], data[1], data[2], data[3], data[4], data[5], | ||
671 | data[6], data[7], data[8], data[9], data[10], data[11]);*/ | ||
672 | |||
673 | /* Now do something useful with the data */ | ||
674 | msg = (struct keyspan_usa28_portStatusMessage *)data; | ||
675 | |||
676 | |||
677 | /* Check port number from message and retrieve private data */ | ||
678 | if (msg->port >= serial->num_ports) { | ||
679 | dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port); | ||
680 | goto exit; | ||
681 | } | ||
682 | port = serial->port[msg->port]; | ||
683 | p_priv = usb_get_serial_port_data(port); | ||
684 | |||
685 | /* Update handshaking pin state information */ | ||
686 | old_dcd_state = p_priv->dcd_state; | ||
687 | p_priv->cts_state = ((msg->cts) ? 1 : 0); | ||
688 | p_priv->dsr_state = ((msg->dsr) ? 1 : 0); | ||
689 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); | ||
690 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | ||
691 | |||
692 | if (port->tty && !C_CLOCAL(port->tty) | ||
693 | && old_dcd_state != p_priv->dcd_state) { | ||
694 | if (old_dcd_state) | ||
695 | tty_hangup(port->tty); | ||
696 | /* else */ | ||
697 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
698 | } | ||
699 | |||
700 | /* Resubmit urb so we continue receiving */ | ||
701 | urb->dev = serial->dev; | ||
702 | if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { | ||
703 | dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); | ||
704 | } | ||
705 | exit: ; | ||
706 | } | ||
707 | |||
708 | static void usa28_glocont_callback(struct urb *urb, struct pt_regs *regs) | ||
709 | { | ||
710 | dbg ("%s", __FUNCTION__); | ||
711 | } | ||
712 | |||
713 | |||
714 | static void usa49_glocont_callback(struct urb *urb, struct pt_regs *regs) | ||
715 | { | ||
716 | struct usb_serial *serial; | ||
717 | struct usb_serial_port *port; | ||
718 | struct keyspan_port_private *p_priv; | ||
719 | int i; | ||
720 | |||
721 | dbg ("%s", __FUNCTION__); | ||
722 | |||
723 | serial = (struct usb_serial *) urb->context; | ||
724 | for (i = 0; i < serial->num_ports; ++i) { | ||
725 | port = serial->port[i]; | ||
726 | p_priv = usb_get_serial_port_data(port); | ||
727 | |||
728 | if (p_priv->resend_cont) { | ||
729 | dbg ("%s - sending setup", __FUNCTION__); | ||
730 | keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1); | ||
731 | break; | ||
732 | } | ||
733 | } | ||
734 | } | ||
735 | |||
736 | /* This is actually called glostat in the Keyspan | ||
737 | doco */ | ||
738 | static void usa49_instat_callback(struct urb *urb, struct pt_regs *regs) | ||
739 | { | ||
740 | int err; | ||
741 | unsigned char *data = urb->transfer_buffer; | ||
742 | struct keyspan_usa49_portStatusMessage *msg; | ||
743 | struct usb_serial *serial; | ||
744 | struct usb_serial_port *port; | ||
745 | struct keyspan_port_private *p_priv; | ||
746 | int old_dcd_state; | ||
747 | |||
748 | dbg ("%s", __FUNCTION__); | ||
749 | |||
750 | serial = (struct usb_serial *) urb->context; | ||
751 | |||
752 | if (urb->status) { | ||
753 | dbg("%s - nonzero status: %x", __FUNCTION__, urb->status); | ||
754 | return; | ||
755 | } | ||
756 | |||
757 | if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) { | ||
758 | dbg("%s - bad length %d", __FUNCTION__, urb->actual_length); | ||
759 | goto exit; | ||
760 | } | ||
761 | |||
762 | /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __FUNCTION__, | ||
763 | data[0], data[1], data[2], data[3], data[4], data[5], | ||
764 | data[6], data[7], data[8], data[9], data[10]);*/ | ||
765 | |||
766 | /* Now do something useful with the data */ | ||
767 | msg = (struct keyspan_usa49_portStatusMessage *)data; | ||
768 | |||
769 | /* Check port number from message and retrieve private data */ | ||
770 | if (msg->portNumber >= serial->num_ports) { | ||
771 | dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->portNumber); | ||
772 | goto exit; | ||
773 | } | ||
774 | port = serial->port[msg->portNumber]; | ||
775 | p_priv = usb_get_serial_port_data(port); | ||
776 | |||
777 | /* Update handshaking pin state information */ | ||
778 | old_dcd_state = p_priv->dcd_state; | ||
779 | p_priv->cts_state = ((msg->cts) ? 1 : 0); | ||
780 | p_priv->dsr_state = ((msg->dsr) ? 1 : 0); | ||
781 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); | ||
782 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | ||
783 | |||
784 | if (port->tty && !C_CLOCAL(port->tty) | ||
785 | && old_dcd_state != p_priv->dcd_state) { | ||
786 | if (old_dcd_state) | ||
787 | tty_hangup(port->tty); | ||
788 | /* else */ | ||
789 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
790 | } | ||
791 | |||
792 | /* Resubmit urb so we continue receiving */ | ||
793 | urb->dev = serial->dev; | ||
794 | |||
795 | if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { | ||
796 | dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); | ||
797 | } | ||
798 | exit: ; | ||
799 | } | ||
800 | |||
801 | static void usa49_inack_callback(struct urb *urb, struct pt_regs *regs) | ||
802 | { | ||
803 | dbg ("%s", __FUNCTION__); | ||
804 | } | ||
805 | |||
806 | static void usa49_indat_callback(struct urb *urb, struct pt_regs *regs) | ||
807 | { | ||
808 | int i, err; | ||
809 | int endpoint; | ||
810 | struct usb_serial_port *port; | ||
811 | struct tty_struct *tty; | ||
812 | unsigned char *data = urb->transfer_buffer; | ||
813 | |||
814 | dbg ("%s", __FUNCTION__); | ||
815 | |||
816 | endpoint = usb_pipeendpoint(urb->pipe); | ||
817 | |||
818 | if (urb->status) { | ||
819 | dbg("%s - nonzero status: %x on endpoint %d.", __FUNCTION__, | ||
820 | urb->status, endpoint); | ||
821 | return; | ||
822 | } | ||
823 | |||
824 | port = (struct usb_serial_port *) urb->context; | ||
825 | tty = port->tty; | ||
826 | if (urb->actual_length) { | ||
827 | /* 0x80 bit is error flag */ | ||
828 | if ((data[0] & 0x80) == 0) { | ||
829 | /* no error on any byte */ | ||
830 | for (i = 1; i < urb->actual_length ; ++i) { | ||
831 | tty_insert_flip_char(tty, data[i], 0); | ||
832 | } | ||
833 | } else { | ||
834 | /* some bytes had errors, every byte has status */ | ||
835 | for (i = 0; i + 1 < urb->actual_length; i += 2) { | ||
836 | int stat = data[i], flag = 0; | ||
837 | if (stat & RXERROR_OVERRUN) | ||
838 | flag |= TTY_OVERRUN; | ||
839 | if (stat & RXERROR_FRAMING) | ||
840 | flag |= TTY_FRAME; | ||
841 | if (stat & RXERROR_PARITY) | ||
842 | flag |= TTY_PARITY; | ||
843 | /* XXX should handle break (0x10) */ | ||
844 | tty_insert_flip_char(tty, data[i+1], flag); | ||
845 | } | ||
846 | } | ||
847 | tty_flip_buffer_push(tty); | ||
848 | } | ||
849 | |||
850 | /* Resubmit urb so we continue receiving */ | ||
851 | urb->dev = port->serial->dev; | ||
852 | if (port->open_count) | ||
853 | if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { | ||
854 | dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); | ||
855 | } | ||
856 | } | ||
857 | |||
858 | /* not used, usa-49 doesn't have per-port control endpoints */ | ||
859 | static void usa49_outcont_callback(struct urb *urb, struct pt_regs *regs) | ||
860 | { | ||
861 | dbg ("%s", __FUNCTION__); | ||
862 | } | ||
863 | |||
864 | static void usa90_indat_callback(struct urb *urb, struct pt_regs *regs) | ||
865 | { | ||
866 | int i, err; | ||
867 | int endpoint; | ||
868 | struct usb_serial_port *port; | ||
869 | struct keyspan_port_private *p_priv; | ||
870 | struct tty_struct *tty; | ||
871 | unsigned char *data = urb->transfer_buffer; | ||
872 | |||
873 | dbg ("%s", __FUNCTION__); | ||
874 | |||
875 | endpoint = usb_pipeendpoint(urb->pipe); | ||
876 | |||
877 | |||
878 | if (urb->status) { | ||
879 | dbg("%s - nonzero status: %x on endpoint %d.", | ||
880 | __FUNCTION__, urb->status, endpoint); | ||
881 | return; | ||
882 | } | ||
883 | |||
884 | port = (struct usb_serial_port *) urb->context; | ||
885 | p_priv = usb_get_serial_port_data(port); | ||
886 | |||
887 | tty = port->tty; | ||
888 | if (urb->actual_length) { | ||
889 | |||
890 | /* if current mode is DMA, looks like usa28 format | ||
891 | otherwise looks like usa26 data format */ | ||
892 | |||
893 | if (p_priv->baud > 57600) { | ||
894 | for (i = 0; i < urb->actual_length ; ++i) | ||
895 | tty_insert_flip_char(tty, data[i], 0); | ||
896 | } | ||
897 | else { | ||
898 | |||
899 | /* 0x80 bit is error flag */ | ||
900 | if ((data[0] & 0x80) == 0) { | ||
901 | /* no errors on individual bytes, only possible overrun err*/ | ||
902 | if (data[0] & RXERROR_OVERRUN) | ||
903 | err = TTY_OVERRUN; | ||
904 | else err = 0; | ||
905 | for (i = 1; i < urb->actual_length ; ++i) | ||
906 | tty_insert_flip_char(tty, data[i], err); | ||
907 | |||
908 | } | ||
909 | else { | ||
910 | /* some bytes had errors, every byte has status */ | ||
911 | dbg("%s - RX error!!!!", __FUNCTION__); | ||
912 | for (i = 0; i + 1 < urb->actual_length; i += 2) { | ||
913 | int stat = data[i], flag = 0; | ||
914 | if (stat & RXERROR_OVERRUN) | ||
915 | flag |= TTY_OVERRUN; | ||
916 | if (stat & RXERROR_FRAMING) | ||
917 | flag |= TTY_FRAME; | ||
918 | if (stat & RXERROR_PARITY) | ||
919 | flag |= TTY_PARITY; | ||
920 | /* XXX should handle break (0x10) */ | ||
921 | tty_insert_flip_char(tty, data[i+1], flag); | ||
922 | } | ||
923 | } | ||
924 | } | ||
925 | tty_flip_buffer_push(tty); | ||
926 | } | ||
927 | |||
928 | /* Resubmit urb so we continue receiving */ | ||
929 | urb->dev = port->serial->dev; | ||
930 | if (port->open_count) | ||
931 | if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { | ||
932 | dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); | ||
933 | } | ||
934 | return; | ||
935 | } | ||
936 | |||
937 | |||
938 | static void usa90_instat_callback(struct urb *urb, struct pt_regs *regs) | ||
939 | { | ||
940 | unsigned char *data = urb->transfer_buffer; | ||
941 | struct keyspan_usa90_portStatusMessage *msg; | ||
942 | struct usb_serial *serial; | ||
943 | struct usb_serial_port *port; | ||
944 | struct keyspan_port_private *p_priv; | ||
945 | int old_dcd_state, err; | ||
946 | |||
947 | serial = (struct usb_serial *) urb->context; | ||
948 | |||
949 | if (urb->status) { | ||
950 | dbg("%s - nonzero status: %x", __FUNCTION__, urb->status); | ||
951 | return; | ||
952 | } | ||
953 | if (urb->actual_length < 14) { | ||
954 | dbg("%s - %d byte report??", __FUNCTION__, urb->actual_length); | ||
955 | goto exit; | ||
956 | } | ||
957 | |||
958 | msg = (struct keyspan_usa90_portStatusMessage *)data; | ||
959 | |||
960 | /* Now do something useful with the data */ | ||
961 | |||
962 | port = serial->port[0]; | ||
963 | p_priv = usb_get_serial_port_data(port); | ||
964 | |||
965 | /* Update handshaking pin state information */ | ||
966 | old_dcd_state = p_priv->dcd_state; | ||
967 | p_priv->cts_state = ((msg->cts) ? 1 : 0); | ||
968 | p_priv->dsr_state = ((msg->dsr) ? 1 : 0); | ||
969 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); | ||
970 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | ||
971 | |||
972 | if (port->tty && !C_CLOCAL(port->tty) | ||
973 | && old_dcd_state != p_priv->dcd_state) { | ||
974 | if (old_dcd_state) | ||
975 | tty_hangup(port->tty); | ||
976 | /* else */ | ||
977 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
978 | } | ||
979 | |||
980 | /* Resubmit urb so we continue receiving */ | ||
981 | urb->dev = serial->dev; | ||
982 | if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { | ||
983 | dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); | ||
984 | } | ||
985 | exit: | ||
986 | ; | ||
987 | } | ||
988 | |||
989 | static void usa90_outcont_callback(struct urb *urb, struct pt_regs *regs) | ||
990 | { | ||
991 | struct usb_serial_port *port; | ||
992 | struct keyspan_port_private *p_priv; | ||
993 | |||
994 | port = (struct usb_serial_port *) urb->context; | ||
995 | p_priv = usb_get_serial_port_data(port); | ||
996 | |||
997 | if (p_priv->resend_cont) { | ||
998 | dbg ("%s - sending setup", __FUNCTION__); | ||
999 | keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1); | ||
1000 | } | ||
1001 | } | ||
1002 | |||
1003 | static int keyspan_write_room (struct usb_serial_port *port) | ||
1004 | { | ||
1005 | struct keyspan_port_private *p_priv; | ||
1006 | const struct keyspan_device_details *d_details; | ||
1007 | int flip; | ||
1008 | int data_len; | ||
1009 | struct urb *this_urb; | ||
1010 | |||
1011 | dbg("%s", __FUNCTION__); | ||
1012 | p_priv = usb_get_serial_port_data(port); | ||
1013 | d_details = p_priv->device_details; | ||
1014 | |||
1015 | if (d_details->msg_format == msg_usa90) | ||
1016 | data_len = 64; | ||
1017 | else | ||
1018 | data_len = 63; | ||
1019 | |||
1020 | flip = p_priv->out_flip; | ||
1021 | |||
1022 | /* Check both endpoints to see if any are available. */ | ||
1023 | if ((this_urb = p_priv->out_urbs[flip]) != NULL) { | ||
1024 | if (this_urb->status != -EINPROGRESS) | ||
1025 | return (data_len); | ||
1026 | flip = (flip + 1) & d_details->outdat_endp_flip; | ||
1027 | if ((this_urb = p_priv->out_urbs[flip]) != NULL) | ||
1028 | if (this_urb->status != -EINPROGRESS) | ||
1029 | return (data_len); | ||
1030 | } | ||
1031 | return (0); | ||
1032 | } | ||
1033 | |||
1034 | |||
1035 | static int keyspan_chars_in_buffer (struct usb_serial_port *port) | ||
1036 | { | ||
1037 | return (0); | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | static int keyspan_open (struct usb_serial_port *port, struct file *filp) | ||
1042 | { | ||
1043 | struct keyspan_port_private *p_priv; | ||
1044 | struct keyspan_serial_private *s_priv; | ||
1045 | struct usb_serial *serial = port->serial; | ||
1046 | const struct keyspan_device_details *d_details; | ||
1047 | int i, err; | ||
1048 | int baud_rate, device_port; | ||
1049 | struct urb *urb; | ||
1050 | unsigned int cflag; | ||
1051 | |||
1052 | s_priv = usb_get_serial_data(serial); | ||
1053 | p_priv = usb_get_serial_port_data(port); | ||
1054 | d_details = p_priv->device_details; | ||
1055 | |||
1056 | dbg("%s - port%d.", __FUNCTION__, port->number); | ||
1057 | |||
1058 | /* Set some sane defaults */ | ||
1059 | p_priv->rts_state = 1; | ||
1060 | p_priv->dtr_state = 1; | ||
1061 | p_priv->baud = 9600; | ||
1062 | |||
1063 | /* force baud and lcr to be set on open */ | ||
1064 | p_priv->old_baud = 0; | ||
1065 | p_priv->old_cflag = 0; | ||
1066 | |||
1067 | p_priv->out_flip = 0; | ||
1068 | p_priv->in_flip = 0; | ||
1069 | |||
1070 | /* Reset low level data toggle and start reading from endpoints */ | ||
1071 | for (i = 0; i < 2; i++) { | ||
1072 | if ((urb = p_priv->in_urbs[i]) == NULL) | ||
1073 | continue; | ||
1074 | urb->dev = serial->dev; | ||
1075 | |||
1076 | /* make sure endpoint data toggle is synchronized with the device */ | ||
1077 | |||
1078 | usb_clear_halt(urb->dev, urb->pipe); | ||
1079 | |||
1080 | if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) { | ||
1081 | dbg("%s - submit urb %d failed (%d)", __FUNCTION__, i, err); | ||
1082 | } | ||
1083 | } | ||
1084 | |||
1085 | /* Reset low level data toggle on out endpoints */ | ||
1086 | for (i = 0; i < 2; i++) { | ||
1087 | if ((urb = p_priv->out_urbs[i]) == NULL) | ||
1088 | continue; | ||
1089 | urb->dev = serial->dev; | ||
1090 | /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */ | ||
1091 | } | ||
1092 | |||
1093 | /* get the terminal config for the setup message now so we don't | ||
1094 | * need to send 2 of them */ | ||
1095 | |||
1096 | cflag = port->tty->termios->c_cflag; | ||
1097 | device_port = port->number - port->serial->minor; | ||
1098 | |||
1099 | /* Baud rate calculation takes baud rate as an integer | ||
1100 | so other rates can be generated if desired. */ | ||
1101 | baud_rate = tty_get_baud_rate(port->tty); | ||
1102 | /* If no match or invalid, leave as default */ | ||
1103 | if (baud_rate >= 0 | ||
1104 | && d_details->calculate_baud_rate(baud_rate, d_details->baudclk, | ||
1105 | NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { | ||
1106 | p_priv->baud = baud_rate; | ||
1107 | } | ||
1108 | |||
1109 | /* set CTS/RTS handshake etc. */ | ||
1110 | p_priv->cflag = cflag; | ||
1111 | p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none; | ||
1112 | |||
1113 | keyspan_send_setup(port, 1); | ||
1114 | //mdelay(100); | ||
1115 | //keyspan_set_termios(port, NULL); | ||
1116 | |||
1117 | return (0); | ||
1118 | } | ||
1119 | |||
1120 | static inline void stop_urb(struct urb *urb) | ||
1121 | { | ||
1122 | if (urb && urb->status == -EINPROGRESS) { | ||
1123 | urb->transfer_flags &= ~URB_ASYNC_UNLINK; | ||
1124 | usb_kill_urb(urb); | ||
1125 | } | ||
1126 | } | ||
1127 | |||
1128 | static void keyspan_close(struct usb_serial_port *port, struct file *filp) | ||
1129 | { | ||
1130 | int i; | ||
1131 | struct usb_serial *serial = port->serial; | ||
1132 | struct keyspan_serial_private *s_priv; | ||
1133 | struct keyspan_port_private *p_priv; | ||
1134 | |||
1135 | dbg("%s", __FUNCTION__); | ||
1136 | s_priv = usb_get_serial_data(serial); | ||
1137 | p_priv = usb_get_serial_port_data(port); | ||
1138 | |||
1139 | p_priv->rts_state = 0; | ||
1140 | p_priv->dtr_state = 0; | ||
1141 | |||
1142 | if (serial->dev) { | ||
1143 | keyspan_send_setup(port, 2); | ||
1144 | /* pilot-xfer seems to work best with this delay */ | ||
1145 | mdelay(100); | ||
1146 | // keyspan_set_termios(port, NULL); | ||
1147 | } | ||
1148 | |||
1149 | /*while (p_priv->outcont_urb->status == -EINPROGRESS) { | ||
1150 | dbg("%s - urb in progress", __FUNCTION__); | ||
1151 | }*/ | ||
1152 | |||
1153 | p_priv->out_flip = 0; | ||
1154 | p_priv->in_flip = 0; | ||
1155 | |||
1156 | if (serial->dev) { | ||
1157 | /* Stop reading/writing urbs */ | ||
1158 | stop_urb(p_priv->inack_urb); | ||
1159 | /* stop_urb(p_priv->outcont_urb); */ | ||
1160 | for (i = 0; i < 2; i++) { | ||
1161 | stop_urb(p_priv->in_urbs[i]); | ||
1162 | stop_urb(p_priv->out_urbs[i]); | ||
1163 | } | ||
1164 | } | ||
1165 | port->tty = NULL; | ||
1166 | } | ||
1167 | |||
1168 | |||
1169 | /* download the firmware to a pre-renumeration device */ | ||
1170 | static int keyspan_fake_startup (struct usb_serial *serial) | ||
1171 | { | ||
1172 | int response; | ||
1173 | const struct ezusb_hex_record *record; | ||
1174 | char *fw_name; | ||
1175 | |||
1176 | dbg("Keyspan startup version %04x product %04x", | ||
1177 | le16_to_cpu(serial->dev->descriptor.bcdDevice), | ||
1178 | le16_to_cpu(serial->dev->descriptor.idProduct)); | ||
1179 | |||
1180 | if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000) != 0x8000) { | ||
1181 | dbg("Firmware already loaded. Quitting."); | ||
1182 | return(1); | ||
1183 | } | ||
1184 | |||
1185 | /* Select firmware image on the basis of idProduct */ | ||
1186 | switch (le16_to_cpu(serial->dev->descriptor.idProduct)) { | ||
1187 | case keyspan_usa28_pre_product_id: | ||
1188 | record = &keyspan_usa28_firmware[0]; | ||
1189 | fw_name = "USA28"; | ||
1190 | break; | ||
1191 | |||
1192 | case keyspan_usa28x_pre_product_id: | ||
1193 | record = &keyspan_usa28x_firmware[0]; | ||
1194 | fw_name = "USA28X"; | ||
1195 | break; | ||
1196 | |||
1197 | case keyspan_usa28xa_pre_product_id: | ||
1198 | record = &keyspan_usa28xa_firmware[0]; | ||
1199 | fw_name = "USA28XA"; | ||
1200 | break; | ||
1201 | |||
1202 | case keyspan_usa28xb_pre_product_id: | ||
1203 | record = &keyspan_usa28xb_firmware[0]; | ||
1204 | fw_name = "USA28XB"; | ||
1205 | break; | ||
1206 | |||
1207 | case keyspan_usa19_pre_product_id: | ||
1208 | record = &keyspan_usa19_firmware[0]; | ||
1209 | fw_name = "USA19"; | ||
1210 | break; | ||
1211 | |||
1212 | case keyspan_usa19qi_pre_product_id: | ||
1213 | record = &keyspan_usa19qi_firmware[0]; | ||
1214 | fw_name = "USA19QI"; | ||
1215 | break; | ||
1216 | |||
1217 | case keyspan_mpr_pre_product_id: | ||
1218 | record = &keyspan_mpr_firmware[0]; | ||
1219 | fw_name = "MPR"; | ||
1220 | break; | ||
1221 | |||
1222 | case keyspan_usa19qw_pre_product_id: | ||
1223 | record = &keyspan_usa19qw_firmware[0]; | ||
1224 | fw_name = "USA19QI"; | ||
1225 | break; | ||
1226 | |||
1227 | case keyspan_usa18x_pre_product_id: | ||
1228 | record = &keyspan_usa18x_firmware[0]; | ||
1229 | fw_name = "USA18X"; | ||
1230 | break; | ||
1231 | |||
1232 | case keyspan_usa19w_pre_product_id: | ||
1233 | record = &keyspan_usa19w_firmware[0]; | ||
1234 | fw_name = "USA19W"; | ||
1235 | break; | ||
1236 | |||
1237 | case keyspan_usa49w_pre_product_id: | ||
1238 | record = &keyspan_usa49w_firmware[0]; | ||
1239 | fw_name = "USA49W"; | ||
1240 | break; | ||
1241 | |||
1242 | case keyspan_usa49wlc_pre_product_id: | ||
1243 | record = &keyspan_usa49wlc_firmware[0]; | ||
1244 | fw_name = "USA49WLC"; | ||
1245 | break; | ||
1246 | |||
1247 | default: | ||
1248 | record = NULL; | ||
1249 | fw_name = "Unknown"; | ||
1250 | break; | ||
1251 | } | ||
1252 | |||
1253 | if (record == NULL) { | ||
1254 | dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name); | ||
1255 | return(1); | ||
1256 | } | ||
1257 | |||
1258 | dbg("Uploading Keyspan %s firmware.", fw_name); | ||
1259 | |||
1260 | /* download the firmware image */ | ||
1261 | response = ezusb_set_reset(serial, 1); | ||
1262 | |||
1263 | while(record->address != 0xffff) { | ||
1264 | response = ezusb_writememory(serial, record->address, | ||
1265 | (unsigned char *)record->data, | ||
1266 | record->data_size, 0xa0); | ||
1267 | if (response < 0) { | ||
1268 | dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan" | ||
1269 | "firmware (%d %04X %p %d)\n", | ||
1270 | response, | ||
1271 | record->address, record->data, record->data_size); | ||
1272 | break; | ||
1273 | } | ||
1274 | record++; | ||
1275 | } | ||
1276 | /* bring device out of reset. Renumeration will occur in a | ||
1277 | moment and the new device will bind to the real driver */ | ||
1278 | response = ezusb_set_reset(serial, 0); | ||
1279 | |||
1280 | /* we don't want this device to have a driver assigned to it. */ | ||
1281 | return (1); | ||
1282 | } | ||
1283 | |||
1284 | /* Helper functions used by keyspan_setup_urbs */ | ||
1285 | static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint, | ||
1286 | int dir, void *ctx, char *buf, int len, | ||
1287 | void (*callback)(struct urb *, struct pt_regs *regs)) | ||
1288 | { | ||
1289 | struct urb *urb; | ||
1290 | |||
1291 | if (endpoint == -1) | ||
1292 | return NULL; /* endpoint not needed */ | ||
1293 | |||
1294 | dbg ("%s - alloc for endpoint %d.", __FUNCTION__, endpoint); | ||
1295 | urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ | ||
1296 | if (urb == NULL) { | ||
1297 | dbg ("%s - alloc for endpoint %d failed.", __FUNCTION__, endpoint); | ||
1298 | return NULL; | ||
1299 | } | ||
1300 | |||
1301 | /* Fill URB using supplied data. */ | ||
1302 | usb_fill_bulk_urb(urb, serial->dev, | ||
1303 | usb_sndbulkpipe(serial->dev, endpoint) | dir, | ||
1304 | buf, len, callback, ctx); | ||
1305 | |||
1306 | return urb; | ||
1307 | } | ||
1308 | |||
1309 | static struct callbacks { | ||
1310 | void (*instat_callback)(struct urb *, struct pt_regs *regs); | ||
1311 | void (*glocont_callback)(struct urb *, struct pt_regs *regs); | ||
1312 | void (*indat_callback)(struct urb *, struct pt_regs *regs); | ||
1313 | void (*outdat_callback)(struct urb *, struct pt_regs *regs); | ||
1314 | void (*inack_callback)(struct urb *, struct pt_regs *regs); | ||
1315 | void (*outcont_callback)(struct urb *, struct pt_regs *regs); | ||
1316 | } keyspan_callbacks[] = { | ||
1317 | { | ||
1318 | /* msg_usa26 callbacks */ | ||
1319 | .instat_callback = usa26_instat_callback, | ||
1320 | .glocont_callback = usa26_glocont_callback, | ||
1321 | .indat_callback = usa26_indat_callback, | ||
1322 | .outdat_callback = usa2x_outdat_callback, | ||
1323 | .inack_callback = usa26_inack_callback, | ||
1324 | .outcont_callback = usa26_outcont_callback, | ||
1325 | }, { | ||
1326 | /* msg_usa28 callbacks */ | ||
1327 | .instat_callback = usa28_instat_callback, | ||
1328 | .glocont_callback = usa28_glocont_callback, | ||
1329 | .indat_callback = usa28_indat_callback, | ||
1330 | .outdat_callback = usa2x_outdat_callback, | ||
1331 | .inack_callback = usa28_inack_callback, | ||
1332 | .outcont_callback = usa28_outcont_callback, | ||
1333 | }, { | ||
1334 | /* msg_usa49 callbacks */ | ||
1335 | .instat_callback = usa49_instat_callback, | ||
1336 | .glocont_callback = usa49_glocont_callback, | ||
1337 | .indat_callback = usa49_indat_callback, | ||
1338 | .outdat_callback = usa2x_outdat_callback, | ||
1339 | .inack_callback = usa49_inack_callback, | ||
1340 | .outcont_callback = usa49_outcont_callback, | ||
1341 | }, { | ||
1342 | /* msg_usa90 callbacks */ | ||
1343 | .instat_callback = usa90_instat_callback, | ||
1344 | .glocont_callback = usa28_glocont_callback, | ||
1345 | .indat_callback = usa90_indat_callback, | ||
1346 | .outdat_callback = usa2x_outdat_callback, | ||
1347 | .inack_callback = usa28_inack_callback, | ||
1348 | .outcont_callback = usa90_outcont_callback, | ||
1349 | } | ||
1350 | }; | ||
1351 | |||
1352 | /* Generic setup urbs function that uses | ||
1353 | data in device_details */ | ||
1354 | static void keyspan_setup_urbs(struct usb_serial *serial) | ||
1355 | { | ||
1356 | int i, j; | ||
1357 | struct keyspan_serial_private *s_priv; | ||
1358 | const struct keyspan_device_details *d_details; | ||
1359 | struct usb_serial_port *port; | ||
1360 | struct keyspan_port_private *p_priv; | ||
1361 | struct callbacks *cback; | ||
1362 | int endp; | ||
1363 | |||
1364 | dbg ("%s", __FUNCTION__); | ||
1365 | |||
1366 | s_priv = usb_get_serial_data(serial); | ||
1367 | d_details = s_priv->device_details; | ||
1368 | |||
1369 | /* Setup values for the various callback routines */ | ||
1370 | cback = &keyspan_callbacks[d_details->msg_format]; | ||
1371 | |||
1372 | /* Allocate and set up urbs for each one that is in use, | ||
1373 | starting with instat endpoints */ | ||
1374 | s_priv->instat_urb = keyspan_setup_urb | ||
1375 | (serial, d_details->instat_endpoint, USB_DIR_IN, | ||
1376 | serial, s_priv->instat_buf, INSTAT_BUFLEN, | ||
1377 | cback->instat_callback); | ||
1378 | |||
1379 | s_priv->glocont_urb = keyspan_setup_urb | ||
1380 | (serial, d_details->glocont_endpoint, USB_DIR_OUT, | ||
1381 | serial, s_priv->glocont_buf, GLOCONT_BUFLEN, | ||
1382 | cback->glocont_callback); | ||
1383 | |||
1384 | /* Setup endpoints for each port specific thing */ | ||
1385 | for (i = 0; i < d_details->num_ports; i ++) { | ||
1386 | port = serial->port[i]; | ||
1387 | p_priv = usb_get_serial_port_data(port); | ||
1388 | |||
1389 | /* Do indat endpoints first, once for each flip */ | ||
1390 | endp = d_details->indat_endpoints[i]; | ||
1391 | for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) { | ||
1392 | p_priv->in_urbs[j] = keyspan_setup_urb | ||
1393 | (serial, endp, USB_DIR_IN, port, | ||
1394 | p_priv->in_buffer[j], 64, | ||
1395 | cback->indat_callback); | ||
1396 | } | ||
1397 | for (; j < 2; ++j) | ||
1398 | p_priv->in_urbs[j] = NULL; | ||
1399 | |||
1400 | /* outdat endpoints also have flip */ | ||
1401 | endp = d_details->outdat_endpoints[i]; | ||
1402 | for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) { | ||
1403 | p_priv->out_urbs[j] = keyspan_setup_urb | ||
1404 | (serial, endp, USB_DIR_OUT, port, | ||
1405 | p_priv->out_buffer[j], 64, | ||
1406 | cback->outdat_callback); | ||
1407 | } | ||
1408 | for (; j < 2; ++j) | ||
1409 | p_priv->out_urbs[j] = NULL; | ||
1410 | |||
1411 | /* inack endpoint */ | ||
1412 | p_priv->inack_urb = keyspan_setup_urb | ||
1413 | (serial, d_details->inack_endpoints[i], USB_DIR_IN, | ||
1414 | port, p_priv->inack_buffer, 1, cback->inack_callback); | ||
1415 | |||
1416 | /* outcont endpoint */ | ||
1417 | p_priv->outcont_urb = keyspan_setup_urb | ||
1418 | (serial, d_details->outcont_endpoints[i], USB_DIR_OUT, | ||
1419 | port, p_priv->outcont_buffer, 64, | ||
1420 | cback->outcont_callback); | ||
1421 | } | ||
1422 | |||
1423 | } | ||
1424 | |||
1425 | /* usa19 function doesn't require prescaler */ | ||
1426 | static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, | ||
1427 | u8 *rate_low, u8 *prescaler, int portnum) | ||
1428 | { | ||
1429 | u32 b16, /* baud rate times 16 (actual rate used internally) */ | ||
1430 | div, /* divisor */ | ||
1431 | cnt; /* inverse of divisor (programmed into 8051) */ | ||
1432 | |||
1433 | dbg ("%s - %d.", __FUNCTION__, baud_rate); | ||
1434 | |||
1435 | /* prevent divide by zero... */ | ||
1436 | if( (b16 = (baud_rate * 16L)) == 0) { | ||
1437 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1438 | } | ||
1439 | |||
1440 | /* Any "standard" rate over 57k6 is marginal on the USA-19 | ||
1441 | as we run out of divisor resolution. */ | ||
1442 | if (baud_rate > 57600) { | ||
1443 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1444 | } | ||
1445 | |||
1446 | /* calculate the divisor and the counter (its inverse) */ | ||
1447 | if( (div = (baudclk / b16)) == 0) { | ||
1448 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1449 | } | ||
1450 | else { | ||
1451 | cnt = 0 - div; | ||
1452 | } | ||
1453 | |||
1454 | if(div > 0xffff) { | ||
1455 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1456 | } | ||
1457 | |||
1458 | /* return the counter values if non-null */ | ||
1459 | if (rate_low) { | ||
1460 | *rate_low = (u8) (cnt & 0xff); | ||
1461 | } | ||
1462 | if (rate_hi) { | ||
1463 | *rate_hi = (u8) ((cnt >> 8) & 0xff); | ||
1464 | } | ||
1465 | if (rate_low && rate_hi) { | ||
1466 | dbg ("%s - %d %02x %02x.", __FUNCTION__, baud_rate, *rate_hi, *rate_low); | ||
1467 | } | ||
1468 | |||
1469 | return (KEYSPAN_BAUD_RATE_OK); | ||
1470 | } | ||
1471 | |||
1472 | /* usa19hs function doesn't require prescaler */ | ||
1473 | static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, | ||
1474 | u8 *rate_low, u8 *prescaler, int portnum) | ||
1475 | { | ||
1476 | u32 b16, /* baud rate times 16 (actual rate used internally) */ | ||
1477 | div; /* divisor */ | ||
1478 | |||
1479 | dbg ("%s - %d.", __FUNCTION__, baud_rate); | ||
1480 | |||
1481 | /* prevent divide by zero... */ | ||
1482 | if( (b16 = (baud_rate * 16L)) == 0) | ||
1483 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1484 | |||
1485 | |||
1486 | |||
1487 | /* calculate the divisor */ | ||
1488 | if( (div = (baudclk / b16)) == 0) | ||
1489 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1490 | |||
1491 | if(div > 0xffff) | ||
1492 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1493 | |||
1494 | /* return the counter values if non-null */ | ||
1495 | if (rate_low) | ||
1496 | *rate_low = (u8) (div & 0xff); | ||
1497 | |||
1498 | if (rate_hi) | ||
1499 | *rate_hi = (u8) ((div >> 8) & 0xff); | ||
1500 | |||
1501 | if (rate_low && rate_hi) | ||
1502 | dbg ("%s - %d %02x %02x.", __FUNCTION__, baud_rate, *rate_hi, *rate_low); | ||
1503 | |||
1504 | return (KEYSPAN_BAUD_RATE_OK); | ||
1505 | } | ||
1506 | |||
1507 | static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, | ||
1508 | u8 *rate_low, u8 *prescaler, int portnum) | ||
1509 | { | ||
1510 | u32 b16, /* baud rate times 16 (actual rate used internally) */ | ||
1511 | clk, /* clock with 13/8 prescaler */ | ||
1512 | div, /* divisor using 13/8 prescaler */ | ||
1513 | res, /* resulting baud rate using 13/8 prescaler */ | ||
1514 | diff, /* error using 13/8 prescaler */ | ||
1515 | smallest_diff; | ||
1516 | u8 best_prescaler; | ||
1517 | int i; | ||
1518 | |||
1519 | dbg ("%s - %d.", __FUNCTION__, baud_rate); | ||
1520 | |||
1521 | /* prevent divide by zero */ | ||
1522 | if( (b16 = baud_rate * 16L) == 0) { | ||
1523 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1524 | } | ||
1525 | |||
1526 | /* Calculate prescaler by trying them all and looking | ||
1527 | for best fit */ | ||
1528 | |||
1529 | /* start with largest possible difference */ | ||
1530 | smallest_diff = 0xffffffff; | ||
1531 | |||
1532 | /* 0 is an invalid prescaler, used as a flag */ | ||
1533 | best_prescaler = 0; | ||
1534 | |||
1535 | for(i = 8; i <= 0xff; ++i) { | ||
1536 | clk = (baudclk * 8) / (u32) i; | ||
1537 | |||
1538 | if( (div = clk / b16) == 0) { | ||
1539 | continue; | ||
1540 | } | ||
1541 | |||
1542 | res = clk / div; | ||
1543 | diff= (res > b16) ? (res-b16) : (b16-res); | ||
1544 | |||
1545 | if(diff < smallest_diff) { | ||
1546 | best_prescaler = i; | ||
1547 | smallest_diff = diff; | ||
1548 | } | ||
1549 | } | ||
1550 | |||
1551 | if(best_prescaler == 0) { | ||
1552 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1553 | } | ||
1554 | |||
1555 | clk = (baudclk * 8) / (u32) best_prescaler; | ||
1556 | div = clk / b16; | ||
1557 | |||
1558 | /* return the divisor and prescaler if non-null */ | ||
1559 | if (rate_low) { | ||
1560 | *rate_low = (u8) (div & 0xff); | ||
1561 | } | ||
1562 | if (rate_hi) { | ||
1563 | *rate_hi = (u8) ((div >> 8) & 0xff); | ||
1564 | } | ||
1565 | if (prescaler) { | ||
1566 | *prescaler = best_prescaler; | ||
1567 | /* dbg("%s - %d %d", __FUNCTION__, *prescaler, div); */ | ||
1568 | } | ||
1569 | return (KEYSPAN_BAUD_RATE_OK); | ||
1570 | } | ||
1571 | |||
1572 | /* USA-28 supports different maximum baud rates on each port */ | ||
1573 | static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, | ||
1574 | u8 *rate_low, u8 *prescaler, int portnum) | ||
1575 | { | ||
1576 | u32 b16, /* baud rate times 16 (actual rate used internally) */ | ||
1577 | div, /* divisor */ | ||
1578 | cnt; /* inverse of divisor (programmed into 8051) */ | ||
1579 | |||
1580 | dbg ("%s - %d.", __FUNCTION__, baud_rate); | ||
1581 | |||
1582 | /* prevent divide by zero */ | ||
1583 | if ((b16 = baud_rate * 16L) == 0) | ||
1584 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1585 | |||
1586 | /* calculate the divisor and the counter (its inverse) */ | ||
1587 | if ((div = (KEYSPAN_USA28_BAUDCLK / b16)) == 0) { | ||
1588 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1589 | } | ||
1590 | else { | ||
1591 | cnt = 0 - div; | ||
1592 | } | ||
1593 | |||
1594 | /* check for out of range, based on portnum, | ||
1595 | and return result */ | ||
1596 | if(portnum == 0) { | ||
1597 | if(div > 0xffff) | ||
1598 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1599 | } | ||
1600 | else { | ||
1601 | if(portnum == 1) { | ||
1602 | if(div > 0xff) { | ||
1603 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1604 | } | ||
1605 | } | ||
1606 | else { | ||
1607 | return (KEYSPAN_INVALID_BAUD_RATE); | ||
1608 | } | ||
1609 | } | ||
1610 | |||
1611 | /* return the counter values if not NULL | ||
1612 | (port 1 will ignore retHi) */ | ||
1613 | if (rate_low) { | ||
1614 | *rate_low = (u8) (cnt & 0xff); | ||
1615 | } | ||
1616 | if (rate_hi) { | ||
1617 | *rate_hi = (u8) ((cnt >> 8) & 0xff); | ||
1618 | } | ||
1619 | dbg ("%s - %d OK.", __FUNCTION__, baud_rate); | ||
1620 | return (KEYSPAN_BAUD_RATE_OK); | ||
1621 | } | ||
1622 | |||
1623 | static int keyspan_usa26_send_setup(struct usb_serial *serial, | ||
1624 | struct usb_serial_port *port, | ||
1625 | int reset_port) | ||
1626 | { | ||
1627 | struct keyspan_usa26_portControlMessage msg; | ||
1628 | struct keyspan_serial_private *s_priv; | ||
1629 | struct keyspan_port_private *p_priv; | ||
1630 | const struct keyspan_device_details *d_details; | ||
1631 | int outcont_urb; | ||
1632 | struct urb *this_urb; | ||
1633 | int device_port, err; | ||
1634 | |||
1635 | dbg ("%s reset=%d", __FUNCTION__, reset_port); | ||
1636 | |||
1637 | s_priv = usb_get_serial_data(serial); | ||
1638 | p_priv = usb_get_serial_port_data(port); | ||
1639 | d_details = s_priv->device_details; | ||
1640 | device_port = port->number - port->serial->minor; | ||
1641 | |||
1642 | outcont_urb = d_details->outcont_endpoints[port->number]; | ||
1643 | this_urb = p_priv->outcont_urb; | ||
1644 | |||
1645 | dbg("%s - endpoint %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe)); | ||
1646 | |||
1647 | /* Make sure we have an urb then send the message */ | ||
1648 | if (this_urb == NULL) { | ||
1649 | dbg("%s - oops no urb.", __FUNCTION__); | ||
1650 | return -1; | ||
1651 | } | ||
1652 | |||
1653 | /* Save reset port val for resend. | ||
1654 | Don't overwrite resend for close condition. */ | ||
1655 | if (p_priv->resend_cont != 3) | ||
1656 | p_priv->resend_cont = reset_port + 1; | ||
1657 | if (this_urb->status == -EINPROGRESS) { | ||
1658 | /* dbg ("%s - already writing", __FUNCTION__); */ | ||
1659 | mdelay(5); | ||
1660 | return(-1); | ||
1661 | } | ||
1662 | |||
1663 | memset(&msg, 0, sizeof (struct keyspan_usa26_portControlMessage)); | ||
1664 | |||
1665 | /* Only set baud rate if it's changed */ | ||
1666 | if (p_priv->old_baud != p_priv->baud) { | ||
1667 | p_priv->old_baud = p_priv->baud; | ||
1668 | msg.setClocking = 0xff; | ||
1669 | if (d_details->calculate_baud_rate | ||
1670 | (p_priv->baud, d_details->baudclk, &msg.baudHi, | ||
1671 | &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) { | ||
1672 | dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__, | ||
1673 | p_priv->baud); | ||
1674 | msg.baudLo = 0; | ||
1675 | msg.baudHi = 125; /* Values for 9600 baud */ | ||
1676 | msg.prescaler = 10; | ||
1677 | } | ||
1678 | msg.setPrescaler = 0xff; | ||
1679 | } | ||
1680 | |||
1681 | msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1; | ||
1682 | switch (p_priv->cflag & CSIZE) { | ||
1683 | case CS5: | ||
1684 | msg.lcr |= USA_DATABITS_5; | ||
1685 | break; | ||
1686 | case CS6: | ||
1687 | msg.lcr |= USA_DATABITS_6; | ||
1688 | break; | ||
1689 | case CS7: | ||
1690 | msg.lcr |= USA_DATABITS_7; | ||
1691 | break; | ||
1692 | case CS8: | ||
1693 | msg.lcr |= USA_DATABITS_8; | ||
1694 | break; | ||
1695 | } | ||
1696 | if (p_priv->cflag & PARENB) { | ||
1697 | /* note USA_PARITY_NONE == 0 */ | ||
1698 | msg.lcr |= (p_priv->cflag & PARODD)? | ||
1699 | USA_PARITY_ODD: USA_PARITY_EVEN; | ||
1700 | } | ||
1701 | msg.setLcr = 0xff; | ||
1702 | |||
1703 | msg.ctsFlowControl = (p_priv->flow_control == flow_cts); | ||
1704 | msg.xonFlowControl = 0; | ||
1705 | msg.setFlowControl = 0xff; | ||
1706 | msg.forwardingLength = 16; | ||
1707 | msg.xonChar = 17; | ||
1708 | msg.xoffChar = 19; | ||
1709 | |||
1710 | /* Opening port */ | ||
1711 | if (reset_port == 1) { | ||
1712 | msg._txOn = 1; | ||
1713 | msg._txOff = 0; | ||
1714 | msg.txFlush = 0; | ||
1715 | msg.txBreak = 0; | ||
1716 | msg.rxOn = 1; | ||
1717 | msg.rxOff = 0; | ||
1718 | msg.rxFlush = 1; | ||
1719 | msg.rxForward = 0; | ||
1720 | msg.returnStatus = 0; | ||
1721 | msg.resetDataToggle = 0xff; | ||
1722 | } | ||
1723 | |||
1724 | /* Closing port */ | ||
1725 | else if (reset_port == 2) { | ||
1726 | msg._txOn = 0; | ||
1727 | msg._txOff = 1; | ||
1728 | msg.txFlush = 0; | ||
1729 | msg.txBreak = 0; | ||
1730 | msg.rxOn = 0; | ||
1731 | msg.rxOff = 1; | ||
1732 | msg.rxFlush = 1; | ||
1733 | msg.rxForward = 0; | ||
1734 | msg.returnStatus = 0; | ||
1735 | msg.resetDataToggle = 0; | ||
1736 | } | ||
1737 | |||
1738 | /* Sending intermediate configs */ | ||
1739 | else { | ||
1740 | msg._txOn = (! p_priv->break_on); | ||
1741 | msg._txOff = 0; | ||
1742 | msg.txFlush = 0; | ||
1743 | msg.txBreak = (p_priv->break_on); | ||
1744 | msg.rxOn = 0; | ||
1745 | msg.rxOff = 0; | ||
1746 | msg.rxFlush = 0; | ||
1747 | msg.rxForward = 0; | ||
1748 | msg.returnStatus = 0; | ||
1749 | msg.resetDataToggle = 0x0; | ||
1750 | } | ||
1751 | |||
1752 | /* Do handshaking outputs */ | ||
1753 | msg.setTxTriState_setRts = 0xff; | ||
1754 | msg.txTriState_rts = p_priv->rts_state; | ||
1755 | |||
1756 | msg.setHskoa_setDtr = 0xff; | ||
1757 | msg.hskoa_dtr = p_priv->dtr_state; | ||
1758 | |||
1759 | p_priv->resend_cont = 0; | ||
1760 | memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); | ||
1761 | |||
1762 | /* send the data out the device on control endpoint */ | ||
1763 | this_urb->transfer_buffer_length = sizeof(msg); | ||
1764 | |||
1765 | this_urb->dev = serial->dev; | ||
1766 | if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { | ||
1767 | dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err); | ||
1768 | } | ||
1769 | #if 0 | ||
1770 | else { | ||
1771 | dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__ | ||
1772 | outcont_urb, this_urb->transfer_buffer_length, | ||
1773 | usb_pipeendpoint(this_urb->pipe)); | ||
1774 | } | ||
1775 | #endif | ||
1776 | |||
1777 | return (0); | ||
1778 | } | ||
1779 | |||
1780 | static int keyspan_usa28_send_setup(struct usb_serial *serial, | ||
1781 | struct usb_serial_port *port, | ||
1782 | int reset_port) | ||
1783 | { | ||
1784 | struct keyspan_usa28_portControlMessage msg; | ||
1785 | struct keyspan_serial_private *s_priv; | ||
1786 | struct keyspan_port_private *p_priv; | ||
1787 | const struct keyspan_device_details *d_details; | ||
1788 | struct urb *this_urb; | ||
1789 | int device_port, err; | ||
1790 | |||
1791 | dbg ("%s", __FUNCTION__); | ||
1792 | |||
1793 | s_priv = usb_get_serial_data(serial); | ||
1794 | p_priv = usb_get_serial_port_data(port); | ||
1795 | d_details = s_priv->device_details; | ||
1796 | device_port = port->number - port->serial->minor; | ||
1797 | |||
1798 | /* only do something if we have a bulk out endpoint */ | ||
1799 | if ((this_urb = p_priv->outcont_urb) == NULL) { | ||
1800 | dbg("%s - oops no urb.", __FUNCTION__); | ||
1801 | return -1; | ||
1802 | } | ||
1803 | |||
1804 | /* Save reset port val for resend. | ||
1805 | Don't overwrite resend for close condition. */ | ||
1806 | if (p_priv->resend_cont != 3) | ||
1807 | p_priv->resend_cont = reset_port + 1; | ||
1808 | if (this_urb->status == -EINPROGRESS) { | ||
1809 | dbg ("%s already writing", __FUNCTION__); | ||
1810 | mdelay(5); | ||
1811 | return(-1); | ||
1812 | } | ||
1813 | |||
1814 | memset(&msg, 0, sizeof (struct keyspan_usa28_portControlMessage)); | ||
1815 | |||
1816 | msg.setBaudRate = 1; | ||
1817 | if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk, | ||
1818 | &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE ) { | ||
1819 | dbg("%s - Invalid baud rate requested %d.", __FUNCTION__, p_priv->baud); | ||
1820 | msg.baudLo = 0xff; | ||
1821 | msg.baudHi = 0xb2; /* Values for 9600 baud */ | ||
1822 | } | ||
1823 | |||
1824 | /* If parity is enabled, we must calculate it ourselves. */ | ||
1825 | msg.parity = 0; /* XXX for now */ | ||
1826 | |||
1827 | msg.ctsFlowControl = (p_priv->flow_control == flow_cts); | ||
1828 | msg.xonFlowControl = 0; | ||
1829 | |||
1830 | /* Do handshaking outputs, DTR is inverted relative to RTS */ | ||
1831 | msg.rts = p_priv->rts_state; | ||
1832 | msg.dtr = p_priv->dtr_state; | ||
1833 | |||
1834 | msg.forwardingLength = 16; | ||
1835 | msg.forwardMs = 10; | ||
1836 | msg.breakThreshold = 45; | ||
1837 | msg.xonChar = 17; | ||
1838 | msg.xoffChar = 19; | ||
1839 | |||
1840 | /*msg.returnStatus = 1; | ||
1841 | msg.resetDataToggle = 0xff;*/ | ||
1842 | /* Opening port */ | ||
1843 | if (reset_port == 1) { | ||
1844 | msg._txOn = 1; | ||
1845 | msg._txOff = 0; | ||
1846 | msg.txFlush = 0; | ||
1847 | msg.txForceXoff = 0; | ||
1848 | msg.txBreak = 0; | ||
1849 | msg.rxOn = 1; | ||
1850 | msg.rxOff = 0; | ||
1851 | msg.rxFlush = 1; | ||
1852 | msg.rxForward = 0; | ||
1853 | msg.returnStatus = 0; | ||
1854 | msg.resetDataToggle = 0xff; | ||
1855 | } | ||
1856 | /* Closing port */ | ||
1857 | else if (reset_port == 2) { | ||
1858 | msg._txOn = 0; | ||
1859 | msg._txOff = 1; | ||
1860 | msg.txFlush = 0; | ||
1861 | msg.txForceXoff = 0; | ||
1862 | msg.txBreak = 0; | ||
1863 | msg.rxOn = 0; | ||
1864 | msg.rxOff = 1; | ||
1865 | msg.rxFlush = 1; | ||
1866 | msg.rxForward = 0; | ||
1867 | msg.returnStatus = 0; | ||
1868 | msg.resetDataToggle = 0; | ||
1869 | } | ||
1870 | /* Sending intermediate configs */ | ||
1871 | else { | ||
1872 | msg._txOn = (! p_priv->break_on); | ||
1873 | msg._txOff = 0; | ||
1874 | msg.txFlush = 0; | ||
1875 | msg.txForceXoff = 0; | ||
1876 | msg.txBreak = (p_priv->break_on); | ||
1877 | msg.rxOn = 0; | ||
1878 | msg.rxOff = 0; | ||
1879 | msg.rxFlush = 0; | ||
1880 | msg.rxForward = 0; | ||
1881 | msg.returnStatus = 0; | ||
1882 | msg.resetDataToggle = 0x0; | ||
1883 | } | ||
1884 | |||
1885 | p_priv->resend_cont = 0; | ||
1886 | memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); | ||
1887 | |||
1888 | /* send the data out the device on control endpoint */ | ||
1889 | this_urb->transfer_buffer_length = sizeof(msg); | ||
1890 | |||
1891 | this_urb->dev = serial->dev; | ||
1892 | if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { | ||
1893 | dbg("%s - usb_submit_urb(setup) failed", __FUNCTION__); | ||
1894 | } | ||
1895 | #if 0 | ||
1896 | else { | ||
1897 | dbg("%s - usb_submit_urb(setup) OK %d bytes", __FUNCTION__, | ||
1898 | this_urb->transfer_buffer_length); | ||
1899 | } | ||
1900 | #endif | ||
1901 | |||
1902 | return (0); | ||
1903 | } | ||
1904 | |||
1905 | static int keyspan_usa49_send_setup(struct usb_serial *serial, | ||
1906 | struct usb_serial_port *port, | ||
1907 | int reset_port) | ||
1908 | { | ||
1909 | struct keyspan_usa49_portControlMessage msg; | ||
1910 | struct keyspan_serial_private *s_priv; | ||
1911 | struct keyspan_port_private *p_priv; | ||
1912 | const struct keyspan_device_details *d_details; | ||
1913 | int glocont_urb; | ||
1914 | struct urb *this_urb; | ||
1915 | int err, device_port; | ||
1916 | |||
1917 | dbg ("%s", __FUNCTION__); | ||
1918 | |||
1919 | s_priv = usb_get_serial_data(serial); | ||
1920 | p_priv = usb_get_serial_port_data(port); | ||
1921 | d_details = s_priv->device_details; | ||
1922 | |||
1923 | glocont_urb = d_details->glocont_endpoint; | ||
1924 | this_urb = s_priv->glocont_urb; | ||
1925 | |||
1926 | /* Work out which port within the device is being setup */ | ||
1927 | device_port = port->number - port->serial->minor; | ||
1928 | |||
1929 | dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port); | ||
1930 | |||
1931 | /* Make sure we have an urb then send the message */ | ||
1932 | if (this_urb == NULL) { | ||
1933 | dbg("%s - oops no urb for port %d.", __FUNCTION__, port->number); | ||
1934 | return -1; | ||
1935 | } | ||
1936 | |||
1937 | /* Save reset port val for resend. | ||
1938 | Don't overwrite resend for close condition. */ | ||
1939 | if (p_priv->resend_cont != 3) | ||
1940 | p_priv->resend_cont = reset_port + 1; | ||
1941 | if (this_urb->status == -EINPROGRESS) { | ||
1942 | /* dbg ("%s - already writing", __FUNCTION__); */ | ||
1943 | mdelay(5); | ||
1944 | return(-1); | ||
1945 | } | ||
1946 | |||
1947 | memset(&msg, 0, sizeof (struct keyspan_usa49_portControlMessage)); | ||
1948 | |||
1949 | /*msg.portNumber = port->number;*/ | ||
1950 | msg.portNumber = device_port; | ||
1951 | |||
1952 | /* Only set baud rate if it's changed */ | ||
1953 | if (p_priv->old_baud != p_priv->baud) { | ||
1954 | p_priv->old_baud = p_priv->baud; | ||
1955 | msg.setClocking = 0xff; | ||
1956 | if (d_details->calculate_baud_rate | ||
1957 | (p_priv->baud, d_details->baudclk, &msg.baudHi, | ||
1958 | &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) { | ||
1959 | dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__, | ||
1960 | p_priv->baud); | ||
1961 | msg.baudLo = 0; | ||
1962 | msg.baudHi = 125; /* Values for 9600 baud */ | ||
1963 | msg.prescaler = 10; | ||
1964 | } | ||
1965 | //msg.setPrescaler = 0xff; | ||
1966 | } | ||
1967 | |||
1968 | msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1; | ||
1969 | switch (p_priv->cflag & CSIZE) { | ||
1970 | case CS5: | ||
1971 | msg.lcr |= USA_DATABITS_5; | ||
1972 | break; | ||
1973 | case CS6: | ||
1974 | msg.lcr |= USA_DATABITS_6; | ||
1975 | break; | ||
1976 | case CS7: | ||
1977 | msg.lcr |= USA_DATABITS_7; | ||
1978 | break; | ||
1979 | case CS8: | ||
1980 | msg.lcr |= USA_DATABITS_8; | ||
1981 | break; | ||
1982 | } | ||
1983 | if (p_priv->cflag & PARENB) { | ||
1984 | /* note USA_PARITY_NONE == 0 */ | ||
1985 | msg.lcr |= (p_priv->cflag & PARODD)? | ||
1986 | USA_PARITY_ODD: USA_PARITY_EVEN; | ||
1987 | } | ||
1988 | msg.setLcr = 0xff; | ||
1989 | |||
1990 | msg.ctsFlowControl = (p_priv->flow_control == flow_cts); | ||
1991 | msg.xonFlowControl = 0; | ||
1992 | msg.setFlowControl = 0xff; | ||
1993 | |||
1994 | msg.forwardingLength = 16; | ||
1995 | msg.xonChar = 17; | ||
1996 | msg.xoffChar = 19; | ||
1997 | |||
1998 | /* Opening port */ | ||
1999 | if (reset_port == 1) { | ||
2000 | msg._txOn = 1; | ||
2001 | msg._txOff = 0; | ||
2002 | msg.txFlush = 0; | ||
2003 | msg.txBreak = 0; | ||
2004 | msg.rxOn = 1; | ||
2005 | msg.rxOff = 0; | ||
2006 | msg.rxFlush = 1; | ||
2007 | msg.rxForward = 0; | ||
2008 | msg.returnStatus = 0; | ||
2009 | msg.resetDataToggle = 0xff; | ||
2010 | msg.enablePort = 1; | ||
2011 | msg.disablePort = 0; | ||
2012 | } | ||
2013 | /* Closing port */ | ||
2014 | else if (reset_port == 2) { | ||
2015 | msg._txOn = 0; | ||
2016 | msg._txOff = 1; | ||
2017 | msg.txFlush = 0; | ||
2018 | msg.txBreak = 0; | ||
2019 | msg.rxOn = 0; | ||
2020 | msg.rxOff = 1; | ||
2021 | msg.rxFlush = 1; | ||
2022 | msg.rxForward = 0; | ||
2023 | msg.returnStatus = 0; | ||
2024 | msg.resetDataToggle = 0; | ||
2025 | msg.enablePort = 0; | ||
2026 | msg.disablePort = 1; | ||
2027 | } | ||
2028 | /* Sending intermediate configs */ | ||
2029 | else { | ||
2030 | msg._txOn = (! p_priv->break_on); | ||
2031 | msg._txOff = 0; | ||
2032 | msg.txFlush = 0; | ||
2033 | msg.txBreak = (p_priv->break_on); | ||
2034 | msg.rxOn = 0; | ||
2035 | msg.rxOff = 0; | ||
2036 | msg.rxFlush = 0; | ||
2037 | msg.rxForward = 0; | ||
2038 | msg.returnStatus = 0; | ||
2039 | msg.resetDataToggle = 0x0; | ||
2040 | msg.enablePort = 0; | ||
2041 | msg.disablePort = 0; | ||
2042 | } | ||
2043 | |||
2044 | /* Do handshaking outputs */ | ||
2045 | msg.setRts = 0xff; | ||
2046 | msg.rts = p_priv->rts_state; | ||
2047 | |||
2048 | msg.setDtr = 0xff; | ||
2049 | msg.dtr = p_priv->dtr_state; | ||
2050 | |||
2051 | p_priv->resend_cont = 0; | ||
2052 | memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); | ||
2053 | |||
2054 | /* send the data out the device on control endpoint */ | ||
2055 | this_urb->transfer_buffer_length = sizeof(msg); | ||
2056 | |||
2057 | this_urb->dev = serial->dev; | ||
2058 | if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { | ||
2059 | dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err); | ||
2060 | } | ||
2061 | #if 0 | ||
2062 | else { | ||
2063 | dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__, | ||
2064 | outcont_urb, this_urb->transfer_buffer_length, | ||
2065 | usb_pipeendpoint(this_urb->pipe)); | ||
2066 | } | ||
2067 | #endif | ||
2068 | |||
2069 | return (0); | ||
2070 | } | ||
2071 | |||
2072 | static int keyspan_usa90_send_setup(struct usb_serial *serial, | ||
2073 | struct usb_serial_port *port, | ||
2074 | int reset_port) | ||
2075 | { | ||
2076 | struct keyspan_usa90_portControlMessage msg; | ||
2077 | struct keyspan_serial_private *s_priv; | ||
2078 | struct keyspan_port_private *p_priv; | ||
2079 | const struct keyspan_device_details *d_details; | ||
2080 | struct urb *this_urb; | ||
2081 | int err; | ||
2082 | u8 prescaler; | ||
2083 | |||
2084 | dbg ("%s", __FUNCTION__); | ||
2085 | |||
2086 | s_priv = usb_get_serial_data(serial); | ||
2087 | p_priv = usb_get_serial_port_data(port); | ||
2088 | d_details = s_priv->device_details; | ||
2089 | |||
2090 | /* only do something if we have a bulk out endpoint */ | ||
2091 | if ((this_urb = p_priv->outcont_urb) == NULL) { | ||
2092 | dbg("%s - oops no urb.", __FUNCTION__); | ||
2093 | return -1; | ||
2094 | } | ||
2095 | |||
2096 | /* Save reset port val for resend. | ||
2097 | Don't overwrite resend for open/close condition. */ | ||
2098 | if ((reset_port + 1) > p_priv->resend_cont) | ||
2099 | p_priv->resend_cont = reset_port + 1; | ||
2100 | if (this_urb->status == -EINPROGRESS) { | ||
2101 | dbg ("%s already writing", __FUNCTION__); | ||
2102 | mdelay(5); | ||
2103 | return(-1); | ||
2104 | } | ||
2105 | |||
2106 | memset(&msg, 0, sizeof (struct keyspan_usa90_portControlMessage)); | ||
2107 | |||
2108 | /* Only set baud rate if it's changed */ | ||
2109 | if (p_priv->old_baud != p_priv->baud) { | ||
2110 | p_priv->old_baud = p_priv->baud; | ||
2111 | msg.setClocking = 0x01; | ||
2112 | if (d_details->calculate_baud_rate | ||
2113 | (p_priv->baud, d_details->baudclk, &msg.baudHi, | ||
2114 | &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) { | ||
2115 | dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__, | ||
2116 | p_priv->baud); | ||
2117 | p_priv->baud = 9600; | ||
2118 | d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk, | ||
2119 | &msg.baudHi, &msg.baudLo, &prescaler, 0); | ||
2120 | } | ||
2121 | msg.setRxMode = 1; | ||
2122 | msg.setTxMode = 1; | ||
2123 | } | ||
2124 | |||
2125 | /* modes must always be correctly specified */ | ||
2126 | if (p_priv->baud > 57600) | ||
2127 | { | ||
2128 | msg.rxMode = RXMODE_DMA; | ||
2129 | msg.txMode = TXMODE_DMA; | ||
2130 | } | ||
2131 | else | ||
2132 | { | ||
2133 | msg.rxMode = RXMODE_BYHAND; | ||
2134 | msg.txMode = TXMODE_BYHAND; | ||
2135 | } | ||
2136 | |||
2137 | msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1; | ||
2138 | switch (p_priv->cflag & CSIZE) { | ||
2139 | case CS5: | ||
2140 | msg.lcr |= USA_DATABITS_5; | ||
2141 | break; | ||
2142 | case CS6: | ||
2143 | msg.lcr |= USA_DATABITS_6; | ||
2144 | break; | ||
2145 | case CS7: | ||
2146 | msg.lcr |= USA_DATABITS_7; | ||
2147 | break; | ||
2148 | case CS8: | ||
2149 | msg.lcr |= USA_DATABITS_8; | ||
2150 | break; | ||
2151 | } | ||
2152 | if (p_priv->cflag & PARENB) { | ||
2153 | /* note USA_PARITY_NONE == 0 */ | ||
2154 | msg.lcr |= (p_priv->cflag & PARODD)? | ||
2155 | USA_PARITY_ODD: USA_PARITY_EVEN; | ||
2156 | } | ||
2157 | if (p_priv->old_cflag != p_priv->cflag) { | ||
2158 | p_priv->old_cflag = p_priv->cflag; | ||
2159 | msg.setLcr = 0x01; | ||
2160 | } | ||
2161 | |||
2162 | if (p_priv->flow_control == flow_cts) | ||
2163 | msg.txFlowControl = TXFLOW_CTS; | ||
2164 | msg.setTxFlowControl = 0x01; | ||
2165 | msg.setRxFlowControl = 0x01; | ||
2166 | |||
2167 | msg.rxForwardingLength = 16; | ||
2168 | msg.rxForwardingTimeout = 16; | ||
2169 | msg.txAckSetting = 0; | ||
2170 | msg.xonChar = 17; | ||
2171 | msg.xoffChar = 19; | ||
2172 | |||
2173 | /* Opening port */ | ||
2174 | if (reset_port == 1) { | ||
2175 | msg.portEnabled = 1; | ||
2176 | msg.rxFlush = 1; | ||
2177 | msg.txBreak = (p_priv->break_on); | ||
2178 | } | ||
2179 | /* Closing port */ | ||
2180 | else if (reset_port == 2) { | ||
2181 | msg.portEnabled = 0; | ||
2182 | } | ||
2183 | /* Sending intermediate configs */ | ||
2184 | else { | ||
2185 | if (port->open_count) | ||
2186 | msg.portEnabled = 1; | ||
2187 | msg.txBreak = (p_priv->break_on); | ||
2188 | } | ||
2189 | |||
2190 | /* Do handshaking outputs */ | ||
2191 | msg.setRts = 0x01; | ||
2192 | msg.rts = p_priv->rts_state; | ||
2193 | |||
2194 | msg.setDtr = 0x01; | ||
2195 | msg.dtr = p_priv->dtr_state; | ||
2196 | |||
2197 | p_priv->resend_cont = 0; | ||
2198 | memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); | ||
2199 | |||
2200 | /* send the data out the device on control endpoint */ | ||
2201 | this_urb->transfer_buffer_length = sizeof(msg); | ||
2202 | |||
2203 | this_urb->dev = serial->dev; | ||
2204 | if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { | ||
2205 | dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err); | ||
2206 | } | ||
2207 | return (0); | ||
2208 | } | ||
2209 | |||
2210 | static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) | ||
2211 | { | ||
2212 | struct usb_serial *serial = port->serial; | ||
2213 | struct keyspan_serial_private *s_priv; | ||
2214 | const struct keyspan_device_details *d_details; | ||
2215 | |||
2216 | dbg ("%s", __FUNCTION__); | ||
2217 | |||
2218 | s_priv = usb_get_serial_data(serial); | ||
2219 | d_details = s_priv->device_details; | ||
2220 | |||
2221 | switch (d_details->msg_format) { | ||
2222 | case msg_usa26: | ||
2223 | keyspan_usa26_send_setup(serial, port, reset_port); | ||
2224 | break; | ||
2225 | case msg_usa28: | ||
2226 | keyspan_usa28_send_setup(serial, port, reset_port); | ||
2227 | break; | ||
2228 | case msg_usa49: | ||
2229 | keyspan_usa49_send_setup(serial, port, reset_port); | ||
2230 | break; | ||
2231 | case msg_usa90: | ||
2232 | keyspan_usa90_send_setup(serial, port, reset_port); | ||
2233 | break; | ||
2234 | } | ||
2235 | } | ||
2236 | |||
2237 | |||
2238 | /* Gets called by the "real" driver (ie once firmware is loaded | ||
2239 | and renumeration has taken place. */ | ||
2240 | static int keyspan_startup (struct usb_serial *serial) | ||
2241 | { | ||
2242 | int i, err; | ||
2243 | struct usb_serial_port *port; | ||
2244 | struct keyspan_serial_private *s_priv; | ||
2245 | struct keyspan_port_private *p_priv; | ||
2246 | const struct keyspan_device_details *d_details; | ||
2247 | |||
2248 | dbg("%s", __FUNCTION__); | ||
2249 | |||
2250 | for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) | ||
2251 | if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct)) | ||
2252 | break; | ||
2253 | if (d_details == NULL) { | ||
2254 | dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __FUNCTION__, le16_to_cpu(serial->dev->descriptor.idProduct)); | ||
2255 | return 1; | ||
2256 | } | ||
2257 | |||
2258 | /* Setup private data for serial driver */ | ||
2259 | s_priv = kmalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL); | ||
2260 | if (!s_priv) { | ||
2261 | dbg("%s - kmalloc for keyspan_serial_private failed.", __FUNCTION__); | ||
2262 | return -ENOMEM; | ||
2263 | } | ||
2264 | memset(s_priv, 0, sizeof(struct keyspan_serial_private)); | ||
2265 | |||
2266 | s_priv->device_details = d_details; | ||
2267 | usb_set_serial_data(serial, s_priv); | ||
2268 | |||
2269 | /* Now setup per port private data */ | ||
2270 | for (i = 0; i < serial->num_ports; i++) { | ||
2271 | port = serial->port[i]; | ||
2272 | p_priv = kmalloc(sizeof(struct keyspan_port_private), GFP_KERNEL); | ||
2273 | if (!p_priv) { | ||
2274 | dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __FUNCTION__, i); | ||
2275 | return (1); | ||
2276 | } | ||
2277 | memset(p_priv, 0, sizeof(struct keyspan_port_private)); | ||
2278 | p_priv->device_details = d_details; | ||
2279 | usb_set_serial_port_data(port, p_priv); | ||
2280 | } | ||
2281 | |||
2282 | keyspan_setup_urbs(serial); | ||
2283 | |||
2284 | s_priv->instat_urb->dev = serial->dev; | ||
2285 | if ((err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL)) != 0) { | ||
2286 | dbg("%s - submit instat urb failed %d", __FUNCTION__, err); | ||
2287 | } | ||
2288 | |||
2289 | return (0); | ||
2290 | } | ||
2291 | |||
2292 | static void keyspan_shutdown (struct usb_serial *serial) | ||
2293 | { | ||
2294 | int i, j; | ||
2295 | struct usb_serial_port *port; | ||
2296 | struct keyspan_serial_private *s_priv; | ||
2297 | struct keyspan_port_private *p_priv; | ||
2298 | |||
2299 | dbg("%s", __FUNCTION__); | ||
2300 | |||
2301 | s_priv = usb_get_serial_data(serial); | ||
2302 | |||
2303 | /* Stop reading/writing urbs */ | ||
2304 | stop_urb(s_priv->instat_urb); | ||
2305 | stop_urb(s_priv->glocont_urb); | ||
2306 | for (i = 0; i < serial->num_ports; ++i) { | ||
2307 | port = serial->port[i]; | ||
2308 | p_priv = usb_get_serial_port_data(port); | ||
2309 | stop_urb(p_priv->inack_urb); | ||
2310 | stop_urb(p_priv->outcont_urb); | ||
2311 | for (j = 0; j < 2; j++) { | ||
2312 | stop_urb(p_priv->in_urbs[j]); | ||
2313 | stop_urb(p_priv->out_urbs[j]); | ||
2314 | } | ||
2315 | } | ||
2316 | |||
2317 | /* Now free them */ | ||
2318 | if (s_priv->instat_urb) | ||
2319 | usb_free_urb(s_priv->instat_urb); | ||
2320 | if (s_priv->glocont_urb) | ||
2321 | usb_free_urb(s_priv->glocont_urb); | ||
2322 | for (i = 0; i < serial->num_ports; ++i) { | ||
2323 | port = serial->port[i]; | ||
2324 | p_priv = usb_get_serial_port_data(port); | ||
2325 | if (p_priv->inack_urb) | ||
2326 | usb_free_urb(p_priv->inack_urb); | ||
2327 | if (p_priv->outcont_urb) | ||
2328 | usb_free_urb(p_priv->outcont_urb); | ||
2329 | for (j = 0; j < 2; j++) { | ||
2330 | if (p_priv->in_urbs[j]) | ||
2331 | usb_free_urb(p_priv->in_urbs[j]); | ||
2332 | if (p_priv->out_urbs[j]) | ||
2333 | usb_free_urb(p_priv->out_urbs[j]); | ||
2334 | } | ||
2335 | } | ||
2336 | |||
2337 | /* dbg("Freeing serial->private."); */ | ||
2338 | kfree(s_priv); | ||
2339 | |||
2340 | /* dbg("Freeing port->private."); */ | ||
2341 | /* Now free per port private data */ | ||
2342 | for (i = 0; i < serial->num_ports; i++) { | ||
2343 | port = serial->port[i]; | ||
2344 | kfree(usb_get_serial_port_data(port)); | ||
2345 | } | ||
2346 | } | ||
2347 | |||
2348 | MODULE_AUTHOR( DRIVER_AUTHOR ); | ||
2349 | MODULE_DESCRIPTION( DRIVER_DESC ); | ||
2350 | MODULE_LICENSE("GPL"); | ||
2351 | |||
2352 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
2353 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
2354 | |||