This commit was manufactured by cvs2svn to create branch 'vserver'.
[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  *
20  *  Lonnie Mendez <dignome@gmail.com>
21  *  04-10-2004
22  *      Driver modified to support dynamic line settings.  Various improvments
23  *      and features.
24  *
25  *  Neil Whelchel
26  *  10-2003
27  *      Driver first released.
28  *
29  *
30  * Long Term TODO:
31  *      Improve transfer speeds - both read/write are somewhat slow
32  *   at this point.
33  */
34
35 /* Neil Whelchel wrote the cypress m8 implementation */
36 /* Thanks to cypress for providing references for the hid reports. */
37 /* Thanks to Jiang Zhang for providing links and for general help. */
38 /* Code originates and was built up from ftdi_sio, belkin, pl2303 and others. */
39
40
41 #include <linux/config.h>
42 #include <linux/kernel.h>
43 #include <linux/errno.h>
44 #include <linux/init.h>
45 #include <linux/slab.h>
46 #include <linux/tty.h>
47 #include <linux/tty_driver.h>
48 #include <linux/tty_flip.h>
49 #include <linux/module.h>
50 #include <linux/moduleparam.h>
51 #include <linux/spinlock.h>
52 #include <asm/uaccess.h>
53 #include <linux/usb.h>
54 #include <linux/serial.h>
55
56 #ifdef CONFIG_USB_SERIAL_DEBUG
57         static int debug = 1;
58 #else
59         static int debug;
60 #endif
61
62 static int stats;
63
64 #include "usb-serial.h"
65 #include "cypress_m8.h"
66
67 /*
68  * Version Information
69  */
70 #define DRIVER_VERSION "v1.06"
71 #define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>"
72 #define DRIVER_DESC "Cypress USB to Serial Driver"
73
74 static struct usb_device_id id_table_earthmate [] = {
75         { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
76         { }                                             /* Terminating entry */
77 };
78
79 static struct usb_device_id id_table_cyphidcomrs232 [] = {
80         { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
81         { }                                             /* Terminating entry */
82 };
83
84 static struct usb_device_id id_table_combined [] = {
85         { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
86         { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
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 struct cypress_private {
100         spinlock_t lock;                   /* private lock */
101         int chiptype;                      /* identifier of device, for quirks/etc */
102         int bytes_in;                      /* used for statistics */
103         int bytes_out;                     /* used for statistics */
104         int cmd_count;                     /* used for statistics */
105         int cmd_ctrl;                      /* always set this to 1 before issuing a command */
106         int termios_initialized;
107         __u8 line_control;                 /* holds dtr / rts value */
108         __u8 current_status;               /* received from last read - info on dsr,cts,cd,ri,etc */
109         __u8 current_config;               /* stores the current configuration byte */
110         __u8 rx_flags;                     /* throttling - used from whiteheat/ftdi_sio */
111         int baud_rate;                     /* stores current baud rate in integer form */
112         int cbr_mask;                      /* stores current baud rate in masked form */
113         int isthrottled;                   /* if throttled, discard reads */
114         wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */
115         char prev_status, diff_status;     /* used for TIOCMIWAIT */
116         /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */
117         struct termios tmp_termios;        /* stores the old termios settings */
118         int write_interval;                /* interrupt out write interval, as obtained from interrupt_out_urb */
119         int writepipe;                     /* used for clear halt, if necessary */
120 };
121
122 /* function prototypes for the Cypress USB to serial device */
123 static int  cypress_earthmate_startup   (struct usb_serial *serial);
124 static int  cypress_hidcom_startup      (struct usb_serial *serial);
125 static void cypress_shutdown            (struct usb_serial *serial);
126 static int  cypress_open                (struct usb_serial_port *port, struct file *filp);
127 static void cypress_close               (struct usb_serial_port *port, struct file *filp);
128 static int  cypress_write               (struct usb_serial_port *port, const unsigned char *buf, int count);
129 static int  cypress_write_room          (struct usb_serial_port *port);
130 static int  cypress_ioctl               (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
131 static void cypress_set_termios         (struct usb_serial_port *port, struct termios * old);
132 static int  cypress_tiocmget            (struct usb_serial_port *port, struct file *file);
133 static int  cypress_tiocmset            (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
134 static int  cypress_chars_in_buffer     (struct usb_serial_port *port);
135 static void cypress_throttle            (struct usb_serial_port *port);
136 static void cypress_unthrottle          (struct usb_serial_port *port);
137 static void cypress_read_int_callback   (struct urb *urb, struct pt_regs *regs);
138 static void cypress_write_int_callback  (struct urb *urb, struct pt_regs *regs);
139 static int  mask_to_rate                (unsigned mask);
140 static unsigned rate_to_mask            (int rate);
141
142 static struct usb_serial_device_type cypress_earthmate_device = {
143         .owner =                        THIS_MODULE,
144         .name =                         "DeLorme Earthmate USB",
145         .short_name =                   "earthmate",
146         .id_table =                     id_table_earthmate,
147         .num_interrupt_in =             1,
148         .num_interrupt_out =            1,
149         .num_bulk_in =                  NUM_DONT_CARE,
150         .num_bulk_out =                 NUM_DONT_CARE,
151         .num_ports =                    1,
152         .attach =                       cypress_earthmate_startup,
153         .shutdown =                     cypress_shutdown,
154         .open =                         cypress_open,
155         .close =                        cypress_close,
156         .write =                        cypress_write,
157         .write_room =                   cypress_write_room,
158         .ioctl =                        cypress_ioctl,
159         .set_termios =                  cypress_set_termios,
160         .tiocmget =                     cypress_tiocmget,
161         .tiocmset =                     cypress_tiocmset,
162         .chars_in_buffer =              cypress_chars_in_buffer,
163         .throttle =                     cypress_throttle,
164         .unthrottle =                   cypress_unthrottle,
165         .read_int_callback =            cypress_read_int_callback,
166         .write_int_callback =           cypress_write_int_callback,
167 };
168
169 static struct usb_serial_device_type cypress_hidcom_device = {
170         .owner =                        THIS_MODULE,
171         .name =                         "HID->COM RS232 Adapter",
172         .short_name =                   "cyphidcom",
173         .id_table =                     id_table_cyphidcomrs232,
174         .num_interrupt_in =             1,
175         .num_interrupt_out =            1,
176         .num_bulk_in =                  NUM_DONT_CARE,
177         .num_bulk_out =                 NUM_DONT_CARE,
178         .num_ports =                    1,
179         .attach =                       cypress_hidcom_startup,
180         .shutdown =                     cypress_shutdown,
181         .open =                         cypress_open,
182         .close =                        cypress_close,
183         .write =                        cypress_write,
184         .write_room =                   cypress_write_room,
185         .ioctl =                        cypress_ioctl,
186         .set_termios =                  cypress_set_termios,
187         .tiocmget =                     cypress_tiocmget,
188         .tiocmset =                     cypress_tiocmset,
189         .chars_in_buffer =              cypress_chars_in_buffer,
190         .throttle =                     cypress_throttle,
191         .unthrottle =                   cypress_unthrottle,
192         .read_int_callback =            cypress_read_int_callback,
193         .write_int_callback =           cypress_write_int_callback,
194 };
195
196
197 /*****************************************************************************
198  * Cypress serial helper functions
199  *****************************************************************************/
200
201
202 /* This function can either set or retreive the current serial line settings */
203 static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits,
204                                    int parity_enable, int parity_type, int reset, int cypress_request_type)
205 {
206         int i, n_baud_rate = 0, retval = 0;
207         struct cypress_private *priv;
208         __u8 feature_buffer[5];
209         __u8 config;
210         unsigned long flags;
211
212         dbg("%s", __FUNCTION__);
213         
214         priv = usb_get_serial_port_data(port);
215
216         switch(cypress_request_type) {
217                 case CYPRESS_SET_CONFIG:
218
219                         /*
220                          * The general purpose firmware for the Cypress M8 allows for a maximum speed
221                          * of 57600bps (I have no idea whether DeLorme chose to use the general purpose
222                          * firmware or not), if you need to modify this speed setting for your own
223                          * project please add your own chiptype and modify the code likewise.  The
224                          * Cypress HID->COM device will work successfully up to 115200bps.
225                          */
226                         if (baud_mask != priv->cbr_mask) {
227                                 dbg("%s - baud rate is changing", __FUNCTION__);
228                                 if ( priv->chiptype == CT_EARTHMATE ) {
229                                         /* 300 and 600 baud rates are supported under the generic firmware,
230                                          * but are not used with NMEA and SiRF protocols */
231                                         
232                                         if ( (baud_mask == B300) || (baud_mask == B600) ) {
233                                                 err("%s - failed setting baud rate, unsupported speed (default to 4800)",
234                                                     __FUNCTION__);
235                                                 n_baud_rate = 4800;
236                                         } else if ( (n_baud_rate = mask_to_rate(baud_mask)) == -1) {
237                                                 err("%s - failed setting baud rate, unsupported speed (default to 4800)",
238                                                     __FUNCTION__);
239                                                 n_baud_rate = 4800;
240                                         }
241                                 } else if (priv->chiptype == CT_CYPHIDCOM) {
242                                         if ( (n_baud_rate = mask_to_rate(baud_mask)) == -1) {
243                                                 err("%s - failed setting baud rate, unsupported speed (default to 4800)",
244                                                     __FUNCTION__);
245                                                 n_baud_rate = 4800;
246                                         }
247                                 } else if (priv->chiptype == CT_GENERIC) {
248                                         if ( (n_baud_rate = mask_to_rate(baud_mask)) == -1) {
249                                                 err("%s - failed setting baud rate, unsupported speed (default to 4800)",
250                                                     __FUNCTION__);
251                                                 n_baud_rate = 4800;
252                                         }
253                                 } else {
254                                         info("%s - please define your chiptype, using 4800bps default", __FUNCTION__);
255                                         n_baud_rate = 4800;
256                                 }
257                         } else {  /* baud rate not changing, keep the old */
258                                 n_baud_rate = priv->baud_rate;
259                         }
260                         dbg("%s - baud rate is being sent as %d", __FUNCTION__, n_baud_rate);
261
262                         
263                         /*
264                          * This algorithm accredited to Jiang Jay Zhang... thanks for all the help!
265                          */
266                         for (i = 0; i < 4; ++i) {
267                                 feature_buffer[i] = ( n_baud_rate >> (i*8) & 0xFF );
268                         }
269
270                         config = 0;                      // reset config byte
271                         config |= data_bits;             // assign data bits in 2 bit space ( max 3 )
272                         /* 1 bit gap */
273                         config |= (stop_bits << 3);      // assign stop bits in 1 bit space
274                         config |= (parity_enable << 4);  // assign parity flag in 1 bit space
275                         config |= (parity_type << 5);    // assign parity type in 1 bit space
276                         /* 1 bit gap */
277                         config |= (reset << 7);          // assign reset at end of byte, 1 bit space
278
279                         feature_buffer[4] = config;
280                                 
281                         dbg("%s - device is being sent this feature report:", __FUNCTION__);
282                         dbg("%s - %02X - %02X - %02X - %02X - %02X", __FUNCTION__, feature_buffer[0], feature_buffer[1],
283                             feature_buffer[2], feature_buffer[3], feature_buffer[4]);
284                         
285                         retval = usb_control_msg (port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
286                                                   HID_REQ_SET_REPORT, USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
287                                                   0x0300, 0, feature_buffer, 5, 500);
288
289                         if (retval != 5)
290                                 err("%s - failed sending serial line settings - %d", __FUNCTION__, retval);
291                         else {
292                                 spin_lock_irqsave(&priv->lock, flags);
293                                 priv->baud_rate = n_baud_rate;
294                                 priv->cbr_mask = baud_mask;
295                                 priv->current_config = config;
296                                 ++priv->cmd_count;
297                                 spin_unlock_irqrestore(&priv->lock, flags);
298                         }
299                 break;
300                 case CYPRESS_GET_CONFIG:
301                         dbg("%s - retreiving serial line settings", __FUNCTION__);
302                         /* reset values in feature buffer */
303                         memset(feature_buffer, 0, 5);
304
305                         retval = usb_control_msg (port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0),
306                                                   HID_REQ_GET_REPORT, USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
307                                                   0x0300, 0, feature_buffer, 5, 500);
308                         if (retval != 5) {
309                                 err("%s - failed to retreive serial line settings - %d", __FUNCTION__, retval);
310                                 return retval;
311                         } else {
312                                 spin_lock_irqsave(&priv->lock, flags);
313                                 /* store the config in one byte, and later use bit masks to check values */
314                                 priv->current_config = feature_buffer[4];
315                                 /* reverse the process above to get the baud_mask value */
316                                 n_baud_rate = 0; // reset bits
317                                 for (i = 0; i < 4; ++i) {
318                                         n_baud_rate |= ( feature_buffer[i] << (i*8) );
319                                 }
320                                 
321                                 priv->baud_rate = n_baud_rate;
322                                 if ( (priv->cbr_mask = rate_to_mask(n_baud_rate)) == 0x40)
323                                         dbg("%s - failed setting the baud mask (not defined)", __FUNCTION__);
324                                 ++priv->cmd_count;
325                                 spin_unlock_irqrestore(&priv->lock, flags);
326                         }
327                         break;
328                 default:
329                         err("%s - unsupported serial control command issued", __FUNCTION__);
330         }
331         return retval;
332 } /* cypress_serial_control */
333
334
335 /* given a baud mask, it will return speed on success */
336 static int mask_to_rate (unsigned mask)
337 {
338         int rate;
339
340         switch (mask) {
341                 case B0: rate = 0; break;
342                 case B300: rate = 300; break;
343                 case B600: rate = 600; break;
344                 case B1200: rate = 1200; break;
345                 case B2400: rate = 2400; break;
346                 case B4800: rate = 4800; break;
347                 case B9600: rate = 9600; break;
348                 case B19200: rate = 19200; break;
349                 case B38400: rate = 38400; break;
350                 case B57600: rate = 57600; break;
351                 case B115200: rate = 115200; break;
352                 default: rate = -1;
353         }
354
355         return rate;
356 }
357
358
359 static unsigned rate_to_mask (int rate)
360 {
361         unsigned mask;
362
363         switch (rate) {
364                 case 0: mask = B0; break;
365                 case 300: mask = B300; break;
366                 case 600: mask = B600; break;
367                 case 1200: mask = B1200; break;
368                 case 2400: mask = B2400; break;
369                 case 4800: mask = B4800; break;
370                 case 9600: mask = B9600; break;
371                 case 19200: mask = B19200; break;
372                 case 38400: mask = B38400; break;
373                 case 57600: mask = B57600; break;
374                 case 115200: mask = B115200; break;
375                 default: mask = 0x40;
376         }
377
378         return mask;
379 }
380 /*****************************************************************************
381  * Cypress serial driver functions
382  *****************************************************************************/
383
384
385 static int generic_startup (struct usb_serial *serial)
386 {
387         struct cypress_private *priv;
388
389         dbg("%s - port %d", __FUNCTION__, serial->port[0]->number);
390
391         priv = kmalloc(sizeof (struct cypress_private), GFP_KERNEL);
392         if (!priv)
393                 return -ENOMEM;
394
395         memset(priv, 0x00, sizeof (struct cypress_private));
396         spin_lock_init(&priv->lock);
397         init_waitqueue_head(&priv->delta_msr_wait);
398         priv->writepipe = serial->port[0]->interrupt_out_urb->pipe;
399         
400         /* free up interrupt_out buffer / urb allocated by usbserial
401          * for this port as we use our own urbs for writing */
402         if (serial->port[0]->interrupt_out_buffer) {
403                 kfree(serial->port[0]->interrupt_out_buffer);
404                 serial->port[0]->interrupt_out_buffer = NULL;
405         }
406         if (serial->port[0]->interrupt_out_urb) {
407                 priv->write_interval = serial->port[0]->interrupt_out_urb->interval;
408                 usb_free_urb(serial->port[0]->interrupt_out_urb);
409                 serial->port[0]->interrupt_out_urb = NULL;
410         } else /* still need a write interval */
411                 priv->write_interval = 10;
412
413         priv->cmd_ctrl = 0;
414         priv->line_control = 0;
415         priv->termios_initialized = 0;
416         priv->rx_flags = 0;
417         usb_set_serial_port_data(serial->port[0], priv);
418         
419         return (0);     
420 }       
421
422
423 static int cypress_earthmate_startup (struct usb_serial *serial)
424 {
425         struct cypress_private *priv;
426
427         dbg("%s", __FUNCTION__);
428
429         if (generic_startup(serial)) {
430                 dbg("%s - Failed setting up port %d", __FUNCTION__, serial->port[0]->number);
431                 return 1;
432         }
433
434         priv = usb_get_serial_port_data(serial->port[0]);
435         priv->chiptype = CT_EARTHMATE;
436         
437         return (0);     
438 } /* cypress_earthmate_startup */
439
440
441 static int cypress_hidcom_startup (struct usb_serial *serial)
442 {
443         struct cypress_private *priv;
444
445         dbg("%s", __FUNCTION__);
446
447         if (generic_startup(serial)) {
448                 dbg("%s - Failed setting up port %d", __FUNCTION__, serial->port[0]->number);
449                 return 1;
450         }
451
452         priv = usb_get_serial_port_data(serial->port[0]);
453         priv->chiptype = CT_CYPHIDCOM;
454         
455         return (0);     
456 } /* cypress_hidcom_startup */
457
458
459 static void cypress_shutdown (struct usb_serial *serial)
460 {
461         struct cypress_private *priv;
462
463         dbg ("%s - port %d", __FUNCTION__, serial->port[0]->number);
464
465         /* all open ports are closed at this point */
466
467         priv = usb_get_serial_port_data(serial->port[0]);
468
469         if (priv) {
470                 kfree(priv);
471                 usb_set_serial_port_data(serial->port[0], NULL);
472         }
473 }
474
475
476 static int cypress_open (struct usb_serial_port *port, struct file *filp)
477 {
478         struct cypress_private *priv = usb_get_serial_port_data(port);
479         struct usb_serial *serial = port->serial;
480         unsigned long flags;
481         int result = 0;
482
483         dbg("%s - port %d", __FUNCTION__, port->number);
484
485         spin_lock_irqsave(&priv->lock, flags);
486         /* reset read/write statistics */
487         priv->bytes_in = 0;
488         priv->bytes_out = 0;
489         priv->cmd_count = 0;
490
491         /* turn on dtr / rts since we are not flow controlling by default */
492         priv->line_control = CONTROL_DTR | CONTROL_RTS; /* sent in status byte */
493         spin_unlock_irqrestore(&priv->lock, flags);
494         priv->cmd_ctrl = 1;
495         result = cypress_write(port, NULL, 0);
496         
497         port->tty->low_latency = 1;
498
499         /* termios defaults are set by usb_serial_init */
500         
501         cypress_set_termios(port, &priv->tmp_termios);
502
503         if (result) {
504                 dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __FUNCTION__, result);
505                 return result;
506         } else
507                 dbg("%s - success setting the control lines", __FUNCTION__);
508
509         /* throttling off */
510         spin_lock_irqsave(&priv->lock, flags);
511         priv->rx_flags = 0;
512         spin_unlock_irqrestore(&priv->lock, flags);
513
514         /* setup the port and
515          * start reading from the device */
516         if(!port->interrupt_in_urb){
517                 err("%s - interrupt_in_urb is empty!", __FUNCTION__);
518                 return(-1);
519         }
520
521         usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
522                 usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
523                 port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length,
524                 cypress_read_int_callback, port, port->interrupt_in_urb->interval);
525         result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
526
527         if (result){
528                 dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
529         }
530
531         return result;
532 } /* cypress_open */
533
534
535 static void cypress_close(struct usb_serial_port *port, struct file * filp)
536 {
537         struct cypress_private *priv = usb_get_serial_port_data(port);
538         unsigned int c_cflag;
539         unsigned long flags;
540
541         dbg("%s - port %d", __FUNCTION__, port->number);
542
543         if (port->tty) {
544                 c_cflag = port->tty->termios->c_cflag;
545                 if (c_cflag & HUPCL) {
546                         /* drop dtr and rts */
547                         priv = usb_get_serial_port_data(port);
548                         spin_lock_irqsave(&priv->lock, flags);
549                         priv->line_control = 0;
550                         priv->cmd_ctrl = 1;
551                         spin_unlock_irqrestore(&priv->lock, flags);
552                         cypress_write(port, NULL, 0);
553                 }
554         }
555
556         if (port->interrupt_in_urb) {
557                 dbg("%s - stopping read urb", __FUNCTION__);
558                 usb_kill_urb (port->interrupt_in_urb);
559         }
560
561         if (stats)
562                 dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
563                           priv->bytes_in, priv->bytes_out, priv->cmd_count);
564 } /* cypress_close */
565
566
567 static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, int count)
568 {
569         struct cypress_private *priv = usb_get_serial_port_data(port);
570         unsigned long flags;
571         struct urb *urb;
572         int status, s_pos = 0;
573         __u8 transfer_size = 0;
574         __u8 *buffer;
575
576         dbg("%s - port %d", __FUNCTION__, port->number);
577
578         spin_lock_irqsave(&priv->lock, flags);
579         if (count == 0 && !priv->cmd_ctrl) {
580                 spin_unlock_irqrestore(&priv->lock, flags);
581                 dbg("%s - write request of 0 bytes", __FUNCTION__);
582                 return 0;
583         }
584
585         if (priv->cmd_ctrl)
586                 ++priv->cmd_count;
587         priv->cmd_ctrl = 0;
588         spin_unlock_irqrestore(&priv->lock, flags);
589
590         dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size);
591         dbg("%s - count is %d", __FUNCTION__, count);
592
593         /* Allocate buffer and urb */
594         buffer = kmalloc (port->interrupt_out_size, GFP_ATOMIC);
595         if (!buffer) {
596                 dev_err(&port->dev, "ran out of memory for buffer\n");
597                 return -ENOMEM;
598         }
599
600         urb = usb_alloc_urb (0, GFP_ATOMIC);
601         if (!urb) {
602                 dev_err(&port->dev, "failed allocating write urb\n");
603                 kfree (buffer);
604                 return -ENOMEM;
605         }
606
607         memset(buffer, 0, port->interrupt_out_size); // test if this is needed... probably not since loop removed
608
609         spin_lock_irqsave(&priv->lock, flags);
610         switch (port->interrupt_out_size) {
611                 case 32:
612                         // this is for the CY7C64013...
613                         transfer_size = min (count, 30);
614                         buffer[0] = priv->line_control;
615                         buffer[1] = transfer_size;
616                         s_pos = 2;
617                         break;
618                 case 8:
619                         // this is for the CY7C63743...
620                         transfer_size = min (count, 7);
621                         buffer[0] = priv->line_control | transfer_size;
622                         s_pos = 1;
623                         break;
624                 default:
625                         dbg("%s - wrong packet size", __FUNCTION__);
626                         spin_unlock_irqrestore(&priv->lock, flags);
627                         kfree (buffer);
628                         usb_free_urb (urb);
629                         return -1;
630         }
631
632         if (priv->line_control & CONTROL_RESET)
633                 priv->line_control &= ~CONTROL_RESET;
634         spin_unlock_irqrestore(&priv->lock, flags);
635
636         /* copy data to offset position in urb transfer buffer */
637         memcpy (&buffer[s_pos], buf, transfer_size);
638
639         usb_serial_debug_data (debug, &port->dev, __FUNCTION__, port->interrupt_out_size, buffer);
640
641         /* build up the urb */
642         usb_fill_int_urb (urb, port->serial->dev,
643                           usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
644                           buffer, port->interrupt_out_size,
645                           cypress_write_int_callback, port, priv->write_interval);
646
647         status = usb_submit_urb(urb, GFP_ATOMIC);
648
649         if (status) {
650                 dev_err(&port->dev, "%s - usb_submit_urb (write interrupt) failed with status %d\n",
651                         __FUNCTION__, status);
652                 transfer_size = status;
653                 kfree (buffer);
654                 goto exit;
655         }
656
657         spin_lock_irqsave(&priv->lock, flags);
658         priv->bytes_out += transfer_size;
659         spin_unlock_irqrestore(&priv->lock, flags);
660
661 exit:
662         /* buffer free'd in callback */
663         usb_free_urb (urb);
664
665         return transfer_size;
666
667 } /* cypress_write */
668
669
670 static int cypress_write_room(struct usb_serial_port *port)
671 {
672         dbg("%s - port %d", __FUNCTION__, port->number);
673
674         /*
675          * We really can take anything the user throw at us
676          * but let's pick a nice big number to tell the tty
677          * layer that we have lots of free space
678          */     
679
680         return 2048;
681 }
682
683
684 static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
685 {
686         struct cypress_private *priv = usb_get_serial_port_data(port);
687         __u8 status, control;
688         unsigned int result = 0;
689         unsigned long flags;
690         
691         dbg("%s - port %d", __FUNCTION__, port->number);
692
693         spin_lock_irqsave(&priv->lock, flags);
694         control = priv->line_control;
695         status = priv->current_status;
696         spin_unlock_irqrestore(&priv->lock, flags);
697
698         result = ((control & CONTROL_DTR)        ? TIOCM_DTR : 0)
699                 | ((control & CONTROL_RTS)       ? TIOCM_RTS : 0)
700                 | ((status & UART_CTS)        ? TIOCM_CTS : 0)
701                 | ((status & UART_DSR)        ? TIOCM_DSR : 0)
702                 | ((status & UART_RI)         ? TIOCM_RI  : 0)
703                 | ((status & UART_CD)         ? TIOCM_CD  : 0);
704
705         dbg("%s - result = %x", __FUNCTION__, result);
706
707         return result;
708 }
709
710
711 static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
712                                unsigned int set, unsigned int clear)
713 {
714         struct cypress_private *priv = usb_get_serial_port_data(port);
715         unsigned long flags;
716         
717         dbg("%s - port %d", __FUNCTION__, port->number);
718
719         spin_lock_irqsave(&priv->lock, flags);
720         if (set & TIOCM_RTS)
721                 priv->line_control |= CONTROL_RTS;
722         if (set & TIOCM_DTR)
723                 priv->line_control |= CONTROL_DTR;
724         if (clear & TIOCM_RTS)
725                 priv->line_control &= ~CONTROL_RTS;
726         if (clear & TIOCM_DTR)
727                 priv->line_control &= ~CONTROL_DTR;
728         spin_unlock_irqrestore(&priv->lock, flags);
729
730         priv->cmd_ctrl = 1;
731         return cypress_write(port, NULL, 0);
732 }
733
734
735 static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
736 {
737         struct cypress_private *priv = usb_get_serial_port_data(port);
738
739         dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
740
741         switch (cmd) {
742                 case TIOCGSERIAL:
743                         if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {
744                                 return -EFAULT;
745                         }
746                         return (0);
747                         break;
748                 case TIOCSSERIAL:
749                         if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {
750                                 return -EFAULT;
751                         }
752                         /* here we need to call cypress_set_termios to invoke the new settings */
753                         cypress_set_termios(port, &priv->tmp_termios);
754                         return (0);
755                         break;
756                 /* these are called when setting baud rate from gpsd */
757                 case TCGETS:
758                         if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {
759                                 return -EFAULT;
760                         }
761                         return (0);
762                         break;
763                 case TCSETS:
764                         if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {
765                                 return -EFAULT;
766                         }
767                         /* here we need to call cypress_set_termios to invoke the new settings */
768                         cypress_set_termios(port, &priv->tmp_termios);
769                         return (0);
770                         break;
771                 /* This code comes from drivers/char/serial.c and ftdi_sio.c */
772                 case TIOCMIWAIT:
773                         while (priv != NULL) {
774                                 interruptible_sleep_on(&priv->delta_msr_wait);
775                                 /* see if a signal did it */
776                                 if (signal_pending(current))
777                                         return -ERESTARTSYS;
778                                 else {
779                                         char diff = priv->diff_status;
780
781                                         if (diff == 0) {
782                                                 return -EIO; /* no change => error */
783                                         }
784                                         
785                                         /* consume all events */
786                                         priv->diff_status = 0;
787
788                                         /* return 0 if caller wanted to know about these bits */
789                                         if ( ((arg & TIOCM_RNG) && (diff & UART_RI)) ||
790                                              ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
791                                              ((arg & TIOCM_CD) && (diff & UART_CD)) ||
792                                              ((arg & TIOCM_CTS) && (diff & UART_CTS)) ) {
793                                                 return 0;
794                                         }
795                                         /* otherwise caller can't care less about what happened,
796                                          * and so we continue to wait for more events.
797                                          */
798                                 }
799                         }
800                         return 0;
801                         break;
802                 default:
803                         break;
804         }
805
806         dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __FUNCTION__, cmd);
807
808         return -ENOIOCTLCMD;
809 } /* cypress_ioctl */
810
811
812 static void cypress_set_termios (struct usb_serial_port *port, struct termios *old_termios)
813 {
814         struct cypress_private *priv = usb_get_serial_port_data(port);
815         struct tty_struct *tty;
816         int data_bits, stop_bits, parity_type, parity_enable;
817         unsigned cflag, iflag, baud_mask;
818         unsigned long flags;
819         
820         dbg("%s - port %d", __FUNCTION__, port->number);
821
822         tty = port->tty;
823         if ((!tty) || (!tty->termios)) {
824                 dbg("%s - no tty structures", __FUNCTION__);
825                 return;
826         }
827
828         spin_lock_irqsave(&priv->lock, flags);
829         if (!priv->termios_initialized) {
830                 if (priv->chiptype == CT_EARTHMATE) {
831                         *(tty->termios) = tty_std_termios;
832                         tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL;
833                 } else if (priv->chiptype == CT_CYPHIDCOM) {
834                         *(tty->termios) = tty_std_termios;
835                         tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
836                 }
837                 priv->termios_initialized = 1;
838         }
839         spin_unlock_irqrestore(&priv->lock, flags);
840
841         cflag = tty->termios->c_cflag;
842         iflag = tty->termios->c_iflag;
843
844         /* check if there are new settings */
845         if (old_termios) {
846                 if ((cflag != old_termios->c_cflag) ||
847                     (RELEVANT_IFLAG(iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
848                         dbg("%s - attempting to set new termios settings", __FUNCTION__);
849                         /* should make a copy of this in case something goes wrong in the function, we can restore it */
850                         spin_lock_irqsave(&priv->lock, flags);
851                         priv->tmp_termios = *(tty->termios);
852                         spin_unlock_irqrestore(&priv->lock, flags); 
853                 } else {
854                         dbg("%s - nothing to do, exiting", __FUNCTION__);
855                         return;
856                 }
857         } else
858                 return;
859
860         /* set number of data bits, parity, stop bits */
861         /* when parity is disabled the parity type bit is ignored */
862
863         stop_bits = cflag & CSTOPB ? 1 : 0; /* 1 means 2 stop bits, 0 means 1 stop bit */
864         
865         if (cflag & PARENB) {
866                 parity_enable = 1;
867                 parity_type = cflag & PARODD ? 1 : 0; /* 1 means odd parity, 0 means even parity */
868         } else
869                 parity_enable = parity_type = 0;
870
871         if (cflag & CSIZE) {
872                 switch (cflag & CSIZE) {
873                         case CS5: data_bits = 0; break;
874                         case CS6: data_bits = 1; break;
875                         case CS7: data_bits = 2; break;
876                         case CS8: data_bits = 3; break;
877                         default: err("%s - CSIZE was set, but not CS5-CS8", __FUNCTION__); data_bits = 3;
878                 }
879         } else
880                 data_bits = 3;
881
882         spin_lock_irqsave(&priv->lock, flags);
883         if ((cflag & CBAUD) == B0) {
884                 /* drop dtr and rts */
885                 dbg("%s - dropping the lines, baud rate 0bps", __FUNCTION__);
886                 baud_mask = B0;
887                 priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
888         } else {
889                 baud_mask = (cflag & CBAUD);
890                 switch(baud_mask) {
891                         case B300: dbg("%s - setting baud 300bps", __FUNCTION__); break;
892                         case B600: dbg("%s - setting baud 600bps", __FUNCTION__); break;
893                         case B1200: dbg("%s - setting baud 1200bps", __FUNCTION__); break;
894                         case B2400: dbg("%s - setting baud 2400bps", __FUNCTION__); break;
895                         case B4800: dbg("%s - setting baud 4800bps", __FUNCTION__); break;
896                         case B9600: dbg("%s - setting baud 9600bps", __FUNCTION__); break;
897                         case B19200: dbg("%s - setting baud 19200bps", __FUNCTION__); break;
898                         case B38400: dbg("%s - setting baud 38400bps", __FUNCTION__); break;
899                         case B57600: dbg("%s - setting baud 57600bps", __FUNCTION__); break;
900                         case B115200: dbg("%s - setting baud 115200bps", __FUNCTION__); break;
901                         default: dbg("%s - unknown masked baud rate", __FUNCTION__);
902                 }
903                 priv->line_control |= CONTROL_DTR;
904                 
905                 /* this is probably not what I think it is... check into it */
906                 if (cflag & CRTSCTS)
907                         priv->line_control |= CONTROL_RTS;
908                 else
909                         priv->line_control &= ~CONTROL_RTS;
910         }
911         spin_unlock_irqrestore(&priv->lock, flags);
912         
913         dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, %d data_bits (+5)", __FUNCTION__,
914             stop_bits, parity_enable, parity_type, data_bits);
915
916         cypress_serial_control(port, baud_mask, data_bits, stop_bits, parity_enable,
917                                parity_type, 0, CYPRESS_SET_CONFIG);
918
919         set_current_state(TASK_INTERRUPTIBLE);
920         schedule_timeout(50*HZ/1000); /* give some time between change and read (50ms) */ 
921
922         /* we perform a CYPRESS_GET_CONFIG so that the current settings are filled into the private structure
923          * this should confirm that all is working if it returns what we just set */
924         cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
925
926         /* Here we can define custom tty settings for devices
927          *
928          * the main tty base comes from empeg.c
929          */
930
931         spin_lock_irqsave(&priv->lock, flags);  
932         if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) {
933
934                 dbg("Using custom termios settings for a baud rate of 4800bps.");
935                 /* define custom termios settings for NMEA protocol */
936
937                 
938                 tty->termios->c_iflag /* input modes - */
939                         &= ~(IGNBRK             /* disable ignore break */
940                         | BRKINT                /* disable break causes interrupt */
941                         | PARMRK                /* disable mark parity errors */
942                         | ISTRIP                /* disable clear high bit of input characters */
943                         | INLCR                 /* disable translate NL to CR */
944                         | IGNCR                 /* disable ignore CR */
945                         | ICRNL                 /* disable translate CR to NL */
946                         | IXON);                /* disable enable XON/XOFF flow control */
947                 
948                 tty->termios->c_oflag /* output modes */
949                         &= ~OPOST;              /* disable postprocess output characters */
950                 
951                 tty->termios->c_lflag /* line discipline modes */
952                         &= ~(ECHO               /* disable echo input characters */
953                         | ECHONL                /* disable echo new line */
954                         | ICANON                /* disable erase, kill, werase, and rprnt special characters */
955                         | ISIG                  /* disable interrupt, quit, and suspend special characters */
956                         | IEXTEN);              /* disable non-POSIX special characters */
957
958         } else if (priv->chiptype == CT_CYPHIDCOM) {
959
960                 // Software app handling it for device...       
961
962         } else {
963                 
964                 /* do something here */
965
966         }
967         spin_unlock_irqrestore(&priv->lock, flags);
968
969         /* set lines */
970         priv->cmd_ctrl = 1;
971         cypress_write(port, NULL, 0);
972         
973         return;
974 } /* cypress_set_termios */
975
976
977 static int cypress_chars_in_buffer(struct usb_serial_port *port)
978 {
979         dbg("%s - port %d", __FUNCTION__, port->number);
980
981         /*
982          * We can't really account for how much data we
983          * have sent out, but hasn't made it through to the
984          * device, so just tell the tty layer that everything
985          * is flushed.
986          */
987
988         return 0;
989 }
990
991
992 static void cypress_throttle (struct usb_serial_port *port)
993 {
994         struct cypress_private *priv = usb_get_serial_port_data(port);
995         unsigned long flags;
996
997         dbg("%s - port %d", __FUNCTION__, port->number);
998
999         spin_lock_irqsave(&priv->lock, flags);
1000         priv->rx_flags = THROTTLED;
1001         spin_unlock_irqrestore(&priv->lock, flags);        
1002 }
1003
1004
1005 static void cypress_unthrottle (struct usb_serial_port *port)
1006 {
1007         struct cypress_private *priv = usb_get_serial_port_data(port);
1008         int actually_throttled, result;
1009         unsigned long flags;
1010
1011         dbg("%s - port %d", __FUNCTION__, port->number);
1012
1013         spin_lock_irqsave(&priv->lock, flags);
1014         actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
1015         priv->rx_flags = 0;
1016         spin_unlock_irqrestore(&priv->lock, flags);
1017
1018         if (actually_throttled) {
1019                 port->interrupt_in_urb->dev = port->serial->dev;
1020
1021                 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
1022                 if (result)
1023                         dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
1024         }
1025 }
1026
1027
1028 static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
1029 {
1030         struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
1031         struct cypress_private *priv = usb_get_serial_port_data(port);
1032         struct tty_struct *tty;
1033         unsigned char *data = urb->transfer_buffer;
1034         unsigned long flags;
1035         char tty_flag = TTY_NORMAL;
1036         int bytes=0;
1037         int result;
1038         int i=0;
1039
1040         dbg("%s - port %d", __FUNCTION__, port->number);
1041
1042         if (urb->status) {
1043                 dbg("%s - nonzero read status received: %d", __FUNCTION__, urb->status);
1044                 return;
1045         }
1046
1047         spin_lock_irqsave(&priv->lock, flags);
1048         if (priv->rx_flags & THROTTLED) {
1049                 priv->rx_flags |= ACTUALLY_THROTTLED;
1050                 spin_unlock_irqrestore(&priv->lock, flags);
1051                 return;
1052         }
1053         spin_unlock_irqrestore(&priv->lock, flags);
1054
1055         tty = port->tty;
1056         if (!tty) {
1057                 dbg("%s - bad tty pointer - exiting", __FUNCTION__);
1058                 return;
1059         }
1060
1061         usb_serial_debug_data (debug, &port->dev, __FUNCTION__, urb->actual_length, data);
1062         
1063         spin_lock_irqsave(&priv->lock, flags);
1064         switch(urb->actual_length) {
1065                 case 32:
1066                         // This is for the CY7C64013...
1067                         priv->current_status = data[0] & 0xF8;
1068                         bytes = data[1]+2;
1069                         i=2;
1070                         break;
1071                 case 8:
1072                         // This is for the CY7C63743...
1073                         priv->current_status = data[0] & 0xF8;
1074                         bytes = (data[0] & 0x07)+1;
1075                         i=1;
1076                         break;
1077                 default:
1078                         dbg("%s - wrong packet size - received %d bytes", __FUNCTION__, urb->actual_length);
1079                         spin_unlock_irqrestore(&priv->lock, flags);
1080                         goto continue_read;
1081         }
1082         spin_unlock_irqrestore(&priv->lock, flags);
1083
1084         spin_lock_irqsave(&priv->lock, flags);
1085         /* check to see if status has changed */
1086         if (priv != NULL) {
1087                 if (priv->current_status != priv->prev_status) {
1088                         priv->diff_status |= priv->current_status ^ priv->prev_status;
1089                         wake_up_interruptible(&priv->delta_msr_wait);
1090                         priv->prev_status = priv->current_status;
1091                 }
1092         }
1093         spin_unlock_irqrestore(&priv->lock, flags);     
1094
1095         /* hangup, as defined in acm.c... this might be a bad place for it though */
1096         if (tty && !(tty->termios->c_cflag & CLOCAL) && !(priv->current_status & UART_CD)) {
1097                 dbg("%s - calling hangup", __FUNCTION__);
1098                 tty_hangup(tty);
1099                 goto continue_read;
1100         }
1101
1102         /* There is one error bit... I'm assuming it is a parity error indicator
1103          * as the generic firmware will set this bit to 1 if a parity error occurs.
1104          * I can not find reference to any other error events.
1105          *
1106          */
1107         spin_lock_irqsave(&priv->lock, flags);
1108         if (priv->current_status & CYP_ERROR) {
1109                 spin_unlock_irqrestore(&priv->lock, flags);
1110                 tty_flag = TTY_PARITY;
1111                 dbg("%s - Parity Error detected", __FUNCTION__);
1112         } else
1113                 spin_unlock_irqrestore(&priv->lock, flags);
1114
1115         /* process read if there is data other than line status */
1116         if (tty && (bytes > i)) {
1117                 for (; i < bytes ; ++i) {
1118                         dbg("pushing byte number %d - %d",i,data[i]);
1119                         if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
1120                                 tty_flip_buffer_push(tty);
1121                         }
1122                         tty_insert_flip_char(tty, data[i], tty_flag);
1123                 }
1124                 tty_flip_buffer_push(port->tty);
1125         }
1126
1127         spin_lock_irqsave(&priv->lock, flags);
1128         priv->bytes_in += bytes;  /* control and status byte(s) are also counted */
1129         spin_unlock_irqrestore(&priv->lock, flags);
1130
1131 continue_read:
1132         
1133         /* Continue trying to always read... unless the port has closed.  */
1134
1135         if (port->open_count > 0) {
1136         usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
1137                 usb_rcvintpipe(port->serial->dev, port->interrupt_in_endpointAddress),
1138                 port->interrupt_in_urb->transfer_buffer,
1139                 port->interrupt_in_urb->transfer_buffer_length,
1140                 cypress_read_int_callback, port,
1141                 port->interrupt_in_urb->interval);
1142         result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
1143         if (result)
1144                 dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
1145         }
1146         
1147         return;
1148 } /* cypress_read_int_callback */
1149
1150
1151 static void cypress_write_int_callback(struct urb *urb, struct pt_regs *regs)
1152 {
1153         struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
1154
1155         /* free up the transfer buffer, as usb_free_urb() does not do this */
1156         kfree (urb->transfer_buffer);
1157
1158         dbg("%s - port %d", __FUNCTION__, port->number);
1159         
1160         if (urb->status) {
1161                 dbg("%s - nonzero write status received: %d", __FUNCTION__, urb->status);
1162                 return;
1163         }
1164
1165         schedule_work(&port->work);
1166 }
1167
1168
1169 /*****************************************************************************
1170  * Module functions
1171  *****************************************************************************/
1172
1173 static int __init cypress_init(void)
1174 {
1175         int retval;
1176         
1177         dbg("%s", __FUNCTION__);
1178         
1179         retval = usb_serial_register(&cypress_earthmate_device);
1180         if (retval)
1181                 goto failed_em_register;
1182         retval = usb_serial_register(&cypress_hidcom_device);
1183         if (retval)
1184                 goto failed_hidcom_register;
1185         retval = usb_register(&cypress_driver);
1186         if (retval)
1187                 goto failed_usb_register;
1188
1189         info(DRIVER_DESC " " DRIVER_VERSION);
1190         return 0;
1191 failed_usb_register:
1192         usb_deregister(&cypress_driver);
1193 failed_hidcom_register:
1194         usb_serial_deregister(&cypress_hidcom_device);
1195 failed_em_register:
1196         usb_serial_deregister(&cypress_earthmate_device);
1197
1198         return retval;
1199 }
1200
1201
1202 static void __exit cypress_exit (void)
1203 {
1204         dbg("%s", __FUNCTION__);
1205
1206         usb_deregister (&cypress_driver);
1207         usb_serial_deregister (&cypress_earthmate_device);
1208         usb_serial_deregister (&cypress_hidcom_device);
1209 }
1210
1211
1212 module_init(cypress_init);
1213 module_exit(cypress_exit);
1214
1215 MODULE_AUTHOR( DRIVER_AUTHOR );
1216 MODULE_DESCRIPTION( DRIVER_DESC );
1217 MODULE_LICENSE("GPL");
1218
1219 module_param(debug, bool, S_IRUGO | S_IWUSR);
1220 MODULE_PARM_DESC(debug, "Debug enabled or not");
1221 module_param(stats, bool, S_IRUGO | S_IWUSR);
1222 MODULE_PARM_DESC(stats, "Enable statistics or not");