]> Pileus Git - ~andy/linux/blob - drivers/usb/serial/cypress_m8.c
Merge tag 'device-for-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg...
[~andy/linux] / 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
15  * driver
16  *
17  * See http://geocities.com/i0xox0i for information on this driver and the
18  * earthmate usb device.
19  */
20
21 /* Thanks to Neil Whelchel for writing the first cypress m8 implementation
22    for linux. */
23 /* Thanks to cypress for providing references for the hid reports. */
24 /* Thanks to Jiang Zhang for providing links and for general help. */
25 /* Code originates and was built up from ftdi_sio, belkin, pl2303 and others.*/
26
27
28 #include <linux/kernel.h>
29 #include <linux/errno.h>
30 #include <linux/init.h>
31 #include <linux/slab.h>
32 #include <linux/tty.h>
33 #include <linux/tty_driver.h>
34 #include <linux/tty_flip.h>
35 #include <linux/module.h>
36 #include <linux/moduleparam.h>
37 #include <linux/spinlock.h>
38 #include <linux/usb.h>
39 #include <linux/usb/serial.h>
40 #include <linux/serial.h>
41 #include <linux/kfifo.h>
42 #include <linux/delay.h>
43 #include <linux/uaccess.h>
44 #include <asm/unaligned.h>
45
46 #include "cypress_m8.h"
47
48
49 static bool debug;
50 static bool stats;
51 static int interval;
52 static bool unstable_bauds;
53
54 /*
55  * Version Information
56  */
57 #define DRIVER_VERSION "v1.10"
58 #define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>"
59 #define DRIVER_DESC "Cypress USB to Serial Driver"
60
61 /* write buffer size defines */
62 #define CYPRESS_BUF_SIZE        1024
63
64 static const struct usb_device_id id_table_earthmate[] = {
65         { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
66         { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
67         { }                                             /* Terminating entry */
68 };
69
70 static const struct usb_device_id id_table_cyphidcomrs232[] = {
71         { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
72         { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
73         { }                                             /* Terminating entry */
74 };
75
76 static const struct usb_device_id id_table_nokiaca42v2[] = {
77         { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
78         { }                                             /* Terminating entry */
79 };
80
81 static const struct usb_device_id id_table_combined[] = {
82         { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
83         { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
84         { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
85         { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
86         { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
87         { }                                             /* Terminating entry */
88 };
89
90 MODULE_DEVICE_TABLE(usb, id_table_combined);
91
92 static struct usb_driver cypress_driver = {
93         .name =         "cypress",
94         .probe =        usb_serial_probe,
95         .disconnect =   usb_serial_disconnect,
96         .id_table =     id_table_combined,
97 };
98
99 enum packet_format {
100         packet_format_1,  /* b0:status, b1:payload count */
101         packet_format_2   /* b0[7:3]:status, b0[2:0]:payload count */
102 };
103
104 struct cypress_private {
105         spinlock_t lock;                   /* private lock */
106         int chiptype;                      /* identifier of device, for quirks/etc */
107         int bytes_in;                      /* used for statistics */
108         int bytes_out;                     /* used for statistics */
109         int cmd_count;                     /* used for statistics */
110         int cmd_ctrl;                      /* always set this to 1 before issuing a command */
111         struct kfifo write_fifo;           /* write fifo */
112         int write_urb_in_use;              /* write urb in use indicator */
113         int write_urb_interval;            /* interval to use for write urb */
114         int read_urb_interval;             /* interval to use for read urb */
115         int comm_is_ok;                    /* true if communication is (still) ok */
116         int termios_initialized;
117         __u8 line_control;                 /* holds dtr / rts value */
118         __u8 current_status;               /* received from last read - info on dsr,cts,cd,ri,etc */
119         __u8 current_config;               /* stores the current configuration byte */
120         __u8 rx_flags;                     /* throttling - used from whiteheat/ftdi_sio */
121         enum packet_format pkt_fmt;        /* format to use for packet send / receive */
122         int get_cfg_unsafe;                /* If true, the CYPRESS_GET_CONFIG is unsafe */
123         int baud_rate;                     /* stores current baud rate in
124                                               integer form */
125         int isthrottled;                   /* if throttled, discard reads */
126         wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */
127         char prev_status, diff_status;     /* used for TIOCMIWAIT */
128         /* we pass a pointer to this as the argument sent to
129            cypress_set_termios old_termios */
130         struct ktermios tmp_termios;       /* stores the old termios settings */
131 };
132
133 /* function prototypes for the Cypress USB to serial device */
134 static int  cypress_earthmate_startup(struct usb_serial *serial);
135 static int  cypress_hidcom_startup(struct usb_serial *serial);
136 static int  cypress_ca42v2_startup(struct usb_serial *serial);
137 static void cypress_release(struct usb_serial *serial);
138 static int  cypress_open(struct tty_struct *tty, struct usb_serial_port *port);
139 static void cypress_close(struct usb_serial_port *port);
140 static void cypress_dtr_rts(struct usb_serial_port *port, int on);
141 static int  cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
142                         const unsigned char *buf, int count);
143 static void cypress_send(struct usb_serial_port *port);
144 static int  cypress_write_room(struct tty_struct *tty);
145 static int  cypress_ioctl(struct tty_struct *tty,
146                         unsigned int cmd, unsigned long arg);
147 static void cypress_set_termios(struct tty_struct *tty,
148                         struct usb_serial_port *port, struct ktermios *old);
149 static int  cypress_tiocmget(struct tty_struct *tty);
150 static int  cypress_tiocmset(struct tty_struct *tty,
151                         unsigned int set, unsigned int clear);
152 static int  cypress_chars_in_buffer(struct tty_struct *tty);
153 static void cypress_throttle(struct tty_struct *tty);
154 static void cypress_unthrottle(struct tty_struct *tty);
155 static void cypress_set_dead(struct usb_serial_port *port);
156 static void cypress_read_int_callback(struct urb *urb);
157 static void cypress_write_int_callback(struct urb *urb);
158
159 static struct usb_serial_driver cypress_earthmate_device = {
160         .driver = {
161                 .owner =                THIS_MODULE,
162                 .name =                 "earthmate",
163         },
164         .description =                  "DeLorme Earthmate USB",
165         .id_table =                     id_table_earthmate,
166         .num_ports =                    1,
167         .attach =                       cypress_earthmate_startup,
168         .release =                      cypress_release,
169         .open =                         cypress_open,
170         .close =                        cypress_close,
171         .dtr_rts =                      cypress_dtr_rts,
172         .write =                        cypress_write,
173         .write_room =                   cypress_write_room,
174         .ioctl =                        cypress_ioctl,
175         .set_termios =                  cypress_set_termios,
176         .tiocmget =                     cypress_tiocmget,
177         .tiocmset =                     cypress_tiocmset,
178         .chars_in_buffer =              cypress_chars_in_buffer,
179         .throttle =                     cypress_throttle,
180         .unthrottle =                   cypress_unthrottle,
181         .read_int_callback =            cypress_read_int_callback,
182         .write_int_callback =           cypress_write_int_callback,
183 };
184
185 static struct usb_serial_driver cypress_hidcom_device = {
186         .driver = {
187                 .owner =                THIS_MODULE,
188                 .name =                 "cyphidcom",
189         },
190         .description =                  "HID->COM RS232 Adapter",
191         .id_table =                     id_table_cyphidcomrs232,
192         .num_ports =                    1,
193         .attach =                       cypress_hidcom_startup,
194         .release =                      cypress_release,
195         .open =                         cypress_open,
196         .close =                        cypress_close,
197         .dtr_rts =                      cypress_dtr_rts,
198         .write =                        cypress_write,
199         .write_room =                   cypress_write_room,
200         .ioctl =                        cypress_ioctl,
201         .set_termios =                  cypress_set_termios,
202         .tiocmget =                     cypress_tiocmget,
203         .tiocmset =                     cypress_tiocmset,
204         .chars_in_buffer =              cypress_chars_in_buffer,
205         .throttle =                     cypress_throttle,
206         .unthrottle =                   cypress_unthrottle,
207         .read_int_callback =            cypress_read_int_callback,
208         .write_int_callback =           cypress_write_int_callback,
209 };
210
211 static struct usb_serial_driver cypress_ca42v2_device = {
212         .driver = {
213                 .owner =                THIS_MODULE,
214                 .name =                 "nokiaca42v2",
215         },
216         .description =                  "Nokia CA-42 V2 Adapter",
217         .id_table =                     id_table_nokiaca42v2,
218         .num_ports =                    1,
219         .attach =                       cypress_ca42v2_startup,
220         .release =                      cypress_release,
221         .open =                         cypress_open,
222         .close =                        cypress_close,
223         .dtr_rts =                      cypress_dtr_rts,
224         .write =                        cypress_write,
225         .write_room =                   cypress_write_room,
226         .ioctl =                        cypress_ioctl,
227         .set_termios =                  cypress_set_termios,
228         .tiocmget =                     cypress_tiocmget,
229         .tiocmset =                     cypress_tiocmset,
230         .chars_in_buffer =              cypress_chars_in_buffer,
231         .throttle =                     cypress_throttle,
232         .unthrottle =                   cypress_unthrottle,
233         .read_int_callback =            cypress_read_int_callback,
234         .write_int_callback =           cypress_write_int_callback,
235 };
236
237 static struct usb_serial_driver * const serial_drivers[] = {
238         &cypress_earthmate_device, &cypress_hidcom_device,
239         &cypress_ca42v2_device, NULL
240 };
241
242 /*****************************************************************************
243  * Cypress serial helper functions
244  *****************************************************************************/
245
246
247 static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
248 {
249         struct cypress_private *priv;
250         priv = usb_get_serial_port_data(port);
251
252         if (unstable_bauds)
253                 return new_rate;
254
255         /*
256          * The general purpose firmware for the Cypress M8 allows for
257          * a maximum speed of 57600bps (I have no idea whether DeLorme
258          * chose to use the general purpose firmware or not), if you
259          * need to modify this speed setting for your own project
260          * please add your own chiptype and modify the code likewise.
261          * The Cypress HID->COM device will work successfully up to
262          * 115200bps (but the actual throughput is around 3kBps).
263          */
264         if (port->serial->dev->speed == USB_SPEED_LOW) {
265                 /*
266                  * Mike Isely <isely@pobox.com> 2-Feb-2008: The
267                  * Cypress app note that describes this mechanism
268                  * states the the low-speed part can't handle more
269                  * than 800 bytes/sec, in which case 4800 baud is the
270                  * safest speed for a part like that.
271                  */
272                 if (new_rate > 4800) {
273                         dbg("%s - failed setting baud rate, device incapable "
274                             "speed %d", __func__, new_rate);
275                         return -1;
276                 }
277         }
278         switch (priv->chiptype) {
279         case CT_EARTHMATE:
280                 if (new_rate <= 600) {
281                         /* 300 and 600 baud rates are supported under
282                          * the generic firmware, but are not used with
283                          * NMEA and SiRF protocols */
284                         dbg("%s - failed setting baud rate, unsupported speed "
285                             "of %d on Earthmate GPS", __func__, new_rate);
286                         return -1;
287                 }
288                 break;
289         default:
290                 break;
291         }
292         return new_rate;
293 }
294
295
296 /* This function can either set or retrieve the current serial line settings */
297 static int cypress_serial_control(struct tty_struct *tty,
298         struct usb_serial_port *port, speed_t baud_rate, int data_bits,
299         int stop_bits, int parity_enable, int parity_type, int reset,
300         int cypress_request_type)
301 {
302         int new_baudrate = 0, retval = 0, tries = 0;
303         struct cypress_private *priv;
304         u8 *feature_buffer;
305         const unsigned int feature_len = 5;
306         unsigned long flags;
307
308         dbg("%s", __func__);
309
310         priv = usb_get_serial_port_data(port);
311
312         if (!priv->comm_is_ok)
313                 return -ENODEV;
314
315         feature_buffer = kcalloc(feature_len, sizeof(u8), GFP_KERNEL);
316         if (!feature_buffer)
317                 return -ENOMEM;
318
319         switch (cypress_request_type) {
320         case CYPRESS_SET_CONFIG:
321                 /* 0 means 'Hang up' so doesn't change the true bit rate */
322                 new_baudrate = priv->baud_rate;
323                 if (baud_rate && baud_rate != priv->baud_rate) {
324                         dbg("%s - baud rate is changing", __func__);
325                         retval = analyze_baud_rate(port, baud_rate);
326                         if (retval >= 0) {
327                                 new_baudrate = retval;
328                                 dbg("%s - New baud rate set to %d",
329                                     __func__, new_baudrate);
330                         }
331                 }
332                 dbg("%s - baud rate is being sent as %d",
333                                         __func__, new_baudrate);
334
335                 /* fill the feature_buffer with new configuration */
336                 put_unaligned_le32(new_baudrate, feature_buffer);
337                 feature_buffer[4] |= data_bits;   /* assign data bits in 2 bit space ( max 3 ) */
338                 /* 1 bit gap */
339                 feature_buffer[4] |= (stop_bits << 3);   /* assign stop bits in 1 bit space */
340                 feature_buffer[4] |= (parity_enable << 4);   /* assign parity flag in 1 bit space */
341                 feature_buffer[4] |= (parity_type << 5);   /* assign parity type in 1 bit space */
342                 /* 1 bit gap */
343                 feature_buffer[4] |= (reset << 7);   /* assign reset at end of byte, 1 bit space */
344
345                 dbg("%s - device is being sent this feature report:",
346                                                                 __func__);
347                 dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__,
348                         feature_buffer[0], feature_buffer[1],
349                         feature_buffer[2], feature_buffer[3],
350                         feature_buffer[4]);
351
352                 do {
353                         retval = usb_control_msg(port->serial->dev,
354                                         usb_sndctrlpipe(port->serial->dev, 0),
355                                         HID_REQ_SET_REPORT,
356                                         USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
357                                         0x0300, 0, feature_buffer,
358                                         feature_len, 500);
359
360                         if (tries++ >= 3)
361                                 break;
362
363                 } while (retval != feature_len &&
364                          retval != -ENODEV);
365
366                 if (retval != feature_len) {
367                         dev_err(&port->dev, "%s - failed sending serial "
368                                 "line settings - %d\n", __func__, retval);
369                         cypress_set_dead(port);
370                 } else {
371                         spin_lock_irqsave(&priv->lock, flags);
372                         priv->baud_rate = new_baudrate;
373                         priv->current_config = feature_buffer[4];
374                         spin_unlock_irqrestore(&priv->lock, flags);
375                         /* If we asked for a speed change encode it */
376                         if (baud_rate)
377                                 tty_encode_baud_rate(tty,
378                                         new_baudrate, new_baudrate);
379                 }
380         break;
381         case CYPRESS_GET_CONFIG:
382                 if (priv->get_cfg_unsafe) {
383                         /* Not implemented for this device,
384                            and if we try to do it we're likely
385                            to crash the hardware. */
386                         retval = -ENOTTY;
387                         goto out;
388                 }
389                 dbg("%s - retreiving serial line settings", __func__);
390                 do {
391                         retval = usb_control_msg(port->serial->dev,
392                                         usb_rcvctrlpipe(port->serial->dev, 0),
393                                         HID_REQ_GET_REPORT,
394                                         USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
395                                         0x0300, 0, feature_buffer,
396                                         feature_len, 500);
397
398                         if (tries++ >= 3)
399                                 break;
400                 } while (retval != feature_len
401                                                 && retval != -ENODEV);
402
403                 if (retval != feature_len) {
404                         dev_err(&port->dev, "%s - failed to retrieve serial "
405                                 "line settings - %d\n", __func__, retval);
406                         cypress_set_dead(port);
407                         goto out;
408                 } else {
409                         spin_lock_irqsave(&priv->lock, flags);
410                         /* store the config in one byte, and later
411                            use bit masks to check values */
412                         priv->current_config = feature_buffer[4];
413                         priv->baud_rate = get_unaligned_le32(feature_buffer);
414                         spin_unlock_irqrestore(&priv->lock, flags);
415                 }
416         }
417         spin_lock_irqsave(&priv->lock, flags);
418         ++priv->cmd_count;
419         spin_unlock_irqrestore(&priv->lock, flags);
420 out:
421         kfree(feature_buffer);
422         return retval;
423 } /* cypress_serial_control */
424
425
426 static void cypress_set_dead(struct usb_serial_port *port)
427 {
428         struct cypress_private *priv = usb_get_serial_port_data(port);
429         unsigned long flags;
430
431         spin_lock_irqsave(&priv->lock, flags);
432         if (!priv->comm_is_ok) {
433                 spin_unlock_irqrestore(&priv->lock, flags);
434                 return;
435         }
436         priv->comm_is_ok = 0;
437         spin_unlock_irqrestore(&priv->lock, flags);
438
439         dev_err(&port->dev, "cypress_m8 suspending failing port %d - "
440                 "interval might be too short\n", port->number);
441 }
442
443
444 /*****************************************************************************
445  * Cypress serial driver functions
446  *****************************************************************************/
447
448
449 static int generic_startup(struct usb_serial *serial)
450 {
451         struct cypress_private *priv;
452         struct usb_serial_port *port = serial->port[0];
453
454         dbg("%s - port %d", __func__, port->number);
455
456         priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
457         if (!priv)
458                 return -ENOMEM;
459
460         priv->comm_is_ok = !0;
461         spin_lock_init(&priv->lock);
462         if (kfifo_alloc(&priv->write_fifo, CYPRESS_BUF_SIZE, GFP_KERNEL)) {
463                 kfree(priv);
464                 return -ENOMEM;
465         }
466         init_waitqueue_head(&priv->delta_msr_wait);
467
468         usb_reset_configuration(serial->dev);
469
470         priv->cmd_ctrl = 0;
471         priv->line_control = 0;
472         priv->termios_initialized = 0;
473         priv->rx_flags = 0;
474         /* Default packet format setting is determined by packet size.
475            Anything with a size larger then 9 must have a separate
476            count field since the 3 bit count field is otherwise too
477            small.  Otherwise we can use the slightly more compact
478            format.  This is in accordance with the cypress_m8 serial
479            converter app note. */
480         if (port->interrupt_out_size > 9)
481                 priv->pkt_fmt = packet_format_1;
482         else
483                 priv->pkt_fmt = packet_format_2;
484
485         if (interval > 0) {
486                 priv->write_urb_interval = interval;
487                 priv->read_urb_interval = interval;
488                 dbg("%s - port %d read & write intervals forced to %d",
489                     __func__, port->number, interval);
490         } else {
491                 priv->write_urb_interval = port->interrupt_out_urb->interval;
492                 priv->read_urb_interval = port->interrupt_in_urb->interval;
493                 dbg("%s - port %d intervals: read=%d write=%d",
494                     __func__, port->number,
495                     priv->read_urb_interval, priv->write_urb_interval);
496         }
497         usb_set_serial_port_data(port, priv);
498
499         return 0;
500 }
501
502
503 static int cypress_earthmate_startup(struct usb_serial *serial)
504 {
505         struct cypress_private *priv;
506         struct usb_serial_port *port = serial->port[0];
507
508         dbg("%s", __func__);
509
510         if (generic_startup(serial)) {
511                 dbg("%s - Failed setting up port %d", __func__,
512                                 port->number);
513                 return 1;
514         }
515
516         priv = usb_get_serial_port_data(port);
517         priv->chiptype = CT_EARTHMATE;
518         /* All Earthmate devices use the separated-count packet
519            format!  Idiotic. */
520         priv->pkt_fmt = packet_format_1;
521         if (serial->dev->descriptor.idProduct !=
522                                 cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) {
523                 /* The old original USB Earthmate seemed able to
524                    handle GET_CONFIG requests; everything they've
525                    produced since that time crashes if this command is
526                    attempted :-( */
527                 dbg("%s - Marking this device as unsafe for GET_CONFIG "
528                     "commands", __func__);
529                 priv->get_cfg_unsafe = !0;
530         }
531
532         return 0;
533 } /* cypress_earthmate_startup */
534
535
536 static int cypress_hidcom_startup(struct usb_serial *serial)
537 {
538         struct cypress_private *priv;
539
540         dbg("%s", __func__);
541
542         if (generic_startup(serial)) {
543                 dbg("%s - Failed setting up port %d", __func__,
544                                 serial->port[0]->number);
545                 return 1;
546         }
547
548         priv = usb_get_serial_port_data(serial->port[0]);
549         priv->chiptype = CT_CYPHIDCOM;
550
551         return 0;
552 } /* cypress_hidcom_startup */
553
554
555 static int cypress_ca42v2_startup(struct usb_serial *serial)
556 {
557         struct cypress_private *priv;
558
559         dbg("%s", __func__);
560
561         if (generic_startup(serial)) {
562                 dbg("%s - Failed setting up port %d", __func__,
563                                 serial->port[0]->number);
564                 return 1;
565         }
566
567         priv = usb_get_serial_port_data(serial->port[0]);
568         priv->chiptype = CT_CA42V2;
569
570         return 0;
571 } /* cypress_ca42v2_startup */
572
573
574 static void cypress_release(struct usb_serial *serial)
575 {
576         struct cypress_private *priv;
577
578         dbg("%s - port %d", __func__, serial->port[0]->number);
579
580         /* all open ports are closed at this point */
581
582         priv = usb_get_serial_port_data(serial->port[0]);
583
584         if (priv) {
585                 kfifo_free(&priv->write_fifo);
586                 kfree(priv);
587         }
588 }
589
590
591 static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
592 {
593         struct cypress_private *priv = usb_get_serial_port_data(port);
594         struct usb_serial *serial = port->serial;
595         unsigned long flags;
596         int result = 0;
597
598         dbg("%s - port %d", __func__, port->number);
599
600         if (!priv->comm_is_ok)
601                 return -EIO;
602
603         /* clear halts before open */
604         usb_clear_halt(serial->dev, 0x81);
605         usb_clear_halt(serial->dev, 0x02);
606
607         spin_lock_irqsave(&priv->lock, flags);
608         /* reset read/write statistics */
609         priv->bytes_in = 0;
610         priv->bytes_out = 0;
611         priv->cmd_count = 0;
612         priv->rx_flags = 0;
613         spin_unlock_irqrestore(&priv->lock, flags);
614
615         /* Set termios */
616         cypress_send(port);
617
618         if (tty)
619                 cypress_set_termios(tty, port, &priv->tmp_termios);
620
621         /* setup the port and start reading from the device */
622         if (!port->interrupt_in_urb) {
623                 dev_err(&port->dev, "%s - interrupt_in_urb is empty!\n",
624                         __func__);
625                 return -1;
626         }
627
628         usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
629                 usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
630                 port->interrupt_in_urb->transfer_buffer,
631                 port->interrupt_in_urb->transfer_buffer_length,
632                 cypress_read_int_callback, port, priv->read_urb_interval);
633         result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
634
635         if (result) {
636                 dev_err(&port->dev,
637                         "%s - failed submitting read urb, error %d\n",
638                                                         __func__, result);
639                 cypress_set_dead(port);
640         }
641         port->port.drain_delay = 256;
642         return result;
643 } /* cypress_open */
644
645 static void cypress_dtr_rts(struct usb_serial_port *port, int on)
646 {
647         struct cypress_private *priv = usb_get_serial_port_data(port);
648         /* drop dtr and rts */
649         spin_lock_irq(&priv->lock);
650         if (on == 0)
651                 priv->line_control = 0;
652         else 
653                 priv->line_control = CONTROL_DTR | CONTROL_RTS;
654         priv->cmd_ctrl = 1;
655         spin_unlock_irq(&priv->lock);
656         cypress_write(NULL, port, NULL, 0);
657 }
658
659 static void cypress_close(struct usb_serial_port *port)
660 {
661         struct cypress_private *priv = usb_get_serial_port_data(port);
662         unsigned long flags;
663
664         dbg("%s - port %d", __func__, port->number);
665
666         /* writing is potentially harmful, lock must be taken */
667         mutex_lock(&port->serial->disc_mutex);
668         if (port->serial->disconnected) {
669                 mutex_unlock(&port->serial->disc_mutex);
670                 return;
671         }
672         spin_lock_irqsave(&priv->lock, flags);
673         kfifo_reset_out(&priv->write_fifo);
674         spin_unlock_irqrestore(&priv->lock, flags);
675
676         dbg("%s - stopping urbs", __func__);
677         usb_kill_urb(port->interrupt_in_urb);
678         usb_kill_urb(port->interrupt_out_urb);
679
680         if (stats)
681                 dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
682                         priv->bytes_in, priv->bytes_out, priv->cmd_count);
683         mutex_unlock(&port->serial->disc_mutex);
684 } /* cypress_close */
685
686
687 static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
688                                         const unsigned char *buf, int count)
689 {
690         struct cypress_private *priv = usb_get_serial_port_data(port);
691
692         dbg("%s - port %d, %d bytes", __func__, port->number, count);
693
694         /* line control commands, which need to be executed immediately,
695            are not put into the buffer for obvious reasons.
696          */
697         if (priv->cmd_ctrl) {
698                 count = 0;
699                 goto finish;
700         }
701
702         if (!count)
703                 return count;
704
705         count = kfifo_in_locked(&priv->write_fifo, buf, count, &priv->lock);
706
707 finish:
708         cypress_send(port);
709
710         return count;
711 } /* cypress_write */
712
713
714 static void cypress_send(struct usb_serial_port *port)
715 {
716         int count = 0, result, offset, actual_size;
717         struct cypress_private *priv = usb_get_serial_port_data(port);
718         unsigned long flags;
719
720         if (!priv->comm_is_ok)
721                 return;
722
723         dbg("%s - port %d", __func__, port->number);
724         dbg("%s - interrupt out size is %d", __func__,
725                                                 port->interrupt_out_size);
726
727         spin_lock_irqsave(&priv->lock, flags);
728         if (priv->write_urb_in_use) {
729                 dbg("%s - can't write, urb in use", __func__);
730                 spin_unlock_irqrestore(&priv->lock, flags);
731                 return;
732         }
733         spin_unlock_irqrestore(&priv->lock, flags);
734
735         /* clear buffer */
736         memset(port->interrupt_out_urb->transfer_buffer, 0,
737                                                 port->interrupt_out_size);
738
739         spin_lock_irqsave(&priv->lock, flags);
740         switch (priv->pkt_fmt) {
741         default:
742         case packet_format_1:
743                 /* this is for the CY7C64013... */
744                 offset = 2;
745                 port->interrupt_out_buffer[0] = priv->line_control;
746                 break;
747         case packet_format_2:
748                 /* this is for the CY7C63743... */
749                 offset = 1;
750                 port->interrupt_out_buffer[0] = priv->line_control;
751                 break;
752         }
753
754         if (priv->line_control & CONTROL_RESET)
755                 priv->line_control &= ~CONTROL_RESET;
756
757         if (priv->cmd_ctrl) {
758                 priv->cmd_count++;
759                 dbg("%s - line control command being issued", __func__);
760                 spin_unlock_irqrestore(&priv->lock, flags);
761                 goto send;
762         } else
763                 spin_unlock_irqrestore(&priv->lock, flags);
764
765         count = kfifo_out_locked(&priv->write_fifo,
766                                         &port->interrupt_out_buffer[offset],
767                                         port->interrupt_out_size - offset,
768                                         &priv->lock);
769         if (count == 0)
770                 return;
771
772         switch (priv->pkt_fmt) {
773         default:
774         case packet_format_1:
775                 port->interrupt_out_buffer[1] = count;
776                 break;
777         case packet_format_2:
778                 port->interrupt_out_buffer[0] |= count;
779         }
780
781         dbg("%s - count is %d", __func__, count);
782
783 send:
784         spin_lock_irqsave(&priv->lock, flags);
785         priv->write_urb_in_use = 1;
786         spin_unlock_irqrestore(&priv->lock, flags);
787
788         if (priv->cmd_ctrl)
789                 actual_size = 1;
790         else
791                 actual_size = count +
792                               (priv->pkt_fmt == packet_format_1 ? 2 : 1);
793
794         usb_serial_debug_data(debug, &port->dev, __func__,
795                 port->interrupt_out_size,
796                 port->interrupt_out_urb->transfer_buffer);
797
798         usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev,
799                 usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
800                 port->interrupt_out_buffer, port->interrupt_out_size,
801                 cypress_write_int_callback, port, priv->write_urb_interval);
802         result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
803         if (result) {
804                 dev_err_console(port,
805                                 "%s - failed submitting write urb, error %d\n",
806                                                         __func__, result);
807                 priv->write_urb_in_use = 0;
808                 cypress_set_dead(port);
809         }
810
811         spin_lock_irqsave(&priv->lock, flags);
812         if (priv->cmd_ctrl)
813                 priv->cmd_ctrl = 0;
814
815         /* do not count the line control and size bytes */
816         priv->bytes_out += count;
817         spin_unlock_irqrestore(&priv->lock, flags);
818
819         usb_serial_port_softint(port);
820 } /* cypress_send */
821
822
823 /* returns how much space is available in the soft buffer */
824 static int cypress_write_room(struct tty_struct *tty)
825 {
826         struct usb_serial_port *port = tty->driver_data;
827         struct cypress_private *priv = usb_get_serial_port_data(port);
828         int room = 0;
829         unsigned long flags;
830
831         dbg("%s - port %d", __func__, port->number);
832
833         spin_lock_irqsave(&priv->lock, flags);
834         room = kfifo_avail(&priv->write_fifo);
835         spin_unlock_irqrestore(&priv->lock, flags);
836
837         dbg("%s - returns %d", __func__, room);
838         return room;
839 }
840
841
842 static int cypress_tiocmget(struct tty_struct *tty)
843 {
844         struct usb_serial_port *port = tty->driver_data;
845         struct cypress_private *priv = usb_get_serial_port_data(port);
846         __u8 status, control;
847         unsigned int result = 0;
848         unsigned long flags;
849
850         dbg("%s - port %d", __func__, port->number);
851
852         spin_lock_irqsave(&priv->lock, flags);
853         control = priv->line_control;
854         status = priv->current_status;
855         spin_unlock_irqrestore(&priv->lock, flags);
856
857         result = ((control & CONTROL_DTR)        ? TIOCM_DTR : 0)
858                 | ((control & CONTROL_RTS)       ? TIOCM_RTS : 0)
859                 | ((status & UART_CTS)        ? TIOCM_CTS : 0)
860                 | ((status & UART_DSR)        ? TIOCM_DSR : 0)
861                 | ((status & UART_RI)         ? TIOCM_RI  : 0)
862                 | ((status & UART_CD)         ? TIOCM_CD  : 0);
863
864         dbg("%s - result = %x", __func__, result);
865
866         return result;
867 }
868
869
870 static int cypress_tiocmset(struct tty_struct *tty,
871                                unsigned int set, unsigned int clear)
872 {
873         struct usb_serial_port *port = tty->driver_data;
874         struct cypress_private *priv = usb_get_serial_port_data(port);
875         unsigned long flags;
876
877         dbg("%s - port %d", __func__, port->number);
878
879         spin_lock_irqsave(&priv->lock, flags);
880         if (set & TIOCM_RTS)
881                 priv->line_control |= CONTROL_RTS;
882         if (set & TIOCM_DTR)
883                 priv->line_control |= CONTROL_DTR;
884         if (clear & TIOCM_RTS)
885                 priv->line_control &= ~CONTROL_RTS;
886         if (clear & TIOCM_DTR)
887                 priv->line_control &= ~CONTROL_DTR;
888         priv->cmd_ctrl = 1;
889         spin_unlock_irqrestore(&priv->lock, flags);
890
891         return cypress_write(tty, port, NULL, 0);
892 }
893
894
895 static int cypress_ioctl(struct tty_struct *tty,
896                                         unsigned int cmd, unsigned long arg)
897 {
898         struct usb_serial_port *port = tty->driver_data;
899         struct cypress_private *priv = usb_get_serial_port_data(port);
900
901         dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
902
903         switch (cmd) {
904         /* This code comes from drivers/char/serial.c and ftdi_sio.c */
905         case TIOCMIWAIT:
906                 while (priv != NULL) {
907                         interruptible_sleep_on(&priv->delta_msr_wait);
908                         /* see if a signal did it */
909                         if (signal_pending(current))
910                                 return -ERESTARTSYS;
911                         else {
912                                 char diff = priv->diff_status;
913                                 if (diff == 0)
914                                         return -EIO; /* no change => error */
915
916                                 /* consume all events */
917                                 priv->diff_status = 0;
918
919                                 /* return 0 if caller wanted to know about
920                                    these bits */
921                                 if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
922                                     ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
923                                     ((arg & TIOCM_CD) && (diff & UART_CD)) ||
924                                     ((arg & TIOCM_CTS) && (diff & UART_CTS)))
925                                         return 0;
926                                 /* otherwise caller can't care less about what
927                                  * happened, and so we continue to wait for
928                                  * more events.
929                                  */
930                         }
931                 }
932                 return 0;
933         default:
934                 break;
935         }
936         dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd);
937         return -ENOIOCTLCMD;
938 } /* cypress_ioctl */
939
940
941 static void cypress_set_termios(struct tty_struct *tty,
942         struct usb_serial_port *port, struct ktermios *old_termios)
943 {
944         struct cypress_private *priv = usb_get_serial_port_data(port);
945         int data_bits, stop_bits, parity_type, parity_enable;
946         unsigned cflag, iflag;
947         unsigned long flags;
948         __u8 oldlines;
949         int linechange = 0;
950
951         dbg("%s - port %d", __func__, port->number);
952
953         spin_lock_irqsave(&priv->lock, flags);
954         /* We can't clean this one up as we don't know the device type
955            early enough */
956         if (!priv->termios_initialized) {
957                 if (priv->chiptype == CT_EARTHMATE) {
958                         *(tty->termios) = tty_std_termios;
959                         tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL |
960                                 CLOCAL;
961                         tty->termios->c_ispeed = 4800;
962                         tty->termios->c_ospeed = 4800;
963                 } else if (priv->chiptype == CT_CYPHIDCOM) {
964                         *(tty->termios) = tty_std_termios;
965                         tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
966                                 CLOCAL;
967                         tty->termios->c_ispeed = 9600;
968                         tty->termios->c_ospeed = 9600;
969                 } else if (priv->chiptype == CT_CA42V2) {
970                         *(tty->termios) = tty_std_termios;
971                         tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
972                                 CLOCAL;
973                         tty->termios->c_ispeed = 9600;
974                         tty->termios->c_ospeed = 9600;
975                 }
976                 priv->termios_initialized = 1;
977         }
978         spin_unlock_irqrestore(&priv->lock, flags);
979
980         /* Unsupported features need clearing */
981         tty->termios->c_cflag &= ~(CMSPAR|CRTSCTS);
982
983         cflag = tty->termios->c_cflag;
984         iflag = tty->termios->c_iflag;
985
986         /* check if there are new settings */
987         if (old_termios) {
988                 spin_lock_irqsave(&priv->lock, flags);
989                 priv->tmp_termios = *(tty->termios);
990                 spin_unlock_irqrestore(&priv->lock, flags);
991         }
992
993         /* set number of data bits, parity, stop bits */
994         /* when parity is disabled the parity type bit is ignored */
995
996         /* 1 means 2 stop bits, 0 means 1 stop bit */
997         stop_bits = cflag & CSTOPB ? 1 : 0;
998
999         if (cflag & PARENB) {
1000                 parity_enable = 1;
1001                 /* 1 means odd parity, 0 means even parity */
1002                 parity_type = cflag & PARODD ? 1 : 0;
1003         } else
1004                 parity_enable = parity_type = 0;
1005
1006         switch (cflag & CSIZE) {
1007         case CS5:
1008                 data_bits = 0;
1009                 break;
1010         case CS6:
1011                 data_bits = 1;
1012                 break;
1013         case CS7:
1014                 data_bits = 2;
1015                 break;
1016         case CS8:
1017                 data_bits = 3;
1018                 break;
1019         default:
1020                 dev_err(&port->dev, "%s - CSIZE was set, but not CS5-CS8\n",
1021                         __func__);
1022                 data_bits = 3;
1023         }
1024         spin_lock_irqsave(&priv->lock, flags);
1025         oldlines = priv->line_control;
1026         if ((cflag & CBAUD) == B0) {
1027                 /* drop dtr and rts */
1028                 dbg("%s - dropping the lines, baud rate 0bps", __func__);
1029                 priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
1030         } else
1031                 priv->line_control = (CONTROL_DTR | CONTROL_RTS);
1032         spin_unlock_irqrestore(&priv->lock, flags);
1033
1034         dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, "
1035                         "%d data_bits (+5)", __func__, stop_bits,
1036                         parity_enable, parity_type, data_bits);
1037
1038         cypress_serial_control(tty, port, tty_get_baud_rate(tty),
1039                         data_bits, stop_bits,
1040                         parity_enable, parity_type,
1041                         0, CYPRESS_SET_CONFIG);
1042
1043         /* we perform a CYPRESS_GET_CONFIG so that the current settings are
1044          * filled into the private structure this should confirm that all is
1045          * working if it returns what we just set */
1046         cypress_serial_control(tty, port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
1047
1048         /* Here we can define custom tty settings for devices; the main tty
1049          * termios flag base comes from empeg.c */
1050
1051         spin_lock_irqsave(&priv->lock, flags);
1052         if (priv->chiptype == CT_EARTHMATE && priv->baud_rate == 4800) {
1053                 dbg("Using custom termios settings for a baud rate of "
1054                                 "4800bps.");
1055                 /* define custom termios settings for NMEA protocol */
1056
1057                 tty->termios->c_iflag /* input modes - */
1058                         &= ~(IGNBRK  /* disable ignore break */
1059                         | BRKINT     /* disable break causes interrupt */
1060                         | PARMRK     /* disable mark parity errors */
1061                         | ISTRIP     /* disable clear high bit of input char */
1062                         | INLCR      /* disable translate NL to CR */
1063                         | IGNCR      /* disable ignore CR */
1064                         | ICRNL      /* disable translate CR to NL */
1065                         | IXON);     /* disable enable XON/XOFF flow control */
1066
1067                 tty->termios->c_oflag /* output modes */
1068                         &= ~OPOST;    /* disable postprocess output char */
1069
1070                 tty->termios->c_lflag /* line discipline modes */
1071                         &= ~(ECHO     /* disable echo input characters */
1072                         | ECHONL      /* disable echo new line */
1073                         | ICANON      /* disable erase, kill, werase, and rprnt
1074                                          special characters */
1075                         | ISIG        /* disable interrupt, quit, and suspend
1076                                          special characters */
1077                         | IEXTEN);    /* disable non-POSIX special characters */
1078         } /* CT_CYPHIDCOM: Application should handle this for device */
1079
1080         linechange = (priv->line_control != oldlines);
1081         spin_unlock_irqrestore(&priv->lock, flags);
1082
1083         /* if necessary, set lines */
1084         if (linechange) {
1085                 priv->cmd_ctrl = 1;
1086                 cypress_write(tty, port, NULL, 0);
1087         }
1088 } /* cypress_set_termios */
1089
1090
1091 /* returns amount of data still left in soft buffer */
1092 static int cypress_chars_in_buffer(struct tty_struct *tty)
1093 {
1094         struct usb_serial_port *port = tty->driver_data;
1095         struct cypress_private *priv = usb_get_serial_port_data(port);
1096         int chars = 0;
1097         unsigned long flags;
1098
1099         dbg("%s - port %d", __func__, port->number);
1100
1101         spin_lock_irqsave(&priv->lock, flags);
1102         chars = kfifo_len(&priv->write_fifo);
1103         spin_unlock_irqrestore(&priv->lock, flags);
1104
1105         dbg("%s - returns %d", __func__, chars);
1106         return chars;
1107 }
1108
1109
1110 static void cypress_throttle(struct tty_struct *tty)
1111 {
1112         struct usb_serial_port *port = tty->driver_data;
1113         struct cypress_private *priv = usb_get_serial_port_data(port);
1114
1115         dbg("%s - port %d", __func__, port->number);
1116
1117         spin_lock_irq(&priv->lock);
1118         priv->rx_flags = THROTTLED;
1119         spin_unlock_irq(&priv->lock);
1120 }
1121
1122
1123 static void cypress_unthrottle(struct tty_struct *tty)
1124 {
1125         struct usb_serial_port *port = tty->driver_data;
1126         struct cypress_private *priv = usb_get_serial_port_data(port);
1127         int actually_throttled, result;
1128
1129         dbg("%s - port %d", __func__, port->number);
1130
1131         spin_lock_irq(&priv->lock);
1132         actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
1133         priv->rx_flags = 0;
1134         spin_unlock_irq(&priv->lock);
1135
1136         if (!priv->comm_is_ok)
1137                 return;
1138
1139         if (actually_throttled) {
1140                 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
1141                 if (result) {
1142                         dev_err(&port->dev, "%s - failed submitting read urb, "
1143                                         "error %d\n", __func__, result);
1144                         cypress_set_dead(port);
1145                 }
1146         }
1147 }
1148
1149
1150 static void cypress_read_int_callback(struct urb *urb)
1151 {
1152         struct usb_serial_port *port = urb->context;
1153         struct cypress_private *priv = usb_get_serial_port_data(port);
1154         struct tty_struct *tty;
1155         unsigned char *data = urb->transfer_buffer;
1156         unsigned long flags;
1157         char tty_flag = TTY_NORMAL;
1158         int havedata = 0;
1159         int bytes = 0;
1160         int result;
1161         int i = 0;
1162         int status = urb->status;
1163
1164         dbg("%s - port %d", __func__, port->number);
1165
1166         switch (status) {
1167         case 0: /* success */
1168                 break;
1169         case -ECONNRESET:
1170         case -ENOENT:
1171         case -ESHUTDOWN:
1172                 /* precursor to disconnect so just go away */
1173                 return;
1174         case -EPIPE:
1175                 /* Can't call usb_clear_halt while in_interrupt */
1176                 /* FALLS THROUGH */
1177         default:
1178                 /* something ugly is going on... */
1179                 dev_err(&urb->dev->dev,
1180                         "%s - unexpected nonzero read status received: %d\n",
1181                                                         __func__, status);
1182                 cypress_set_dead(port);
1183                 return;
1184         }
1185
1186         spin_lock_irqsave(&priv->lock, flags);
1187         if (priv->rx_flags & THROTTLED) {
1188                 dbg("%s - now throttling", __func__);
1189                 priv->rx_flags |= ACTUALLY_THROTTLED;
1190                 spin_unlock_irqrestore(&priv->lock, flags);
1191                 return;
1192         }
1193         spin_unlock_irqrestore(&priv->lock, flags);
1194
1195         tty = tty_port_tty_get(&port->port);
1196         if (!tty) {
1197                 dbg("%s - bad tty pointer - exiting", __func__);
1198                 return;
1199         }
1200
1201         spin_lock_irqsave(&priv->lock, flags);
1202         result = urb->actual_length;
1203         switch (priv->pkt_fmt) {
1204         default:
1205         case packet_format_1:
1206                 /* This is for the CY7C64013... */
1207                 priv->current_status = data[0] & 0xF8;
1208                 bytes = data[1] + 2;
1209                 i = 2;
1210                 if (bytes > 2)
1211                         havedata = 1;
1212                 break;
1213         case packet_format_2:
1214                 /* This is for the CY7C63743... */
1215                 priv->current_status = data[0] & 0xF8;
1216                 bytes = (data[0] & 0x07) + 1;
1217                 i = 1;
1218                 if (bytes > 1)
1219                         havedata = 1;
1220                 break;
1221         }
1222         spin_unlock_irqrestore(&priv->lock, flags);
1223         if (result < bytes) {
1224                 dbg("%s - wrong packet size - received %d bytes but packet "
1225                     "said %d bytes", __func__, result, bytes);
1226                 goto continue_read;
1227         }
1228
1229         usb_serial_debug_data(debug, &port->dev, __func__,
1230                                                 urb->actual_length, data);
1231
1232         spin_lock_irqsave(&priv->lock, flags);
1233         /* check to see if status has changed */
1234         if (priv->current_status != priv->prev_status) {
1235                 priv->diff_status |= priv->current_status ^
1236                         priv->prev_status;
1237                 wake_up_interruptible(&priv->delta_msr_wait);
1238                 priv->prev_status = priv->current_status;
1239         }
1240         spin_unlock_irqrestore(&priv->lock, flags);
1241
1242         /* hangup, as defined in acm.c... this might be a bad place for it
1243          * though */
1244         if (tty && !(tty->termios->c_cflag & CLOCAL) &&
1245                         !(priv->current_status & UART_CD)) {
1246                 dbg("%s - calling hangup", __func__);
1247                 tty_hangup(tty);
1248                 goto continue_read;
1249         }
1250
1251         /* There is one error bit... I'm assuming it is a parity error
1252          * indicator as the generic firmware will set this bit to 1 if a
1253          * parity error occurs.
1254          * I can not find reference to any other error events. */
1255         spin_lock_irqsave(&priv->lock, flags);
1256         if (priv->current_status & CYP_ERROR) {
1257                 spin_unlock_irqrestore(&priv->lock, flags);
1258                 tty_flag = TTY_PARITY;
1259                 dbg("%s - Parity Error detected", __func__);
1260         } else
1261                 spin_unlock_irqrestore(&priv->lock, flags);
1262
1263         /* process read if there is data other than line status */
1264         if (tty && bytes > i) {
1265                 tty_insert_flip_string_fixed_flag(tty, data + i,
1266                                 tty_flag, bytes - i);
1267                 tty_flip_buffer_push(tty);
1268         }
1269
1270         spin_lock_irqsave(&priv->lock, flags);
1271         /* control and status byte(s) are also counted */
1272         priv->bytes_in += bytes;
1273         spin_unlock_irqrestore(&priv->lock, flags);
1274
1275 continue_read:
1276         tty_kref_put(tty);
1277
1278         /* Continue trying to always read */
1279
1280         if (priv->comm_is_ok) {
1281                 usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
1282                                 usb_rcvintpipe(port->serial->dev,
1283                                         port->interrupt_in_endpointAddress),
1284                                 port->interrupt_in_urb->transfer_buffer,
1285                                 port->interrupt_in_urb->transfer_buffer_length,
1286                                 cypress_read_int_callback, port,
1287                                 priv->read_urb_interval);
1288                 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
1289                 if (result && result != -EPERM) {
1290                         dev_err(&urb->dev->dev, "%s - failed resubmitting "
1291                                         "read urb, error %d\n", __func__,
1292                                         result);
1293                         cypress_set_dead(port);
1294                 }
1295         }
1296 } /* cypress_read_int_callback */
1297
1298
1299 static void cypress_write_int_callback(struct urb *urb)
1300 {
1301         struct usb_serial_port *port = urb->context;
1302         struct cypress_private *priv = usb_get_serial_port_data(port);
1303         int result;
1304         int status = urb->status;
1305
1306         dbg("%s - port %d", __func__, port->number);
1307
1308         switch (status) {
1309         case 0:
1310                 /* success */
1311                 break;
1312         case -ECONNRESET:
1313         case -ENOENT:
1314         case -ESHUTDOWN:
1315                 /* this urb is terminated, clean up */
1316                 dbg("%s - urb shutting down with status: %d",
1317                                                 __func__, status);
1318                 priv->write_urb_in_use = 0;
1319                 return;
1320         case -EPIPE: /* no break needed; clear halt and resubmit */
1321                 if (!priv->comm_is_ok)
1322                         break;
1323                 usb_clear_halt(port->serial->dev, 0x02);
1324                 /* error in the urb, so we have to resubmit it */
1325                 dbg("%s - nonzero write bulk status received: %d",
1326                         __func__, status);
1327                 port->interrupt_out_urb->transfer_buffer_length = 1;
1328                 result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
1329                 if (!result)
1330                         return;
1331                 dev_err(&urb->dev->dev,
1332                         "%s - failed resubmitting write urb, error %d\n",
1333                                                         __func__, result);
1334                 cypress_set_dead(port);
1335                 break;
1336         default:
1337                 dev_err(&urb->dev->dev,
1338                          "%s - unexpected nonzero write status received: %d\n",
1339                                                         __func__, status);
1340                 cypress_set_dead(port);
1341                 break;
1342         }
1343         priv->write_urb_in_use = 0;
1344
1345         /* send any buffered data */
1346         cypress_send(port);
1347 }
1348
1349 module_usb_serial_driver(cypress_driver, serial_drivers);
1350
1351 MODULE_AUTHOR(DRIVER_AUTHOR);
1352 MODULE_DESCRIPTION(DRIVER_DESC);
1353 MODULE_VERSION(DRIVER_VERSION);
1354 MODULE_LICENSE("GPL");
1355
1356 module_param(debug, bool, S_IRUGO | S_IWUSR);
1357 MODULE_PARM_DESC(debug, "Debug enabled or not");
1358 module_param(stats, bool, S_IRUGO | S_IWUSR);
1359 MODULE_PARM_DESC(stats, "Enable statistics or not");
1360 module_param(interval, int, S_IRUGO | S_IWUSR);
1361 MODULE_PARM_DESC(interval, "Overrides interrupt interval");
1362 module_param(unstable_bauds, bool, S_IRUGO | S_IWUSR);
1363 MODULE_PARM_DESC(unstable_bauds, "Allow unstable baud rates");