5fc2cef30e39f76603421616b3e4a06c9cebd586
[pandora-kernel.git] / drivers / usb / serial / mct_u232.c
1 /*
2  * MCT (Magic Control Technology Corp.) USB RS232 Converter Driver
3  *
4  *   Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.ch)
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  * This program is largely derived from the Belkin USB Serial Adapter Driver
12  * (see belkin_sa.[ch]). All of the information about the device was acquired
13  * by using SniffUSB on Windows98. For technical details see mct_u232.h.
14  *
15  * William G. Greathouse and Greg Kroah-Hartman provided great help on how to
16  * do the reverse engineering and how to write a USB serial device driver.
17  *
18  * TO BE DONE, TO BE CHECKED:
19  *   DTR/RTS signal handling may be incomplete or incorrect. I have mainly
20  *   implemented what I have seen with SniffUSB or found in belkin_sa.c.
21  *   For further TODOs check also belkin_sa.c.
22  *
23  * TEST STATUS:
24  *   Basic tests have been performed with minicom/zmodem transfers and
25  *   modem dialing under Linux 2.4.0-test10 (for me it works fine).
26  *
27  * 04-Nov-2003 Bill Marr <marr at flex dot com>
28  *   - Mimic Windows driver by sending 2 USB 'device request' messages
29  *     following normal 'baud rate change' message.  This allows data to be
30  *     transmitted to RS-232 devices which don't assert the 'CTS' signal.
31  *
32  * 10-Nov-2001 Wolfgang Grandegger
33  *   - Fixed an endianess problem with the baudrate selection for PowerPC.
34  *
35  * 06-Dec-2001 Martin Hamilton <martinh@gnu.org>
36  *      Added support for the Belkin F5U109 DB9 adaptor
37  *
38  * 30-May-2001 Greg Kroah-Hartman
39  *      switched from using spinlock to a semaphore, which fixes lots of problems.
40  *
41  * 04-May-2001 Stelian Pop
42  *   - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes
43  *     instead of the device reported 32 (using 32 bytes causes many data
44  *     loss, Windows driver uses 16 too).
45  *
46  * 02-May-2001 Stelian Pop
47  *   - Fixed the baud calculation for Sitecom U232-P25 model
48  *
49  * 08-Apr-2001 gb
50  *   - Identify version on module load.
51  *
52  * 06-Jan-2001 Cornel Ciocirlan 
53  *   - Added support for Sitecom U232-P25 model (Product Id 0x0230)
54  *   - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
55  *
56  * 29-Nov-2000 Greg Kroah-Hartman
57  *   - Added device id table to fit with 2.4.0-test11 structure.
58  *   - took out DEAL_WITH_TWO_INT_IN_ENDPOINTS #define as it's not needed
59  *     (lots of things will change if/when the usb-serial core changes to
60  *     handle these issues.
61  *
62  * 27-Nov-2000 Wolfgang Grandegger
63  *   A version for kernel 2.4.0-test10 released to the Linux community 
64  *   (via linux-usb-devel).
65  */
66
67 #include <linux/kernel.h>
68 #include <linux/errno.h>
69 #include <linux/init.h>
70 #include <linux/slab.h>
71 #include <linux/tty.h>
72 #include <linux/tty_driver.h>
73 #include <linux/tty_flip.h>
74 #include <linux/module.h>
75 #include <linux/spinlock.h>
76 #include <asm/uaccess.h>
77 #include <linux/usb.h>
78 #include <linux/usb/serial.h>
79 #include "mct_u232.h"
80
81 /*
82  * Version Information
83  */
84 #define DRIVER_VERSION "z2.1"           /* Linux in-kernel version */
85 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
86 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
87
88 static int debug;
89
90 /*
91  * Function prototypes
92  */
93 static int  mct_u232_startup             (struct usb_serial *serial);
94 static void mct_u232_shutdown            (struct usb_serial *serial);
95 static int  mct_u232_open                (struct usb_serial_port *port,
96                                           struct file *filp);
97 static void mct_u232_close               (struct usb_serial_port *port,
98                                           struct file *filp);
99 static void mct_u232_read_int_callback   (struct urb *urb);
100 static void mct_u232_set_termios         (struct usb_serial_port *port,
101                                           struct ktermios * old);
102 static int  mct_u232_ioctl               (struct usb_serial_port *port,
103                                           struct file * file,
104                                           unsigned int cmd,
105                                           unsigned long arg);
106 static void mct_u232_break_ctl           (struct usb_serial_port *port,
107                                           int break_state );
108 static int  mct_u232_tiocmget            (struct usb_serial_port *port,
109                                           struct file *file);
110 static int  mct_u232_tiocmset            (struct usb_serial_port *port,
111                                           struct file *file, unsigned int set,
112                                           unsigned int clear);
113 static void mct_u232_throttle            (struct usb_serial_port *port);
114 static void mct_u232_unthrottle          (struct usb_serial_port *port);
115
116
117 /*
118  * All of the device info needed for the MCT USB-RS232 converter.
119  */
120 static struct usb_device_id id_table_combined [] = {
121         { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
122         { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
123         { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
124         { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
125         { }             /* Terminating entry */
126 };
127
128 MODULE_DEVICE_TABLE (usb, id_table_combined);
129
130 static struct usb_driver mct_u232_driver = {
131         .name =         "mct_u232",
132         .probe =        usb_serial_probe,
133         .disconnect =   usb_serial_disconnect,
134         .id_table =     id_table_combined,
135         .no_dynamic_id =        1,
136 };
137
138 static struct usb_serial_driver mct_u232_device = {
139         .driver = {
140                 .owner =        THIS_MODULE,
141                 .name =         "mct_u232",
142         },
143         .description =       "MCT U232",
144         .usb_driver =        &mct_u232_driver,
145         .id_table =          id_table_combined,
146         .num_ports =         1,
147         .open =              mct_u232_open,
148         .close =             mct_u232_close,
149         .throttle =          mct_u232_throttle,
150         .unthrottle =        mct_u232_unthrottle,
151         .read_int_callback = mct_u232_read_int_callback,
152         .ioctl =             mct_u232_ioctl,
153         .set_termios =       mct_u232_set_termios,
154         .break_ctl =         mct_u232_break_ctl,
155         .tiocmget =          mct_u232_tiocmget,
156         .tiocmset =          mct_u232_tiocmset,
157         .attach =            mct_u232_startup,
158         .shutdown =          mct_u232_shutdown,
159 };
160
161
162 struct mct_u232_private {
163         spinlock_t lock;
164         unsigned int         control_state; /* Modem Line Setting (TIOCM) */
165         unsigned char        last_lcr;      /* Line Control Register */
166         unsigned char        last_lsr;      /* Line Status Register */
167         unsigned char        last_msr;      /* Modem Status Register */
168         unsigned int         rx_flags;      /* Throttling flags */
169 };
170
171 #define THROTTLED               0x01
172
173 /*
174  * Handle vendor specific USB requests
175  */
176
177 #define WDR_TIMEOUT 5000 /* default urb timeout */
178
179 /*
180  * Later day 2.6.0-test kernels have new baud rates like B230400 which
181  * we do not know how to support. We ignore them for the moment.
182  */
183 static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value, speed_t *result)
184 {
185         *result = value;
186
187         if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
188           || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
189                 switch (value) {
190                 case    300: return 0x01;
191                 case    600: return 0x02; /* this one not tested */
192                 case   1200: return 0x03;
193                 case   2400: return 0x04;
194                 case   4800: return 0x06;
195                 case   9600: return 0x08;
196                 case  19200: return 0x09;
197                 case  38400: return 0x0a;
198                 case  57600: return 0x0b;
199                 case 115200: return 0x0c;
200                 default:
201                         *result = 9600;
202                         return 0x08;
203                 }
204         } else {
205                 /* FIXME: Can we use any divider - should we do
206                    divider = 115200/value;
207                    real baud = 115200/divider */
208                 switch (value) {
209                 case 300: break;
210                 case 600: break;
211                 case 1200: break;
212                 case 2400: break;
213                 case 4800: break;
214                 case 9600: break;
215                 case 19200: break;
216                 case 38400: break;
217                 case 57600: break;
218                 case 115200: break;
219                 default:
220                         value = 9600;
221                         *result = 9600;
222                 }
223                 return 115200/value;
224         }
225 }
226
227 static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port,
228                                   speed_t value)
229 {
230         __le32 divisor;
231         int rc;
232         unsigned char zero_byte = 0;
233         unsigned char cts_enable_byte = 0;
234         speed_t speed;
235
236         divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, &speed));
237
238         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
239                              MCT_U232_SET_BAUD_RATE_REQUEST,
240                              MCT_U232_SET_REQUEST_TYPE,
241                              0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
242                              WDR_TIMEOUT);
243         if (rc < 0)     /*FIXME: What value speed results */
244                 err("Set BAUD RATE %d failed (error = %d)", value, rc);
245         else
246                 tty_encode_baud_rate(port->tty, speed, speed);
247         dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
248
249         /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
250            always sends two extra USB 'device request' messages after the
251            'baud rate change' message.  The actual functionality of the
252            request codes in these messages is not fully understood but these
253            particular codes are never seen in any operation besides a baud
254            rate change.  Both of these messages send a single byte of data.
255            In the first message, the value of this byte is always zero.
256
257            The second message has been determined experimentally to control
258            whether data will be transmitted to a device which is not asserting
259            the 'CTS' signal.  If the second message's data byte is zero, data
260            will be transmitted even if 'CTS' is not asserted (i.e. no hardware
261            flow control).  if the second message's data byte is nonzero (a value
262            of 1 is used by this driver), data will not be transmitted to a device
263            which is not asserting 'CTS'.
264         */
265
266         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
267                              MCT_U232_SET_UNKNOWN1_REQUEST, 
268                              MCT_U232_SET_REQUEST_TYPE,
269                              0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE, 
270                              WDR_TIMEOUT);
271         if (rc < 0)
272                 err("Sending USB device request code %d failed (error = %d)", 
273                     MCT_U232_SET_UNKNOWN1_REQUEST, rc);
274
275         if (port && C_CRTSCTS(port->tty)) {
276            cts_enable_byte = 1;
277         }
278
279         dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte);
280         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
281                              MCT_U232_SET_CTS_REQUEST,
282                              MCT_U232_SET_REQUEST_TYPE,
283                              0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
284                              WDR_TIMEOUT);
285         if (rc < 0)
286           err("Sending USB device request code %d failed (error = %d)",
287               MCT_U232_SET_CTS_REQUEST, rc);
288
289         return rc;
290 } /* mct_u232_set_baud_rate */
291
292 static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
293 {
294         int rc;
295         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
296                              MCT_U232_SET_LINE_CTRL_REQUEST,
297                              MCT_U232_SET_REQUEST_TYPE,
298                              0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
299                              WDR_TIMEOUT);
300         if (rc < 0)
301                 err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
302         dbg("set_line_ctrl: 0x%x", lcr);
303         return rc;
304 } /* mct_u232_set_line_ctrl */
305
306 static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
307                                    unsigned int control_state)
308 {
309         int rc;
310         unsigned char mcr = MCT_U232_MCR_NONE;
311
312         if (control_state & TIOCM_DTR)
313                 mcr |= MCT_U232_MCR_DTR;
314         if (control_state & TIOCM_RTS)
315                 mcr |= MCT_U232_MCR_RTS;
316
317         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
318                              MCT_U232_SET_MODEM_CTRL_REQUEST,
319                              MCT_U232_SET_REQUEST_TYPE,
320                              0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
321                              WDR_TIMEOUT);
322         if (rc < 0)
323                 err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
324         dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
325
326         return rc;
327 } /* mct_u232_set_modem_ctrl */
328
329 static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
330 {
331         int rc;
332         rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
333                              MCT_U232_GET_MODEM_STAT_REQUEST,
334                              MCT_U232_GET_REQUEST_TYPE,
335                              0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
336                              WDR_TIMEOUT);
337         if (rc < 0) {
338                 err("Get MODEM STATus failed (error = %d)", rc);
339                 *msr = 0;
340         }
341         dbg("get_modem_stat: 0x%x", *msr);
342         return rc;
343 } /* mct_u232_get_modem_stat */
344
345 static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr)
346 {
347         /* Translate Control Line states */
348         if (msr & MCT_U232_MSR_DSR)
349                 *control_state |=  TIOCM_DSR;
350         else
351                 *control_state &= ~TIOCM_DSR;
352         if (msr & MCT_U232_MSR_CTS)
353                 *control_state |=  TIOCM_CTS;
354         else
355                 *control_state &= ~TIOCM_CTS;
356         if (msr & MCT_U232_MSR_RI)
357                 *control_state |=  TIOCM_RI;
358         else
359                 *control_state &= ~TIOCM_RI;
360         if (msr & MCT_U232_MSR_CD)
361                 *control_state |=  TIOCM_CD;
362         else
363                 *control_state &= ~TIOCM_CD;
364         dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
365 } /* mct_u232_msr_to_state */
366
367 /*
368  * Driver's tty interface functions
369  */
370
371 static int mct_u232_startup (struct usb_serial *serial)
372 {
373         struct mct_u232_private *priv;
374         struct usb_serial_port *port, *rport;
375
376         priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
377         if (!priv)
378                 return -ENOMEM;
379         spin_lock_init(&priv->lock);
380         usb_set_serial_port_data(serial->port[0], priv);
381
382         init_waitqueue_head(&serial->port[0]->write_wait);
383
384         /* Puh, that's dirty */
385         port = serial->port[0];
386         rport = serial->port[1];
387         /* No unlinking, it wasn't submitted yet. */
388         usb_free_urb(port->read_urb);
389         port->read_urb = rport->interrupt_in_urb;
390         rport->interrupt_in_urb = NULL;
391         port->read_urb->context = port;
392
393         return (0);
394 } /* mct_u232_startup */
395
396
397 static void mct_u232_shutdown (struct usb_serial *serial)
398 {
399         struct mct_u232_private *priv;
400         int i;
401         
402         dbg("%s", __func__);
403
404         for (i=0; i < serial->num_ports; ++i) {
405                 /* My special items, the standard routines free my urbs */
406                 priv = usb_get_serial_port_data(serial->port[i]);
407                 if (priv) {
408                         usb_set_serial_port_data(serial->port[i], NULL);
409                         kfree(priv);
410                 }
411         }
412 } /* mct_u232_shutdown */
413
414 static int  mct_u232_open (struct usb_serial_port *port, struct file *filp)
415 {
416         struct usb_serial *serial = port->serial;
417         struct mct_u232_private *priv = usb_get_serial_port_data(port);
418         int retval = 0;
419         unsigned int control_state;
420         unsigned long flags;
421         unsigned char last_lcr;
422         unsigned char last_msr;
423
424         dbg("%s port %d", __func__, port->number);
425
426         /* Compensate for a hardware bug: although the Sitecom U232-P25
427          * device reports a maximum output packet size of 32 bytes,
428          * it seems to be able to accept only 16 bytes (and that's what
429          * SniffUSB says too...)
430          */
431         if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID)
432                 port->bulk_out_size = 16;
433
434         /* Do a defined restart: the normal serial device seems to 
435          * always turn on DTR and RTS here, so do the same. I'm not
436          * sure if this is really necessary. But it should not harm
437          * either.
438          */
439         spin_lock_irqsave(&priv->lock, flags);
440         if (port->tty->termios->c_cflag & CBAUD)
441                 priv->control_state = TIOCM_DTR | TIOCM_RTS;
442         else
443                 priv->control_state = 0;
444         
445         priv->last_lcr = (MCT_U232_DATA_BITS_8 | 
446                           MCT_U232_PARITY_NONE |
447                           MCT_U232_STOP_BITS_1);
448         control_state = priv->control_state;
449         last_lcr = priv->last_lcr;
450         spin_unlock_irqrestore(&priv->lock, flags);
451         mct_u232_set_modem_ctrl(serial, control_state);
452         mct_u232_set_line_ctrl(serial, last_lcr);
453
454         /* Read modem status and update control state */
455         mct_u232_get_modem_stat(serial, &last_msr);
456         spin_lock_irqsave(&priv->lock, flags);
457         priv->last_msr = last_msr;
458         mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
459         spin_unlock_irqrestore(&priv->lock, flags);
460
461         port->read_urb->dev = port->serial->dev;
462         retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
463         if (retval) {
464                 err("usb_submit_urb(read bulk) failed pipe 0x%x err %d",
465                     port->read_urb->pipe, retval);
466                 goto error;
467         }
468
469         port->interrupt_in_urb->dev = port->serial->dev;
470         retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
471         if (retval) {
472                 usb_kill_urb(port->read_urb);
473                 err(" usb_submit_urb(read int) failed pipe 0x%x err %d",
474                     port->interrupt_in_urb->pipe, retval);
475                 goto error;
476         }
477         return 0;
478
479 error:
480         return retval;
481 } /* mct_u232_open */
482
483
484 static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
485 {
486         unsigned int c_cflag;
487         unsigned int control_state;
488         struct mct_u232_private *priv = usb_get_serial_port_data(port);
489         dbg("%s port %d", __func__, port->number);
490
491         if (port->tty) {
492                 c_cflag = port->tty->termios->c_cflag;
493                 mutex_lock(&port->serial->disc_mutex);
494                 if (c_cflag & HUPCL && !port->serial->disconnected) {
495                         /* drop DTR and RTS */
496                         spin_lock_irq(&priv->lock);
497                         priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
498                         control_state = priv->control_state;
499                         spin_unlock_irq(&priv->lock);
500                         mct_u232_set_modem_ctrl(port->serial, control_state);
501                 }
502                 mutex_unlock(&port->serial->disc_mutex);
503         }
504
505
506         if (port->serial->dev) {
507                 /* shutdown our urbs */
508                 usb_kill_urb(port->write_urb);
509                 usb_kill_urb(port->read_urb);
510                 usb_kill_urb(port->interrupt_in_urb);
511         }
512 } /* mct_u232_close */
513
514
515 static void mct_u232_read_int_callback (struct urb *urb)
516 {
517         struct usb_serial_port *port = urb->context;
518         struct mct_u232_private *priv = usb_get_serial_port_data(port);
519         struct usb_serial *serial = port->serial;
520         struct tty_struct *tty;
521         unsigned char *data = urb->transfer_buffer;
522         int retval;
523         int status = urb->status;
524         unsigned long flags;
525
526         switch (status) {
527         case 0:
528                 /* success */
529                 break;
530         case -ECONNRESET:
531         case -ENOENT:
532         case -ESHUTDOWN:
533                 /* this urb is terminated, clean up */
534                 dbg("%s - urb shutting down with status: %d",
535                     __func__, status);
536                 return;
537         default:
538                 dbg("%s - nonzero urb status received: %d",
539                     __func__, status);
540                 goto exit;
541         }
542
543         if (!serial) {
544                 dbg("%s - bad serial pointer, exiting", __func__);
545                 return;
546         }
547
548         dbg("%s - port %d", __func__, port->number);
549         usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
550
551         /*
552          * Work-a-round: handle the 'usual' bulk-in pipe here
553          */
554         if (urb->transfer_buffer_length > 2) {
555                 int i;
556                 tty = port->tty;
557                 if (urb->actual_length) {
558                         for (i = 0; i < urb->actual_length ; ++i) {
559                                 tty_insert_flip_char(tty, data[i], 0);
560                         }
561                         tty_flip_buffer_push(tty);
562                 }
563                 goto exit;
564         }
565         
566         /*
567          * The interrupt-in pipe signals exceptional conditions (modem line
568          * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
569          */
570         spin_lock_irqsave(&priv->lock, flags);
571         priv->last_msr = data[MCT_U232_MSR_INDEX];
572         
573         /* Record Control Line states */
574         mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
575
576 #if 0
577         /* Not yet handled. See belin_sa.c for further information */
578         /* Now to report any errors */
579         priv->last_lsr = data[MCT_U232_LSR_INDEX];
580         /*
581          * fill in the flip buffer here, but I do not know the relation
582          * to the current/next receive buffer or characters.  I need
583          * to look in to this before committing any code.
584          */
585         if (priv->last_lsr & MCT_U232_LSR_ERR) {
586                 tty = port->tty;
587                 /* Overrun Error */
588                 if (priv->last_lsr & MCT_U232_LSR_OE) {
589                 }
590                 /* Parity Error */
591                 if (priv->last_lsr & MCT_U232_LSR_PE) {
592                 }
593                 /* Framing Error */
594                 if (priv->last_lsr & MCT_U232_LSR_FE) {
595                 }
596                 /* Break Indicator */
597                 if (priv->last_lsr & MCT_U232_LSR_BI) {
598                 }
599         }
600 #endif
601         spin_unlock_irqrestore(&priv->lock, flags);
602 exit:
603         retval = usb_submit_urb (urb, GFP_ATOMIC);
604         if (retval)
605                 err ("%s - usb_submit_urb failed with result %d",
606                      __func__, retval);
607 } /* mct_u232_read_int_callback */
608
609 static void mct_u232_set_termios (struct usb_serial_port *port,
610                                   struct ktermios *old_termios)
611 {
612         struct usb_serial *serial = port->serial;
613         struct mct_u232_private *priv = usb_get_serial_port_data(port);
614         struct ktermios *termios = port->tty->termios;
615         unsigned int cflag = termios->c_cflag;
616         unsigned int old_cflag = old_termios->c_cflag;
617         unsigned long flags;
618         unsigned int control_state;
619         unsigned char last_lcr;
620
621         /* get a local copy of the current port settings */
622         spin_lock_irqsave(&priv->lock, flags);
623         control_state = priv->control_state;
624         spin_unlock_irqrestore(&priv->lock, flags);
625         last_lcr = 0;
626
627         /*
628          * Update baud rate.
629          * Do not attempt to cache old rates and skip settings,
630          * disconnects screw such tricks up completely.
631          * Premature optimization is the root of all evil.
632          */
633
634         /* reassert DTR and RTS on transition from B0 */
635         if ((old_cflag & CBAUD) == B0) {
636                 dbg("%s: baud was B0", __func__);
637                 control_state |= TIOCM_DTR | TIOCM_RTS;
638                 mct_u232_set_modem_ctrl(serial, control_state);
639         }
640
641         mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty));
642
643         if ((cflag & CBAUD) == B0 ) {
644                 dbg("%s: baud is B0", __func__);
645                 /* Drop RTS and DTR */
646                 control_state &= ~(TIOCM_DTR | TIOCM_RTS);
647                 mct_u232_set_modem_ctrl(serial, control_state);
648         }
649
650         /*
651          * Update line control register (LCR)
652          */
653
654         /* set the parity */
655         if (cflag & PARENB)
656                 last_lcr |= (cflag & PARODD) ?
657                         MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
658         else
659                 last_lcr |= MCT_U232_PARITY_NONE;
660
661         /* set the number of data bits */
662         switch (cflag & CSIZE) {
663         case CS5:
664                 last_lcr |= MCT_U232_DATA_BITS_5; break;
665         case CS6:
666                 last_lcr |= MCT_U232_DATA_BITS_6; break;
667         case CS7:
668                 last_lcr |= MCT_U232_DATA_BITS_7; break;
669         case CS8:
670                 last_lcr |= MCT_U232_DATA_BITS_8; break;
671         default:
672                 err("CSIZE was not CS5-CS8, using default of 8");
673                 last_lcr |= MCT_U232_DATA_BITS_8;
674                 break;
675         }
676
677         termios->c_cflag &= ~CMSPAR;
678
679         /* set the number of stop bits */
680         last_lcr |= (cflag & CSTOPB) ?
681                 MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
682
683         mct_u232_set_line_ctrl(serial, last_lcr);
684
685         /* save off the modified port settings */
686         spin_lock_irqsave(&priv->lock, flags);
687         priv->control_state = control_state;
688         priv->last_lcr = last_lcr;
689         spin_unlock_irqrestore(&priv->lock, flags);
690 } /* mct_u232_set_termios */
691
692 static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
693 {
694         struct usb_serial *serial = port->serial;
695         struct mct_u232_private *priv = usb_get_serial_port_data(port);
696         unsigned char lcr;
697         unsigned long flags;
698
699         dbg("%sstate=%d", __func__, break_state);
700
701         spin_lock_irqsave(&priv->lock, flags);
702         lcr = priv->last_lcr;
703         spin_unlock_irqrestore(&priv->lock, flags);
704
705         if (break_state)
706                 lcr |= MCT_U232_SET_BREAK;
707
708         mct_u232_set_line_ctrl(serial, lcr);
709 } /* mct_u232_break_ctl */
710
711
712 static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
713 {
714         struct mct_u232_private *priv = usb_get_serial_port_data(port);
715         unsigned int control_state;
716         unsigned long flags;
717         
718         dbg("%s", __func__);
719
720         spin_lock_irqsave(&priv->lock, flags);
721         control_state = priv->control_state;
722         spin_unlock_irqrestore(&priv->lock, flags);
723
724         return control_state;
725 }
726
727 static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
728                               unsigned int set, unsigned int clear)
729 {
730         struct usb_serial *serial = port->serial;
731         struct mct_u232_private *priv = usb_get_serial_port_data(port);
732         unsigned int control_state;
733         unsigned long flags;
734         
735         dbg("%s", __func__);
736
737         spin_lock_irqsave(&priv->lock, flags);
738         control_state = priv->control_state;
739
740         if (set & TIOCM_RTS)
741                 control_state |= TIOCM_RTS;
742         if (set & TIOCM_DTR)
743                 control_state |= TIOCM_DTR;
744         if (clear & TIOCM_RTS)
745                 control_state &= ~TIOCM_RTS;
746         if (clear & TIOCM_DTR)
747                 control_state &= ~TIOCM_DTR;
748
749         priv->control_state = control_state;
750         spin_unlock_irqrestore(&priv->lock, flags);
751         return mct_u232_set_modem_ctrl(serial, control_state);
752 }
753
754 static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
755                            unsigned int cmd, unsigned long arg)
756 {
757         dbg("%scmd=0x%x", __func__, cmd);
758
759         /* Based on code from acm.c and others */
760         switch (cmd) {
761         case TIOCMIWAIT:
762                 /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
763                 /* TODO */
764                 return( 0 );
765
766         case TIOCGICOUNT:
767                 /* return count of modemline transitions */
768                 /* TODO */
769                 return 0;
770
771         default:
772                 dbg("%s: arg not supported - 0x%04x", __func__,cmd);
773                 return(-ENOIOCTLCMD);
774                 break;
775         }
776         return 0;
777 } /* mct_u232_ioctl */
778
779 static void mct_u232_throttle (struct usb_serial_port *port)
780 {
781         struct mct_u232_private *priv = usb_get_serial_port_data(port);
782         unsigned long flags;
783         unsigned int control_state;
784         struct tty_struct *tty;
785
786         tty = port->tty;
787         dbg("%s - port %d", __func__, port->number);
788
789         spin_lock_irqsave(&priv->lock, flags);
790         priv->rx_flags |= THROTTLED;
791         if (C_CRTSCTS(tty)) {
792           priv->control_state &= ~TIOCM_RTS;
793           control_state = priv->control_state;
794           spin_unlock_irqrestore(&priv->lock, flags);
795           (void) mct_u232_set_modem_ctrl(port->serial, control_state);
796         } else {
797           spin_unlock_irqrestore(&priv->lock, flags);
798         }
799 }
800
801
802 static void mct_u232_unthrottle (struct usb_serial_port *port)
803 {
804         struct mct_u232_private *priv = usb_get_serial_port_data(port);
805         unsigned long flags;
806         unsigned int control_state;
807         struct tty_struct *tty;
808
809         dbg("%s - port %d", __func__, port->number);
810
811         tty = port->tty;
812         spin_lock_irqsave(&priv->lock, flags);
813         if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
814           priv->rx_flags &= ~THROTTLED;
815           priv->control_state |= TIOCM_RTS;
816           control_state = priv->control_state;
817           spin_unlock_irqrestore(&priv->lock, flags);
818           (void) mct_u232_set_modem_ctrl(port->serial, control_state);
819         } else {
820           spin_unlock_irqrestore(&priv->lock, flags);
821         }
822 }
823
824 static int __init mct_u232_init (void)
825 {
826         int retval;
827         retval = usb_serial_register(&mct_u232_device);
828         if (retval)
829                 goto failed_usb_serial_register;
830         retval = usb_register(&mct_u232_driver);
831         if (retval)
832                 goto failed_usb_register;
833         info(DRIVER_DESC " " DRIVER_VERSION);
834         return 0;
835 failed_usb_register:
836         usb_serial_deregister(&mct_u232_device);
837 failed_usb_serial_register:
838         return retval;
839 }
840
841
842 static void __exit mct_u232_exit (void)
843 {
844         usb_deregister (&mct_u232_driver);
845         usb_serial_deregister (&mct_u232_device);
846 }
847
848
849 module_init (mct_u232_init);
850 module_exit(mct_u232_exit);
851
852 MODULE_AUTHOR( DRIVER_AUTHOR );
853 MODULE_DESCRIPTION( DRIVER_DESC );
854 MODULE_LICENSE("GPL");
855
856 module_param(debug, bool, S_IRUGO | S_IWUSR);
857 MODULE_PARM_DESC(debug, "Debug enabled or not");