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