aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/cypress_m8.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/usb/serial/cypress_m8.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/cypress_m8.c')
-rw-r--r--drivers/usb/serial/cypress_m8.c1538
1 files changed, 1538 insertions, 0 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
new file mode 100644
index 000000000000..db8f472d9e3f
--- /dev/null
+++ b/drivers/usb/serial/cypress_m8.c
@@ -0,0 +1,1538 @@
1/*
2 * USB Cypress M8 driver
3 *
4 * Copyright (C) 2004
5 * Lonnie Mendez (dignome@gmail.com)
6 * Copyright (C) 2003,2004
7 * Neil Whelchel (koyama@firstlight.net)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * See Documentation/usb/usb-serial.txt for more information on using this driver
15 *
16 * See http://geocities.com/i0xox0i for information on this driver and the
17 * earthmate usb device.
18 *
19 *
20 * Lonnie Mendez <dignome@gmail.com>
21 * 12-15-2004
22 * Incorporated write buffering from pl2303 driver. Fixed bug with line
23 * handling so both lines are raised in cypress_open. (was dropping rts)
24 * Various code cleanups made as well along with other misc bug fixes.
25 *
26 * Lonnie Mendez <dignome@gmail.com>
27 * 04-10-2004
28 * Driver modified to support dynamic line settings. Various improvments
29 * and features.
30 *
31 * Neil Whelchel
32 * 10-2003
33 * Driver first released.
34 *
35 *
36 * Long Term TODO:
37 * Improve transfer speeds - both read/write are somewhat slow
38 * at this point.
39 * Improve debugging. Show modem line status with debug output and
40 * implement filtering for certain data as a module parameter.
41 */
42
43/* Thanks to Neil Whelchel for writing the first cypress m8 implementation for linux. */
44/* Thanks to cypress for providing references for the hid reports. */
45/* Thanks to Jiang Zhang for providing links and for general help. */
46/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others. */
47
48
49#include <linux/config.h>
50#include <linux/kernel.h>
51#include <linux/errno.h>
52#include <linux/init.h>
53#include <linux/slab.h>
54#include <linux/tty.h>
55#include <linux/tty_driver.h>
56#include <linux/tty_flip.h>
57#include <linux/module.h>
58#include <linux/moduleparam.h>
59#include <linux/spinlock.h>
60#include <linux/usb.h>
61#include <linux/serial.h>
62#include <linux/delay.h>
63#include <asm/uaccess.h>
64
65#include "usb-serial.h"
66#include "cypress_m8.h"
67
68
69#ifdef CONFIG_USB_SERIAL_DEBUG
70 static int debug = 1;
71#else
72 static int debug;
73#endif
74static int stats;
75
76/*
77 * Version Information
78 */
79#define DRIVER_VERSION "v1.08"
80#define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>"
81#define DRIVER_DESC "Cypress USB to Serial Driver"
82
83/* write buffer size defines */
84#define CYPRESS_BUF_SIZE 1024
85#define CYPRESS_CLOSING_WAIT (30*HZ)
86
87static struct usb_device_id id_table_earthmate [] = {
88 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
89 { } /* Terminating entry */
90};
91
92static struct usb_device_id id_table_cyphidcomrs232 [] = {
93 { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
94 { } /* Terminating entry */
95};
96
97static struct usb_device_id id_table_combined [] = {
98 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
99 { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
100 { } /* Terminating entry */
101};
102
103MODULE_DEVICE_TABLE (usb, id_table_combined);
104
105static struct usb_driver cypress_driver = {
106 .name = "cypress",
107 .probe = usb_serial_probe,
108 .disconnect = usb_serial_disconnect,
109 .id_table = id_table_combined,
110};
111
112struct cypress_private {
113 spinlock_t lock; /* private lock */
114 int chiptype; /* identifier of device, for quirks/etc */
115 int bytes_in; /* used for statistics */
116 int bytes_out; /* used for statistics */
117 int cmd_count; /* used for statistics */
118 int cmd_ctrl; /* always set this to 1 before issuing a command */
119 struct cypress_buf *buf; /* write buffer */
120 int write_urb_in_use; /* write urb in use indicator */
121 int termios_initialized;
122 __u8 line_control; /* holds dtr / rts value */
123 __u8 current_status; /* received from last read - info on dsr,cts,cd,ri,etc */
124 __u8 current_config; /* stores the current configuration byte */
125 __u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */
126 int baud_rate; /* stores current baud rate in integer form */
127 int cbr_mask; /* stores current baud rate in masked form */
128 int isthrottled; /* if throttled, discard reads */
129 wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */
130 char prev_status, diff_status; /* used for TIOCMIWAIT */
131 /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */
132 struct termios tmp_termios; /* stores the old termios settings */
133 char calledfromopen; /* used when issuing lines on open - fixes rts drop bug */
134};
135
136/* write buffer structure */
137struct cypress_buf {
138 unsigned int buf_size;
139 char *buf_buf;
140 char *buf_get;
141 char *buf_put;
142};
143
144/* function prototypes for the Cypress USB to serial device */
145static int cypress_earthmate_startup (struct usb_serial *serial);
146static int cypress_hidcom_startup (struct usb_serial *serial);
147static void cypress_shutdown (struct usb_serial *serial);
148static int cypress_open (struct usb_serial_port *port, struct file *filp);
149static void cypress_close (struct usb_serial_port *port, struct file *filp);
150static int cypress_write (struct usb_serial_port *port, const unsigned char *buf, int count);
151static void cypress_send (struct usb_serial_port *port);
152static int cypress_write_room (struct usb_serial_port *port);
153static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
154static void cypress_set_termios (struct usb_serial_port *port, struct termios * old);
155static int cypress_tiocmget (struct usb_serial_port *port, struct file *file);
156static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
157static int cypress_chars_in_buffer (struct usb_serial_port *port);
158static void cypress_throttle (struct usb_serial_port *port);
159static void cypress_unthrottle (struct usb_serial_port *port);
160static void cypress_read_int_callback (struct urb *urb, struct pt_regs *regs);
161static void cypress_write_int_callback (struct urb *urb, struct pt_regs *regs);
162/* baud helper functions */
163static int mask_to_rate (unsigned mask);
164static unsigned rate_to_mask (int rate);
165/* write buffer functions */
166static struct cypress_buf *cypress_buf_alloc(unsigned int size);
167static void cypress_buf_free(struct cypress_buf *cb);
168static void cypress_buf_clear(struct cypress_buf *cb);
169static unsigned int cypress_buf_data_avail(struct cypress_buf *cb);
170static unsigned int cypress_buf_space_avail(struct cypress_buf *cb);
171static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf,
172 unsigned int count);
173static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf,
174 unsigned int count);
175
176
177static struct usb_serial_device_type cypress_earthmate_device = {
178 .owner = THIS_MODULE,
179 .name = "DeLorme Earthmate USB",
180 .short_name = "earthmate",
181 .id_table = id_table_earthmate,
182 .num_interrupt_in = 1,
183 .num_interrupt_out = 1,
184 .num_bulk_in = NUM_DONT_CARE,
185 .num_bulk_out = NUM_DONT_CARE,
186 .num_ports = 1,
187 .attach = cypress_earthmate_startup,
188 .shutdown = cypress_shutdown,
189 .open = cypress_open,
190 .close = cypress_close,
191 .write = cypress_write,
192 .write_room = cypress_write_room,
193 .ioctl = cypress_ioctl,
194 .set_termios = cypress_set_termios,
195 .tiocmget = cypress_tiocmget,
196 .tiocmset = cypress_tiocmset,
197 .chars_in_buffer = cypress_chars_in_buffer,
198 .throttle = cypress_throttle,
199 .unthrottle = cypress_unthrottle,
200 .read_int_callback = cypress_read_int_callback,
201 .write_int_callback = cypress_write_int_callback,
202};
203
204static struct usb_serial_device_type cypress_hidcom_device = {
205 .owner = THIS_MODULE,
206 .name = "HID->COM RS232 Adapter",
207 .short_name = "cyphidcom",
208 .id_table = id_table_cyphidcomrs232,
209 .num_interrupt_in = 1,
210 .num_interrupt_out = 1,
211 .num_bulk_in = NUM_DONT_CARE,
212 .num_bulk_out = NUM_DONT_CARE,
213 .num_ports = 1,
214 .attach = cypress_hidcom_startup,
215 .shutdown = cypress_shutdown,
216 .open = cypress_open,
217 .close = cypress_close,
218 .write = cypress_write,
219 .write_room = cypress_write_room,
220 .ioctl = cypress_ioctl,
221 .set_termios = cypress_set_termios,
222 .tiocmget = cypress_tiocmget,
223 .tiocmset = cypress_tiocmset,
224 .chars_in_buffer = cypress_chars_in_buffer,
225 .throttle = cypress_throttle,
226 .unthrottle = cypress_unthrottle,
227 .read_int_callback = cypress_read_int_callback,
228 .write_int_callback = cypress_write_int_callback,
229};
230
231
232/*****************************************************************************
233 * Cypress serial helper functions
234 *****************************************************************************/
235
236
237/* This function can either set or retreive the current serial line settings */
238static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits,
239 int parity_enable, int parity_type, int reset, int cypress_request_type)
240{
241 int i, n_baud_rate = 0, retval = 0;
242 struct cypress_private *priv;
243 __u8 feature_buffer[5];
244 __u8 config;
245 unsigned long flags;
246
247 dbg("%s", __FUNCTION__);
248
249 priv = usb_get_serial_port_data(port);
250
251 switch(cypress_request_type) {
252 case CYPRESS_SET_CONFIG:
253
254 /*
255 * The general purpose firmware for the Cypress M8 allows for a maximum speed
256 * of 57600bps (I have no idea whether DeLorme chose to use the general purpose
257 * firmware or not), if you need to modify this speed setting for your own
258 * project please add your own chiptype and modify the code likewise. The
259 * Cypress HID->COM device will work successfully up to 115200bps.
260 */
261 if (baud_mask != priv->cbr_mask) {
262 dbg("%s - baud rate is changing", __FUNCTION__);
263 if ( priv->chiptype == CT_EARTHMATE ) {
264 /* 300 and 600 baud rates are supported under the generic firmware,
265 * but are not used with NMEA and SiRF protocols */
266
267 if ( (baud_mask == B300) || (baud_mask == B600) ) {
268 err("%s - failed setting baud rate, unsupported speed (default to 4800)",
269 __FUNCTION__);
270 n_baud_rate = 4800;
271 } else if ( (n_baud_rate = mask_to_rate(baud_mask)) == -1) {
272 err("%s - failed setting baud rate, unsupported speed (default to 4800)",
273 __FUNCTION__);
274 n_baud_rate = 4800;
275 }
276 } else if (priv->chiptype == CT_CYPHIDCOM) {
277 if ( (n_baud_rate = mask_to_rate(baud_mask)) == -1) {
278 err("%s - failed setting baud rate, unsupported speed (default to 4800)",
279 __FUNCTION__);
280 n_baud_rate = 4800;
281 }
282 } else if (priv->chiptype == CT_GENERIC) {
283 if ( (n_baud_rate = mask_to_rate(baud_mask)) == -1) {
284 err("%s - failed setting baud rate, unsupported speed (default to 4800)",
285 __FUNCTION__);
286 n_baud_rate = 4800;
287 }
288 } else {
289 info("%s - please define your chiptype, using 4800bps default", __FUNCTION__);
290 n_baud_rate = 4800;
291 }
292 } else { /* baud rate not changing, keep the old */
293 n_baud_rate = priv->baud_rate;
294 }
295 dbg("%s - baud rate is being sent as %d", __FUNCTION__, n_baud_rate);
296
297
298 /*
299 * This algorithm accredited to Jiang Jay Zhang... thanks for all the help!
300 */
301 for (i = 0; i < 4; ++i) {
302 feature_buffer[i] = ( n_baud_rate >> (i*8) & 0xFF );
303 }
304
305 config = 0; // reset config byte
306 config |= data_bits; // assign data bits in 2 bit space ( max 3 )
307 /* 1 bit gap */
308 config |= (stop_bits << 3); // assign stop bits in 1 bit space
309 config |= (parity_enable << 4); // assign parity flag in 1 bit space
310 config |= (parity_type << 5); // assign parity type in 1 bit space
311 /* 1 bit gap */
312 config |= (reset << 7); // assign reset at end of byte, 1 bit space
313
314 feature_buffer[4] = config;
315
316 dbg("%s - device is being sent this feature report:", __FUNCTION__);
317 dbg("%s - %02X - %02X - %02X - %02X - %02X", __FUNCTION__, feature_buffer[0], feature_buffer[1],
318 feature_buffer[2], feature_buffer[3], feature_buffer[4]);
319
320 retval = usb_control_msg (port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
321 HID_REQ_SET_REPORT, USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
322 0x0300, 0, feature_buffer, 5, 500);
323
324 if (retval != 5)
325 err("%s - failed sending serial line settings - %d", __FUNCTION__, retval);
326 else {
327 spin_lock_irqsave(&priv->lock, flags);
328 priv->baud_rate = n_baud_rate;
329 priv->cbr_mask = baud_mask;
330 priv->current_config = config;
331 ++priv->cmd_count;
332 spin_unlock_irqrestore(&priv->lock, flags);
333 }
334 break;
335 case CYPRESS_GET_CONFIG:
336 dbg("%s - retreiving serial line settings", __FUNCTION__);
337 /* reset values in feature buffer */
338 memset(feature_buffer, 0, 5);
339
340 retval = usb_control_msg (port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0),
341 HID_REQ_GET_REPORT, USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
342 0x0300, 0, feature_buffer, 5, 500);
343 if (retval != 5) {
344 err("%s - failed to retreive serial line settings - %d", __FUNCTION__, retval);
345 return retval;
346 } else {
347 spin_lock_irqsave(&priv->lock, flags);
348 /* store the config in one byte, and later use bit masks to check values */
349 priv->current_config = feature_buffer[4];
350 /* reverse the process above to get the baud_mask value */
351 n_baud_rate = 0; // reset bits
352 for (i = 0; i < 4; ++i) {
353 n_baud_rate |= ( feature_buffer[i] << (i*8) );
354 }
355
356 priv->baud_rate = n_baud_rate;
357 if ( (priv->cbr_mask = rate_to_mask(n_baud_rate)) == 0x40)
358 dbg("%s - failed setting the baud mask (not defined)", __FUNCTION__);
359 ++priv->cmd_count;
360 spin_unlock_irqrestore(&priv->lock, flags);
361 }
362 break;
363 default:
364 err("%s - unsupported serial control command issued", __FUNCTION__);
365 }
366 return retval;
367} /* cypress_serial_control */
368
369
370/* given a baud mask, it will return speed on success */
371static int mask_to_rate (unsigned mask)
372{
373 int rate;
374
375 switch (mask) {
376 case B0: rate = 0; break;
377 case B300: rate = 300; break;
378 case B600: rate = 600; break;
379 case B1200: rate = 1200; break;
380 case B2400: rate = 2400; break;
381 case B4800: rate = 4800; break;
382 case B9600: rate = 9600; break;
383 case B19200: rate = 19200; break;
384 case B38400: rate = 38400; break;
385 case B57600: rate = 57600; break;
386 case B115200: rate = 115200; break;
387 default: rate = -1;
388 }
389
390 return rate;
391}
392
393
394static unsigned rate_to_mask (int rate)
395{
396 unsigned mask;
397
398 switch (rate) {
399 case 0: mask = B0; break;
400 case 300: mask = B300; break;
401 case 600: mask = B600; break;
402 case 1200: mask = B1200; break;
403 case 2400: mask = B2400; break;
404 case 4800: mask = B4800; break;
405 case 9600: mask = B9600; break;
406 case 19200: mask = B19200; break;
407 case 38400: mask = B38400; break;
408 case 57600: mask = B57600; break;
409 case 115200: mask = B115200; break;
410 default: mask = 0x40;
411 }
412
413 return mask;
414}
415/*****************************************************************************
416 * Cypress serial driver functions
417 *****************************************************************************/
418
419
420static int generic_startup (struct usb_serial *serial)
421{
422 struct cypress_private *priv;
423
424 dbg("%s - port %d", __FUNCTION__, serial->port[0]->number);
425
426 priv = kmalloc(sizeof (struct cypress_private), GFP_KERNEL);
427 if (!priv)
428 return -ENOMEM;
429
430 memset(priv, 0x00, sizeof (struct cypress_private));
431 spin_lock_init(&priv->lock);
432 priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE);
433 if (priv->buf == NULL) {
434 kfree(priv);
435 return -ENOMEM;
436 }
437 init_waitqueue_head(&priv->delta_msr_wait);
438
439 usb_reset_configuration (serial->dev);
440
441 priv->cmd_ctrl = 0;
442 priv->line_control = 0;
443 priv->termios_initialized = 0;
444 priv->calledfromopen = 0;
445 priv->rx_flags = 0;
446 usb_set_serial_port_data(serial->port[0], priv);
447
448 return (0);
449}
450
451
452static int cypress_earthmate_startup (struct usb_serial *serial)
453{
454 struct cypress_private *priv;
455
456 dbg("%s", __FUNCTION__);
457
458 if (generic_startup(serial)) {
459 dbg("%s - Failed setting up port %d", __FUNCTION__, serial->port[0]->number);
460 return 1;
461 }
462
463 priv = usb_get_serial_port_data(serial->port[0]);
464 priv->chiptype = CT_EARTHMATE;
465
466 return (0);
467} /* cypress_earthmate_startup */
468
469
470static int cypress_hidcom_startup (struct usb_serial *serial)
471{
472 struct cypress_private *priv;
473
474 dbg("%s", __FUNCTION__);
475
476 if (generic_startup(serial)) {
477 dbg("%s - Failed setting up port %d", __FUNCTION__, serial->port[0]->number);
478 return 1;
479 }
480
481 priv = usb_get_serial_port_data(serial->port[0]);
482 priv->chiptype = CT_CYPHIDCOM;
483
484 return (0);
485} /* cypress_hidcom_startup */
486
487
488static void cypress_shutdown (struct usb_serial *serial)
489{
490 struct cypress_private *priv;
491
492 dbg ("%s - port %d", __FUNCTION__, serial->port[0]->number);
493
494 /* all open ports are closed at this point */
495
496 priv = usb_get_serial_port_data(serial->port[0]);
497
498 if (priv) {
499 cypress_buf_free(priv->buf);
500 kfree(priv);
501 usb_set_serial_port_data(serial->port[0], NULL);
502 }
503}
504
505
506static int cypress_open (struct usb_serial_port *port, struct file *filp)
507{
508 struct cypress_private *priv = usb_get_serial_port_data(port);
509 struct usb_serial *serial = port->serial;
510 unsigned long flags;
511 int result = 0;
512
513 dbg("%s - port %d", __FUNCTION__, port->number);
514
515 /* clear halts before open */
516 usb_clear_halt(serial->dev, 0x00);
517 usb_clear_halt(serial->dev, 0x81);
518 usb_clear_halt(serial->dev, 0x02);
519
520 spin_lock_irqsave(&priv->lock, flags);
521 /* reset read/write statistics */
522 priv->bytes_in = 0;
523 priv->bytes_out = 0;
524 priv->cmd_count = 0;
525 priv->rx_flags = 0;
526 spin_unlock_irqrestore(&priv->lock, flags);
527
528 /* setting to zero could cause data loss */
529 port->tty->low_latency = 1;
530
531 /* raise both lines and set termios */
532 spin_lock_irqsave(&priv->lock, flags);
533 priv->line_control = CONTROL_DTR | CONTROL_RTS;
534 priv->calledfromopen = 1;
535 priv->cmd_ctrl = 1;
536 spin_unlock_irqrestore(&priv->lock, flags);
537 result = cypress_write(port, NULL, 0);
538
539 if (result) {
540 dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __FUNCTION__, result);
541 return result;
542 } else
543 dbg("%s - success setting the control lines", __FUNCTION__);
544
545 cypress_set_termios(port, &priv->tmp_termios);
546
547 /* setup the port and start reading from the device */
548 if(!port->interrupt_in_urb){
549 err("%s - interrupt_in_urb is empty!", __FUNCTION__);
550 return(-1);
551 }
552
553 usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
554 usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
555 port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length,
556 cypress_read_int_callback, port, port->interrupt_in_urb->interval);
557 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
558
559 if (result){
560 dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
561 }
562
563 return result;
564} /* cypress_open */
565
566
567static void cypress_close(struct usb_serial_port *port, struct file * filp)
568{
569 struct cypress_private *priv = usb_get_serial_port_data(port);
570 unsigned int c_cflag;
571 unsigned long flags;
572 int bps;
573 long timeout;
574 wait_queue_t wait;
575
576 dbg("%s - port %d", __FUNCTION__, port->number);
577
578 /* wait for data to drain from buffer */
579 spin_lock_irqsave(&priv->lock, flags);
580 timeout = CYPRESS_CLOSING_WAIT;
581 init_waitqueue_entry(&wait, current);
582 add_wait_queue(&port->tty->write_wait, &wait);
583 for (;;) {
584 set_current_state(TASK_INTERRUPTIBLE);
585 if (cypress_buf_data_avail(priv->buf) == 0
586 || timeout == 0 || signal_pending(current)
587 || !usb_get_intfdata(port->serial->interface))
588 break;
589 spin_unlock_irqrestore(&priv->lock, flags);
590 timeout = schedule_timeout(timeout);
591 spin_lock_irqsave(&priv->lock, flags);
592 }
593 set_current_state(TASK_RUNNING);
594 remove_wait_queue(&port->tty->write_wait, &wait);
595 /* clear out any remaining data in the buffer */
596 cypress_buf_clear(priv->buf);
597 spin_unlock_irqrestore(&priv->lock, flags);
598
599 /* wait for characters to drain from device */
600 bps = tty_get_baud_rate(port->tty);
601 if (bps > 1200)
602 timeout = max((HZ*2560)/bps,HZ/10);
603 else
604 timeout = 2*HZ;
605 set_current_state(TASK_INTERRUPTIBLE);
606 schedule_timeout(timeout);
607
608 dbg("%s - stopping urbs", __FUNCTION__);
609 usb_kill_urb (port->interrupt_in_urb);
610 usb_kill_urb (port->interrupt_out_urb);
611
612 if (port->tty) {
613 c_cflag = port->tty->termios->c_cflag;
614 if (c_cflag & HUPCL) {
615 /* drop dtr and rts */
616 priv = usb_get_serial_port_data(port);
617 spin_lock_irqsave(&priv->lock, flags);
618 priv->line_control = 0;
619 priv->cmd_ctrl = 1;
620 spin_unlock_irqrestore(&priv->lock, flags);
621 cypress_write(port, NULL, 0);
622 }
623 }
624
625 if (stats)
626 dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
627 priv->bytes_in, priv->bytes_out, priv->cmd_count);
628} /* cypress_close */
629
630
631static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, int count)
632{
633 struct cypress_private *priv = usb_get_serial_port_data(port);
634 unsigned long flags;
635
636 dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
637
638 /* line control commands, which need to be executed immediately,
639 are not put into the buffer for obvious reasons.
640 */
641 if (priv->cmd_ctrl) {
642 count = 0;
643 goto finish;
644 }
645
646 if (!count)
647 return count;
648
649 spin_lock_irqsave(&priv->lock, flags);
650 count = cypress_buf_put(priv->buf, buf, count);
651 spin_unlock_irqrestore(&priv->lock, flags);
652
653finish:
654 cypress_send(port);
655
656 return count;
657} /* cypress_write */
658
659
660static void cypress_send(struct usb_serial_port *port)
661{
662 int count = 0, result, offset, actual_size;
663 struct cypress_private *priv = usb_get_serial_port_data(port);
664 unsigned long flags;
665
666 dbg("%s - port %d", __FUNCTION__, port->number);
667 dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size);
668
669 spin_lock_irqsave(&priv->lock, flags);
670 if (priv->write_urb_in_use) {
671 dbg("%s - can't write, urb in use", __FUNCTION__);
672 spin_unlock_irqrestore(&priv->lock, flags);
673 return;
674 }
675 spin_unlock_irqrestore(&priv->lock, flags);
676
677 /* clear buffer */
678 memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size);
679
680 spin_lock_irqsave(&priv->lock, flags);
681 switch (port->interrupt_out_size) {
682 case 32:
683 // this is for the CY7C64013...
684 offset = 2;
685 port->interrupt_out_buffer[0] = priv->line_control;
686 break;
687 case 8:
688 // this is for the CY7C63743...
689 offset = 1;
690 port->interrupt_out_buffer[0] = priv->line_control;
691 break;
692 default:
693 dbg("%s - wrong packet size", __FUNCTION__);
694 spin_unlock_irqrestore(&priv->lock, flags);
695 return;
696 }
697
698 if (priv->line_control & CONTROL_RESET)
699 priv->line_control &= ~CONTROL_RESET;
700
701 if (priv->cmd_ctrl) {
702 priv->cmd_count++;
703 dbg("%s - line control command being issued", __FUNCTION__);
704 spin_unlock_irqrestore(&priv->lock, flags);
705 goto send;
706 } else
707 spin_unlock_irqrestore(&priv->lock, flags);
708
709 count = cypress_buf_get(priv->buf, &port->interrupt_out_buffer[offset],
710 port->interrupt_out_size-offset);
711
712 if (count == 0) {
713 return;
714 }
715
716 switch (port->interrupt_out_size) {
717 case 32:
718 port->interrupt_out_buffer[1] = count;
719 break;
720 case 8:
721 port->interrupt_out_buffer[0] |= count;
722 }
723
724 dbg("%s - count is %d", __FUNCTION__, count);
725
726send:
727 spin_lock_irqsave(&priv->lock, flags);
728 priv->write_urb_in_use = 1;
729 spin_unlock_irqrestore(&priv->lock, flags);
730
731 if (priv->cmd_ctrl)
732 actual_size = 1;
733 else
734 actual_size = count + (port->interrupt_out_size == 32 ? 2 : 1);
735
736 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size,
737 port->interrupt_out_urb->transfer_buffer);
738
739 port->interrupt_out_urb->transfer_buffer_length = actual_size;
740 port->interrupt_out_urb->dev = port->serial->dev;
741 result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC);
742 if (result) {
743 dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__,
744 result);
745 priv->write_urb_in_use = 0;
746 }
747
748 spin_lock_irqsave(&priv->lock, flags);
749 if (priv->cmd_ctrl) {
750 priv->cmd_ctrl = 0;
751 }
752 priv->bytes_out += count; /* do not count the line control and size bytes */
753 spin_unlock_irqrestore(&priv->lock, flags);
754
755 schedule_work(&port->work);
756} /* cypress_send */
757
758
759/* returns how much space is available in the soft buffer */
760static int cypress_write_room(struct usb_serial_port *port)
761{
762 struct cypress_private *priv = usb_get_serial_port_data(port);
763 int room = 0;
764 unsigned long flags;
765
766 dbg("%s - port %d", __FUNCTION__, port->number);
767
768 spin_lock_irqsave(&priv->lock, flags);
769 room = cypress_buf_space_avail(priv->buf);
770 spin_unlock_irqrestore(&priv->lock, flags);
771
772 dbg("%s - returns %d", __FUNCTION__, room);
773 return room;
774}
775
776
777static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
778{
779 struct cypress_private *priv = usb_get_serial_port_data(port);
780 __u8 status, control;
781 unsigned int result = 0;
782 unsigned long flags;
783
784 dbg("%s - port %d", __FUNCTION__, port->number);
785
786 spin_lock_irqsave(&priv->lock, flags);
787 control = priv->line_control;
788 status = priv->current_status;
789 spin_unlock_irqrestore(&priv->lock, flags);
790
791 result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)
792 | ((control & CONTROL_RTS) ? TIOCM_RTS : 0)
793 | ((status & UART_CTS) ? TIOCM_CTS : 0)
794 | ((status & UART_DSR) ? TIOCM_DSR : 0)
795 | ((status & UART_RI) ? TIOCM_RI : 0)
796 | ((status & UART_CD) ? TIOCM_CD : 0);
797
798 dbg("%s - result = %x", __FUNCTION__, result);
799
800 return result;
801}
802
803
804static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
805 unsigned int set, unsigned int clear)
806{
807 struct cypress_private *priv = usb_get_serial_port_data(port);
808 unsigned long flags;
809
810 dbg("%s - port %d", __FUNCTION__, port->number);
811
812 spin_lock_irqsave(&priv->lock, flags);
813 if (set & TIOCM_RTS)
814 priv->line_control |= CONTROL_RTS;
815 if (set & TIOCM_DTR)
816 priv->line_control |= CONTROL_DTR;
817 if (clear & TIOCM_RTS)
818 priv->line_control &= ~CONTROL_RTS;
819 if (clear & TIOCM_DTR)
820 priv->line_control &= ~CONTROL_DTR;
821 spin_unlock_irqrestore(&priv->lock, flags);
822
823 priv->cmd_ctrl = 1;
824 return cypress_write(port, NULL, 0);
825}
826
827
828static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
829{
830 struct cypress_private *priv = usb_get_serial_port_data(port);
831
832 dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
833
834 switch (cmd) {
835 case TIOCGSERIAL:
836 if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {
837 return -EFAULT;
838 }
839 return (0);
840 break;
841 case TIOCSSERIAL:
842 if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {
843 return -EFAULT;
844 }
845 /* here we need to call cypress_set_termios to invoke the new settings */
846 cypress_set_termios(port, &priv->tmp_termios);
847 return (0);
848 break;
849 /* these are called when setting baud rate from gpsd */
850 case TCGETS:
851 if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {
852 return -EFAULT;
853 }
854 return (0);
855 break;
856 case TCSETS:
857 if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {
858 return -EFAULT;
859 }
860 /* here we need to call cypress_set_termios to invoke the new settings */
861 cypress_set_termios(port, &priv->tmp_termios);
862 return (0);
863 break;
864 /* This code comes from drivers/char/serial.c and ftdi_sio.c */
865 case TIOCMIWAIT:
866 while (priv != NULL) {
867 interruptible_sleep_on(&priv->delta_msr_wait);
868 /* see if a signal did it */
869 if (signal_pending(current))
870 return -ERESTARTSYS;
871 else {
872 char diff = priv->diff_status;
873
874 if (diff == 0) {
875 return -EIO; /* no change => error */
876 }
877
878 /* consume all events */
879 priv->diff_status = 0;
880
881 /* return 0 if caller wanted to know about these bits */
882 if ( ((arg & TIOCM_RNG) && (diff & UART_RI)) ||
883 ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
884 ((arg & TIOCM_CD) && (diff & UART_CD)) ||
885 ((arg & TIOCM_CTS) && (diff & UART_CTS)) ) {
886 return 0;
887 }
888 /* otherwise caller can't care less about what happened,
889 * and so we continue to wait for more events.
890 */
891 }
892 }
893 return 0;
894 break;
895 default:
896 break;
897 }
898
899 dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __FUNCTION__, cmd);
900
901 return -ENOIOCTLCMD;
902} /* cypress_ioctl */
903
904
905static void cypress_set_termios (struct usb_serial_port *port, struct termios *old_termios)
906{
907 struct cypress_private *priv = usb_get_serial_port_data(port);
908 struct tty_struct *tty;
909 int data_bits, stop_bits, parity_type, parity_enable;
910 unsigned cflag, iflag, baud_mask;
911 unsigned long flags;
912 __u8 oldlines;
913 int linechange;
914
915 dbg("%s - port %d", __FUNCTION__, port->number);
916
917 tty = port->tty;
918 if ((!tty) || (!tty->termios)) {
919 dbg("%s - no tty structures", __FUNCTION__);
920 return;
921 }
922
923 spin_lock_irqsave(&priv->lock, flags);
924 if (!priv->termios_initialized) {
925 if (priv->chiptype == CT_EARTHMATE) {
926 *(tty->termios) = tty_std_termios;
927 tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL;
928 } else if (priv->chiptype == CT_CYPHIDCOM) {
929 *(tty->termios) = tty_std_termios;
930 tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
931 }
932 priv->termios_initialized = 1;
933 }
934 spin_unlock_irqrestore(&priv->lock, flags);
935
936 cflag = tty->termios->c_cflag;
937 iflag = tty->termios->c_iflag;
938
939 /* check if there are new settings */
940 if (old_termios) {
941 if ((cflag != old_termios->c_cflag) ||
942 (RELEVANT_IFLAG(iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
943 dbg("%s - attempting to set new termios settings", __FUNCTION__);
944 /* should make a copy of this in case something goes wrong in the function, we can restore it */
945 spin_lock_irqsave(&priv->lock, flags);
946 priv->tmp_termios = *(tty->termios);
947 spin_unlock_irqrestore(&priv->lock, flags);
948 } else {
949 dbg("%s - nothing to do, exiting", __FUNCTION__);
950 return;
951 }
952 } else
953 return;
954
955 /* set number of data bits, parity, stop bits */
956 /* when parity is disabled the parity type bit is ignored */
957
958 stop_bits = cflag & CSTOPB ? 1 : 0; /* 1 means 2 stop bits, 0 means 1 stop bit */
959
960 if (cflag & PARENB) {
961 parity_enable = 1;
962 parity_type = cflag & PARODD ? 1 : 0; /* 1 means odd parity, 0 means even parity */
963 } else
964 parity_enable = parity_type = 0;
965
966 if (cflag & CSIZE) {
967 switch (cflag & CSIZE) {
968 case CS5: data_bits = 0; break;
969 case CS6: data_bits = 1; break;
970 case CS7: data_bits = 2; break;
971 case CS8: data_bits = 3; break;
972 default: err("%s - CSIZE was set, but not CS5-CS8", __FUNCTION__); data_bits = 3;
973 }
974 } else
975 data_bits = 3;
976
977 spin_lock_irqsave(&priv->lock, flags);
978 oldlines = priv->line_control;
979 if ((cflag & CBAUD) == B0) {
980 /* drop dtr and rts */
981 dbg("%s - dropping the lines, baud rate 0bps", __FUNCTION__);
982 baud_mask = B0;
983 priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
984 } else {
985 baud_mask = (cflag & CBAUD);
986 switch(baud_mask) {
987 case B300: dbg("%s - setting baud 300bps", __FUNCTION__); break;
988 case B600: dbg("%s - setting baud 600bps", __FUNCTION__); break;
989 case B1200: dbg("%s - setting baud 1200bps", __FUNCTION__); break;
990 case B2400: dbg("%s - setting baud 2400bps", __FUNCTION__); break;
991 case B4800: dbg("%s - setting baud 4800bps", __FUNCTION__); break;
992 case B9600: dbg("%s - setting baud 9600bps", __FUNCTION__); break;
993 case B19200: dbg("%s - setting baud 19200bps", __FUNCTION__); break;
994 case B38400: dbg("%s - setting baud 38400bps", __FUNCTION__); break;
995 case B57600: dbg("%s - setting baud 57600bps", __FUNCTION__); break;
996 case B115200: dbg("%s - setting baud 115200bps", __FUNCTION__); break;
997 default: dbg("%s - unknown masked baud rate", __FUNCTION__);
998 }
999 priv->line_control |= CONTROL_DTR;
1000
1001 /* toggle CRTSCTS? - don't do this if being called from cypress_open */
1002 if (!priv->calledfromopen) {
1003 if (cflag & CRTSCTS)
1004 priv->line_control |= CONTROL_RTS;
1005 else
1006 priv->line_control &= ~CONTROL_RTS;
1007 }
1008 }
1009 spin_unlock_irqrestore(&priv->lock, flags);
1010
1011 dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, %d data_bits (+5)", __FUNCTION__,
1012 stop_bits, parity_enable, parity_type, data_bits);
1013
1014 cypress_serial_control(port, baud_mask, data_bits, stop_bits, parity_enable,
1015 parity_type, 0, CYPRESS_SET_CONFIG);
1016
1017 msleep(50); /* give some time between change and read (50ms) */
1018
1019 /* we perform a CYPRESS_GET_CONFIG so that the current settings are filled into the private structure
1020 * this should confirm that all is working if it returns what we just set */
1021 cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
1022
1023 /* Here we can define custom tty settings for devices
1024 *
1025 * the main tty termios flag base comes from empeg.c
1026 */
1027
1028 spin_lock_irqsave(&priv->lock, flags);
1029 if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) {
1030
1031 dbg("Using custom termios settings for a baud rate of 4800bps.");
1032 /* define custom termios settings for NMEA protocol */
1033
1034
1035 tty->termios->c_iflag /* input modes - */
1036 &= ~(IGNBRK /* disable ignore break */
1037 | BRKINT /* disable break causes interrupt */
1038 | PARMRK /* disable mark parity errors */
1039 | ISTRIP /* disable clear high bit of input characters */
1040 | INLCR /* disable translate NL to CR */
1041 | IGNCR /* disable ignore CR */
1042 | ICRNL /* disable translate CR to NL */
1043 | IXON); /* disable enable XON/XOFF flow control */
1044
1045 tty->termios->c_oflag /* output modes */
1046 &= ~OPOST; /* disable postprocess output characters */
1047
1048 tty->termios->c_lflag /* line discipline modes */
1049 &= ~(ECHO /* disable echo input characters */
1050 | ECHONL /* disable echo new line */
1051 | ICANON /* disable erase, kill, werase, and rprnt special characters */
1052 | ISIG /* disable interrupt, quit, and suspend special characters */
1053 | IEXTEN); /* disable non-POSIX special characters */
1054
1055 } else if (priv->chiptype == CT_CYPHIDCOM) {
1056
1057 // Software app handling it for device...
1058
1059 }
1060 linechange = (priv->line_control != oldlines);
1061 spin_unlock_irqrestore(&priv->lock, flags);
1062
1063 /* if necessary, set lines */
1064 if (!priv->calledfromopen && linechange) {
1065 priv->cmd_ctrl = 1;
1066 cypress_write(port, NULL, 0);
1067 }
1068
1069 if (priv->calledfromopen)
1070 priv->calledfromopen = 0;
1071
1072} /* cypress_set_termios */
1073
1074
1075/* returns amount of data still left in soft buffer */
1076static int cypress_chars_in_buffer(struct usb_serial_port *port)
1077{
1078 struct cypress_private *priv = usb_get_serial_port_data(port);
1079 int chars = 0;
1080 unsigned long flags;
1081
1082 dbg("%s - port %d", __FUNCTION__, port->number);
1083
1084 spin_lock_irqsave(&priv->lock, flags);
1085 chars = cypress_buf_data_avail(priv->buf);
1086 spin_unlock_irqrestore(&priv->lock, flags);
1087
1088 dbg("%s - returns %d", __FUNCTION__, chars);
1089 return chars;
1090}
1091
1092
1093static void cypress_throttle (struct usb_serial_port *port)
1094{
1095 struct cypress_private *priv = usb_get_serial_port_data(port);
1096 unsigned long flags;
1097
1098 dbg("%s - port %d", __FUNCTION__, port->number);
1099
1100 spin_lock_irqsave(&priv->lock, flags);
1101 priv->rx_flags = THROTTLED;
1102 spin_unlock_irqrestore(&priv->lock, flags);
1103}
1104
1105
1106static void cypress_unthrottle (struct usb_serial_port *port)
1107{
1108 struct cypress_private *priv = usb_get_serial_port_data(port);
1109 int actually_throttled, result;
1110 unsigned long flags;
1111
1112 dbg("%s - port %d", __FUNCTION__, port->number);
1113
1114 spin_lock_irqsave(&priv->lock, flags);
1115 actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
1116 priv->rx_flags = 0;
1117 spin_unlock_irqrestore(&priv->lock, flags);
1118
1119 if (actually_throttled) {
1120 port->interrupt_in_urb->dev = port->serial->dev;
1121
1122 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
1123 if (result)
1124 dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
1125 }
1126}
1127
1128
1129static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
1130{
1131 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
1132 struct cypress_private *priv = usb_get_serial_port_data(port);
1133 struct tty_struct *tty;
1134 unsigned char *data = urb->transfer_buffer;
1135 unsigned long flags;
1136 char tty_flag = TTY_NORMAL;
1137 int havedata = 0;
1138 int bytes = 0;
1139 int result;
1140 int i = 0;
1141
1142 dbg("%s - port %d", __FUNCTION__, port->number);
1143
1144 if (urb->status) {
1145 dbg("%s - nonzero read status received: %d", __FUNCTION__, urb->status);
1146 return;
1147 }
1148
1149 spin_lock_irqsave(&priv->lock, flags);
1150 if (priv->rx_flags & THROTTLED) {
1151 dbg("%s - now throttling", __FUNCTION__);
1152 priv->rx_flags |= ACTUALLY_THROTTLED;
1153 spin_unlock_irqrestore(&priv->lock, flags);
1154 return;
1155 }
1156 spin_unlock_irqrestore(&priv->lock, flags);
1157
1158 tty = port->tty;
1159 if (!tty) {
1160 dbg("%s - bad tty pointer - exiting", __FUNCTION__);
1161 return;
1162 }
1163
1164 spin_lock_irqsave(&priv->lock, flags);
1165 switch(urb->actual_length) {
1166 case 32:
1167 // This is for the CY7C64013...
1168 priv->current_status = data[0] & 0xF8;
1169 bytes = data[1]+2;
1170 i=2;
1171 if (bytes > 2)
1172 havedata = 1;
1173 break;
1174 case 8:
1175 // This is for the CY7C63743...
1176 priv->current_status = data[0] & 0xF8;
1177 bytes = (data[0] & 0x07)+1;
1178 i=1;
1179 if (bytes > 1)
1180 havedata = 1;
1181 break;
1182 default:
1183 dbg("%s - wrong packet size - received %d bytes", __FUNCTION__, urb->actual_length);
1184 spin_unlock_irqrestore(&priv->lock, flags);
1185 goto continue_read;
1186 }
1187 spin_unlock_irqrestore(&priv->lock, flags);
1188
1189 usb_serial_debug_data (debug, &port->dev, __FUNCTION__, urb->actual_length, data);
1190
1191 spin_lock_irqsave(&priv->lock, flags);
1192 /* check to see if status has changed */
1193 if (priv != NULL) {
1194 if (priv->current_status != priv->prev_status) {
1195 priv->diff_status |= priv->current_status ^ priv->prev_status;
1196 wake_up_interruptible(&priv->delta_msr_wait);
1197 priv->prev_status = priv->current_status;
1198 }
1199 }
1200 spin_unlock_irqrestore(&priv->lock, flags);
1201
1202 /* hangup, as defined in acm.c... this might be a bad place for it though */
1203 if (tty && !(tty->termios->c_cflag & CLOCAL) && !(priv->current_status & UART_CD)) {
1204 dbg("%s - calling hangup", __FUNCTION__);
1205 tty_hangup(tty);
1206 goto continue_read;
1207 }
1208
1209 /* There is one error bit... I'm assuming it is a parity error indicator
1210 * as the generic firmware will set this bit to 1 if a parity error occurs.
1211 * I can not find reference to any other error events.
1212 *
1213 */
1214 spin_lock_irqsave(&priv->lock, flags);
1215 if (priv->current_status & CYP_ERROR) {
1216 spin_unlock_irqrestore(&priv->lock, flags);
1217 tty_flag = TTY_PARITY;
1218 dbg("%s - Parity Error detected", __FUNCTION__);
1219 } else
1220 spin_unlock_irqrestore(&priv->lock, flags);
1221
1222 /* process read if there is data other than line status */
1223 if (tty && (bytes > i)) {
1224 for (; i < bytes ; ++i) {
1225 dbg("pushing byte number %d - %d - %c",i,data[i],data[i]);
1226 if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
1227 tty_flip_buffer_push(tty);
1228 }
1229 tty_insert_flip_char(tty, data[i], tty_flag);
1230 }
1231 tty_flip_buffer_push(port->tty);
1232 }
1233
1234 spin_lock_irqsave(&priv->lock, flags);
1235 priv->bytes_in += bytes; /* control and status byte(s) are also counted */
1236 spin_unlock_irqrestore(&priv->lock, flags);
1237
1238continue_read:
1239
1240 /* Continue trying to always read... unless the port has closed. */
1241
1242 if (port->open_count > 0) {
1243 usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
1244 usb_rcvintpipe(port->serial->dev, port->interrupt_in_endpointAddress),
1245 port->interrupt_in_urb->transfer_buffer,
1246 port->interrupt_in_urb->transfer_buffer_length,
1247 cypress_read_int_callback, port,
1248 port->interrupt_in_urb->interval);
1249 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
1250 if (result)
1251 dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
1252 }
1253
1254 return;
1255} /* cypress_read_int_callback */
1256
1257
1258static void cypress_write_int_callback(struct urb *urb, struct pt_regs *regs)
1259{
1260 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
1261 struct cypress_private *priv = usb_get_serial_port_data(port);
1262 int result;
1263
1264 dbg("%s - port %d", __FUNCTION__, port->number);
1265
1266 switch (urb->status) {
1267 case 0:
1268 /* success */
1269 break;
1270 case -ECONNRESET:
1271 case -ENOENT:
1272 case -ESHUTDOWN:
1273 /* this urb is terminated, clean up */
1274 dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
1275 priv->write_urb_in_use = 0;
1276 return;
1277 default:
1278 /* error in the urb, so we have to resubmit it */
1279 dbg("%s - Overflow in write", __FUNCTION__);
1280 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
1281 port->interrupt_out_urb->transfer_buffer_length = 1;
1282 port->interrupt_out_urb->dev = port->serial->dev;
1283 result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
1284 if (result)
1285 dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
1286 __FUNCTION__, result);
1287 else
1288 return;
1289 }
1290
1291 priv->write_urb_in_use = 0;
1292
1293 /* send any buffered data */
1294 cypress_send(port);
1295}
1296
1297
1298/*****************************************************************************
1299 * Write buffer functions - buffering code from pl2303 used
1300 *****************************************************************************/
1301
1302/*
1303 * cypress_buf_alloc
1304 *
1305 * Allocate a circular buffer and all associated memory.
1306 */
1307
1308static struct cypress_buf *cypress_buf_alloc(unsigned int size)
1309{
1310
1311 struct cypress_buf *cb;
1312
1313
1314 if (size == 0)
1315 return NULL;
1316
1317 cb = (struct cypress_buf *)kmalloc(sizeof(struct cypress_buf), GFP_KERNEL);
1318 if (cb == NULL)
1319 return NULL;
1320
1321 cb->buf_buf = kmalloc(size, GFP_KERNEL);
1322 if (cb->buf_buf == NULL) {
1323 kfree(cb);
1324 return NULL;
1325 }
1326
1327 cb->buf_size = size;
1328 cb->buf_get = cb->buf_put = cb->buf_buf;
1329
1330 return cb;
1331
1332}
1333
1334
1335/*
1336 * cypress_buf_free
1337 *
1338 * Free the buffer and all associated memory.
1339 */
1340
1341static void cypress_buf_free(struct cypress_buf *cb)
1342{
1343 if (cb != NULL) {
1344 if (cb->buf_buf != NULL)
1345 kfree(cb->buf_buf);
1346 kfree(cb);
1347 }
1348}
1349
1350
1351/*
1352 * cypress_buf_clear
1353 *
1354 * Clear out all data in the circular buffer.
1355 */
1356
1357static void cypress_buf_clear(struct cypress_buf *cb)
1358{
1359 if (cb != NULL)
1360 cb->buf_get = cb->buf_put;
1361 /* equivalent to a get of all data available */
1362}
1363
1364
1365/*
1366 * cypress_buf_data_avail
1367 *
1368 * Return the number of bytes of data available in the circular
1369 * buffer.
1370 */
1371
1372static unsigned int cypress_buf_data_avail(struct cypress_buf *cb)
1373{
1374 if (cb != NULL)
1375 return ((cb->buf_size + cb->buf_put - cb->buf_get) % cb->buf_size);
1376 else
1377 return 0;
1378}
1379
1380
1381/*
1382 * cypress_buf_space_avail
1383 *
1384 * Return the number of bytes of space available in the circular
1385 * buffer.
1386 */
1387
1388static unsigned int cypress_buf_space_avail(struct cypress_buf *cb)
1389{
1390 if (cb != NULL)
1391 return ((cb->buf_size + cb->buf_get - cb->buf_put - 1) % cb->buf_size);
1392 else
1393 return 0;
1394}
1395
1396
1397/*
1398 * cypress_buf_put
1399 *
1400 * Copy data data from a user buffer and put it into the circular buffer.
1401 * Restrict to the amount of space available.
1402 *
1403 * Return the number of bytes copied.
1404 */
1405
1406static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf,
1407 unsigned int count)
1408{
1409
1410 unsigned int len;
1411
1412
1413 if (cb == NULL)
1414 return 0;
1415
1416 len = cypress_buf_space_avail(cb);
1417 if (count > len)
1418 count = len;
1419
1420 if (count == 0)
1421 return 0;
1422
1423 len = cb->buf_buf + cb->buf_size - cb->buf_put;
1424 if (count > len) {
1425 memcpy(cb->buf_put, buf, len);
1426 memcpy(cb->buf_buf, buf+len, count - len);
1427 cb->buf_put = cb->buf_buf + count - len;
1428 } else {
1429 memcpy(cb->buf_put, buf, count);
1430 if (count < len)
1431 cb->buf_put += count;
1432 else /* count == len */
1433 cb->buf_put = cb->buf_buf;
1434 }
1435
1436 return count;
1437
1438}
1439
1440
1441/*
1442 * cypress_buf_get
1443 *
1444 * Get data from the circular buffer and copy to the given buffer.
1445 * Restrict to the amount of data available.
1446 *
1447 * Return the number of bytes copied.
1448 */
1449
1450static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf,
1451 unsigned int count)
1452{
1453
1454 unsigned int len;
1455
1456
1457 if (cb == NULL)
1458 return 0;
1459
1460 len = cypress_buf_data_avail(cb);
1461 if (count > len)
1462 count = len;
1463
1464 if (count == 0)
1465 return 0;
1466
1467 len = cb->buf_buf + cb->buf_size - cb->buf_get;
1468 if (count > len) {
1469 memcpy(buf, cb->buf_get, len);
1470 memcpy(buf+len, cb->buf_buf, count - len);
1471 cb->buf_get = cb->buf_buf + count - len;
1472 } else {
1473 memcpy(buf, cb->buf_get, count);
1474 if (count < len)
1475 cb->buf_get += count;
1476 else /* count == len */
1477 cb->buf_get = cb->buf_buf;
1478 }
1479
1480 return count;
1481
1482}
1483
1484/*****************************************************************************
1485 * Module functions
1486 *****************************************************************************/
1487
1488static int __init cypress_init(void)
1489{
1490 int retval;
1491
1492 dbg("%s", __FUNCTION__);
1493
1494 retval = usb_serial_register(&cypress_earthmate_device);
1495 if (retval)
1496 goto failed_em_register;
1497 retval = usb_serial_register(&cypress_hidcom_device);
1498 if (retval)
1499 goto failed_hidcom_register;
1500 retval = usb_register(&cypress_driver);
1501 if (retval)
1502 goto failed_usb_register;
1503
1504 info(DRIVER_DESC " " DRIVER_VERSION);
1505 return 0;
1506failed_usb_register:
1507 usb_deregister(&cypress_driver);
1508failed_hidcom_register:
1509 usb_serial_deregister(&cypress_hidcom_device);
1510failed_em_register:
1511 usb_serial_deregister(&cypress_earthmate_device);
1512
1513 return retval;
1514}
1515
1516
1517static void __exit cypress_exit (void)
1518{
1519 dbg("%s", __FUNCTION__);
1520
1521 usb_deregister (&cypress_driver);
1522 usb_serial_deregister (&cypress_earthmate_device);
1523 usb_serial_deregister (&cypress_hidcom_device);
1524}
1525
1526
1527module_init(cypress_init);
1528module_exit(cypress_exit);
1529
1530MODULE_AUTHOR( DRIVER_AUTHOR );
1531MODULE_DESCRIPTION( DRIVER_DESC );
1532MODULE_VERSION( DRIVER_VERSION );
1533MODULE_LICENSE("GPL");
1534
1535module_param(debug, bool, S_IRUGO | S_IWUSR);
1536MODULE_PARM_DESC(debug, "Debug enabled or not");
1537module_param(stats, bool, S_IRUGO | S_IWUSR);
1538MODULE_PARM_DESC(stats, "Enable statistics or not");