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