USB: mct_u232: add sanity checking in probe
[profile/mobile/platform/kernel/linux-3.10-sc7730.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
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/init.h>
27 #include <linux/slab.h>
28 #include <linux/tty.h>
29 #include <linux/tty_driver.h>
30 #include <linux/tty_flip.h>
31 #include <linux/module.h>
32 #include <linux/spinlock.h>
33 #include <linux/uaccess.h>
34 #include <asm/unaligned.h>
35 #include <linux/usb.h>
36 #include <linux/usb/serial.h>
37 #include <linux/serial.h>
38 #include "mct_u232.h"
39
40 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
41 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
42
43 /*
44  * Function prototypes
45  */
46 static int  mct_u232_port_probe(struct usb_serial_port *port);
47 static int  mct_u232_port_remove(struct usb_serial_port *remove);
48 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
49 static void mct_u232_close(struct usb_serial_port *port);
50 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
51 static void mct_u232_read_int_callback(struct urb *urb);
52 static void mct_u232_set_termios(struct tty_struct *tty,
53                         struct usb_serial_port *port, struct ktermios *old);
54 static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
55 static int  mct_u232_tiocmget(struct tty_struct *tty);
56 static int  mct_u232_tiocmset(struct tty_struct *tty,
57                         unsigned int set, unsigned int clear);
58 static void mct_u232_throttle(struct tty_struct *tty);
59 static void mct_u232_unthrottle(struct tty_struct *tty);
60
61
62 /*
63  * All of the device info needed for the MCT USB-RS232 converter.
64  */
65 static const struct usb_device_id id_table[] = {
66         { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
67         { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
68         { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
69         { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
70         { }             /* Terminating entry */
71 };
72 MODULE_DEVICE_TABLE(usb, id_table);
73
74 static struct usb_serial_driver mct_u232_device = {
75         .driver = {
76                 .owner =        THIS_MODULE,
77                 .name =         "mct_u232",
78         },
79         .description =       "MCT U232",
80         .id_table =          id_table,
81         .num_ports =         1,
82         .open =              mct_u232_open,
83         .close =             mct_u232_close,
84         .dtr_rts =           mct_u232_dtr_rts,
85         .throttle =          mct_u232_throttle,
86         .unthrottle =        mct_u232_unthrottle,
87         .read_int_callback = mct_u232_read_int_callback,
88         .set_termios =       mct_u232_set_termios,
89         .break_ctl =         mct_u232_break_ctl,
90         .tiocmget =          mct_u232_tiocmget,
91         .tiocmset =          mct_u232_tiocmset,
92         .tiocmiwait =        usb_serial_generic_tiocmiwait,
93         .port_probe =        mct_u232_port_probe,
94         .port_remove =       mct_u232_port_remove,
95         .get_icount =        usb_serial_generic_get_icount,
96 };
97
98 static struct usb_serial_driver * const serial_drivers[] = {
99         &mct_u232_device, NULL
100 };
101
102 struct mct_u232_private {
103         struct urb *read_urb;
104         spinlock_t lock;
105         unsigned int         control_state; /* Modem Line Setting (TIOCM) */
106         unsigned char        last_lcr;      /* Line Control Register */
107         unsigned char        last_lsr;      /* Line Status Register */
108         unsigned char        last_msr;      /* Modem Status Register */
109         unsigned int         rx_flags;      /* Throttling flags */
110 };
111
112 #define THROTTLED               0x01
113
114 /*
115  * Handle vendor specific USB requests
116  */
117
118 #define WDR_TIMEOUT 5000 /* default urb timeout */
119
120 /*
121  * Later day 2.6.0-test kernels have new baud rates like B230400 which
122  * we do not know how to support. We ignore them for the moment.
123  */
124 static int mct_u232_calculate_baud_rate(struct usb_serial *serial,
125                                         speed_t value, speed_t *result)
126 {
127         *result = value;
128
129         if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
130                 || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
131                 switch (value) {
132                 case 300:
133                         return 0x01;
134                 case 600:
135                         return 0x02; /* this one not tested */
136                 case 1200:
137                         return 0x03;
138                 case 2400:
139                         return 0x04;
140                 case 4800:
141                         return 0x06;
142                 case 9600:
143                         return 0x08;
144                 case 19200:
145                         return 0x09;
146                 case 38400:
147                         return 0x0a;
148                 case 57600:
149                         return 0x0b;
150                 case 115200:
151                         return 0x0c;
152                 default:
153                         *result = 9600;
154                         return 0x08;
155                 }
156         } else {
157                 /* FIXME: Can we use any divider - should we do
158                    divider = 115200/value;
159                    real baud = 115200/divider */
160                 switch (value) {
161                 case 300: break;
162                 case 600: break;
163                 case 1200: break;
164                 case 2400: break;
165                 case 4800: break;
166                 case 9600: break;
167                 case 19200: break;
168                 case 38400: break;
169                 case 57600: break;
170                 case 115200: break;
171                 default:
172                         value = 9600;
173                         *result = 9600;
174                 }
175                 return 115200/value;
176         }
177 }
178
179 static int mct_u232_set_baud_rate(struct tty_struct *tty,
180         struct usb_serial *serial, struct usb_serial_port *port, speed_t value)
181 {
182         unsigned int divisor;
183         int rc;
184         unsigned char *buf;
185         unsigned char cts_enable_byte = 0;
186         speed_t speed;
187
188         buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
189         if (buf == NULL)
190                 return -ENOMEM;
191
192         divisor = mct_u232_calculate_baud_rate(serial, value, &speed);
193         put_unaligned_le32(cpu_to_le32(divisor), buf);
194         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
195                                 MCT_U232_SET_BAUD_RATE_REQUEST,
196                                 MCT_U232_SET_REQUEST_TYPE,
197                                 0, 0, buf, MCT_U232_SET_BAUD_RATE_SIZE,
198                                 WDR_TIMEOUT);
199         if (rc < 0)     /*FIXME: What value speed results */
200                 dev_err(&port->dev, "Set BAUD RATE %d failed (error = %d)\n",
201                         value, rc);
202         else
203                 tty_encode_baud_rate(tty, speed, speed);
204         dev_dbg(&port->dev, "set_baud_rate: value: 0x%x, divisor: 0x%x\n", value, divisor);
205
206         /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
207            always sends two extra USB 'device request' messages after the
208            'baud rate change' message.  The actual functionality of the
209            request codes in these messages is not fully understood but these
210            particular codes are never seen in any operation besides a baud
211            rate change.  Both of these messages send a single byte of data.
212            In the first message, the value of this byte is always zero.
213
214            The second message has been determined experimentally to control
215            whether data will be transmitted to a device which is not asserting
216            the 'CTS' signal.  If the second message's data byte is zero, data
217            will be transmitted even if 'CTS' is not asserted (i.e. no hardware
218            flow control).  if the second message's data byte is nonzero (a
219            value of 1 is used by this driver), data will not be transmitted to
220            a device which is not asserting 'CTS'.
221         */
222
223         buf[0] = 0;
224         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
225                                 MCT_U232_SET_UNKNOWN1_REQUEST,
226                                 MCT_U232_SET_REQUEST_TYPE,
227                                 0, 0, buf, MCT_U232_SET_UNKNOWN1_SIZE,
228                                 WDR_TIMEOUT);
229         if (rc < 0)
230                 dev_err(&port->dev, "Sending USB device request code %d "
231                         "failed (error = %d)\n", MCT_U232_SET_UNKNOWN1_REQUEST,
232                         rc);
233
234         if (port && C_CRTSCTS(tty))
235            cts_enable_byte = 1;
236
237         dev_dbg(&port->dev, "set_baud_rate: send second control message, data = %02X\n",
238                 cts_enable_byte);
239         buf[0] = cts_enable_byte;
240         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
241                         MCT_U232_SET_CTS_REQUEST,
242                         MCT_U232_SET_REQUEST_TYPE,
243                         0, 0, buf, MCT_U232_SET_CTS_SIZE,
244                         WDR_TIMEOUT);
245         if (rc < 0)
246                 dev_err(&port->dev, "Sending USB device request code %d "
247                         "failed (error = %d)\n", MCT_U232_SET_CTS_REQUEST, rc);
248
249         kfree(buf);
250         return rc;
251 } /* mct_u232_set_baud_rate */
252
253 static int mct_u232_set_line_ctrl(struct usb_serial_port *port,
254                                   unsigned char lcr)
255 {
256         int rc;
257         unsigned char *buf;
258
259         buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
260         if (buf == NULL)
261                 return -ENOMEM;
262
263         buf[0] = lcr;
264         rc = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
265                         MCT_U232_SET_LINE_CTRL_REQUEST,
266                         MCT_U232_SET_REQUEST_TYPE,
267                         0, 0, buf, MCT_U232_SET_LINE_CTRL_SIZE,
268                         WDR_TIMEOUT);
269         if (rc < 0)
270                 dev_err(&port->dev, "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc);
271         dev_dbg(&port->dev, "set_line_ctrl: 0x%x\n", lcr);
272         kfree(buf);
273         return rc;
274 } /* mct_u232_set_line_ctrl */
275
276 static int mct_u232_set_modem_ctrl(struct usb_serial_port *port,
277                                    unsigned int control_state)
278 {
279         int rc;
280         unsigned char mcr;
281         unsigned char *buf;
282
283         buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
284         if (buf == NULL)
285                 return -ENOMEM;
286
287         mcr = MCT_U232_MCR_NONE;
288         if (control_state & TIOCM_DTR)
289                 mcr |= MCT_U232_MCR_DTR;
290         if (control_state & TIOCM_RTS)
291                 mcr |= MCT_U232_MCR_RTS;
292
293         buf[0] = mcr;
294         rc = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
295                         MCT_U232_SET_MODEM_CTRL_REQUEST,
296                         MCT_U232_SET_REQUEST_TYPE,
297                         0, 0, buf, MCT_U232_SET_MODEM_CTRL_SIZE,
298                         WDR_TIMEOUT);
299         kfree(buf);
300
301         dev_dbg(&port->dev, "set_modem_ctrl: state=0x%x ==> mcr=0x%x\n", control_state, mcr);
302
303         if (rc < 0) {
304                 dev_err(&port->dev, "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
305                 return rc;
306         }
307         return 0;
308 } /* mct_u232_set_modem_ctrl */
309
310 static int mct_u232_get_modem_stat(struct usb_serial_port *port,
311                                    unsigned char *msr)
312 {
313         int rc;
314         unsigned char *buf;
315
316         buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
317         if (buf == NULL) {
318                 *msr = 0;
319                 return -ENOMEM;
320         }
321         rc = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0),
322                         MCT_U232_GET_MODEM_STAT_REQUEST,
323                         MCT_U232_GET_REQUEST_TYPE,
324                         0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE,
325                         WDR_TIMEOUT);
326         if (rc < 0) {
327                 dev_err(&port->dev, "Get MODEM STATus failed (error = %d)\n", rc);
328                 *msr = 0;
329         } else {
330                 *msr = buf[0];
331         }
332         dev_dbg(&port->dev, "get_modem_stat: 0x%x\n", *msr);
333         kfree(buf);
334         return rc;
335 } /* mct_u232_get_modem_stat */
336
337 static void mct_u232_msr_to_icount(struct async_icount *icount,
338                                                 unsigned char msr)
339 {
340         /* Translate Control Line states */
341         if (msr & MCT_U232_MSR_DDSR)
342                 icount->dsr++;
343         if (msr & MCT_U232_MSR_DCTS)
344                 icount->cts++;
345         if (msr & MCT_U232_MSR_DRI)
346                 icount->rng++;
347         if (msr & MCT_U232_MSR_DCD)
348                 icount->dcd++;
349 } /* mct_u232_msr_to_icount */
350
351 static void mct_u232_msr_to_state(struct usb_serial_port *port,
352                                   unsigned int *control_state, unsigned char msr)
353 {
354         /* Translate Control Line states */
355         if (msr & MCT_U232_MSR_DSR)
356                 *control_state |=  TIOCM_DSR;
357         else
358                 *control_state &= ~TIOCM_DSR;
359         if (msr & MCT_U232_MSR_CTS)
360                 *control_state |=  TIOCM_CTS;
361         else
362                 *control_state &= ~TIOCM_CTS;
363         if (msr & MCT_U232_MSR_RI)
364                 *control_state |=  TIOCM_RI;
365         else
366                 *control_state &= ~TIOCM_RI;
367         if (msr & MCT_U232_MSR_CD)
368                 *control_state |=  TIOCM_CD;
369         else
370                 *control_state &= ~TIOCM_CD;
371         dev_dbg(&port->dev, "msr_to_state: msr=0x%x ==> state=0x%x\n", msr, *control_state);
372 } /* mct_u232_msr_to_state */
373
374 /*
375  * Driver's tty interface functions
376  */
377
378 static int mct_u232_port_probe(struct usb_serial_port *port)
379 {
380         struct usb_serial *serial = port->serial;
381         struct mct_u232_private *priv;
382
383         /* check first to simplify error handling */
384         if (!serial->port[1] || !serial->port[1]->interrupt_in_urb) {
385                 dev_err(&port->dev, "expected endpoint missing\n");
386                 return -ENODEV;
387         }
388
389         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
390         if (!priv)
391                 return -ENOMEM;
392
393         /* Use second interrupt-in endpoint for reading. */
394         priv->read_urb = serial->port[1]->interrupt_in_urb;
395         priv->read_urb->context = port;
396
397         spin_lock_init(&priv->lock);
398
399         usb_set_serial_port_data(port, priv);
400
401         return 0;
402 }
403
404 static int mct_u232_port_remove(struct usb_serial_port *port)
405 {
406         struct mct_u232_private *priv;
407
408         priv = usb_get_serial_port_data(port);
409         kfree(priv);
410
411         return 0;
412 }
413
414 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
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         /* Compensate for a hardware bug: although the Sitecom U232-P25
425          * device reports a maximum output packet size of 32 bytes,
426          * it seems to be able to accept only 16 bytes (and that's what
427          * SniffUSB says too...)
428          */
429         if (le16_to_cpu(serial->dev->descriptor.idProduct)
430                                                 == MCT_U232_SITECOM_PID)
431                 port->bulk_out_size = 16;
432
433         /* Do a defined restart: the normal serial device seems to
434          * always turn on DTR and RTS here, so do the same. I'm not
435          * sure if this is really necessary. But it should not harm
436          * either.
437          */
438         spin_lock_irqsave(&priv->lock, flags);
439         if (tty && (tty->termios.c_cflag & CBAUD))
440                 priv->control_state = TIOCM_DTR | TIOCM_RTS;
441         else
442                 priv->control_state = 0;
443
444         priv->last_lcr = (MCT_U232_DATA_BITS_8 |
445                           MCT_U232_PARITY_NONE |
446                           MCT_U232_STOP_BITS_1);
447         control_state = priv->control_state;
448         last_lcr = priv->last_lcr;
449         spin_unlock_irqrestore(&priv->lock, flags);
450         mct_u232_set_modem_ctrl(port, control_state);
451         mct_u232_set_line_ctrl(port, last_lcr);
452
453         /* Read modem status and update control state */
454         mct_u232_get_modem_stat(port, &last_msr);
455         spin_lock_irqsave(&priv->lock, flags);
456         priv->last_msr = last_msr;
457         mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
458         spin_unlock_irqrestore(&priv->lock, flags);
459
460         retval = usb_submit_urb(priv->read_urb, GFP_KERNEL);
461         if (retval) {
462                 dev_err(&port->dev,
463                         "usb_submit_urb(read) failed pipe 0x%x err %d\n",
464                         port->read_urb->pipe, retval);
465                 goto error;
466         }
467
468         retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
469         if (retval) {
470                 usb_kill_urb(priv->read_urb);
471                 dev_err(&port->dev,
472                         "usb_submit_urb(read int) failed pipe 0x%x err %d",
473                         port->interrupt_in_urb->pipe, retval);
474                 goto error;
475         }
476         return 0;
477
478 error:
479         return retval;
480 } /* mct_u232_open */
481
482 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
483 {
484         unsigned int control_state;
485         struct mct_u232_private *priv = usb_get_serial_port_data(port);
486
487         spin_lock_irq(&priv->lock);
488         if (on)
489                 priv->control_state |= TIOCM_DTR | TIOCM_RTS;
490         else
491                 priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
492         control_state = priv->control_state;
493         spin_unlock_irq(&priv->lock);
494
495         mct_u232_set_modem_ctrl(port, control_state);
496 }
497
498 static void mct_u232_close(struct usb_serial_port *port)
499 {
500         struct mct_u232_private *priv = usb_get_serial_port_data(port);
501
502         usb_kill_urb(priv->read_urb);
503         usb_kill_urb(port->interrupt_in_urb);
504
505         usb_serial_generic_close(port);
506 } /* mct_u232_close */
507
508
509 static void mct_u232_read_int_callback(struct urb *urb)
510 {
511         struct usb_serial_port *port = urb->context;
512         struct mct_u232_private *priv = usb_get_serial_port_data(port);
513         unsigned char *data = urb->transfer_buffer;
514         int retval;
515         int status = urb->status;
516         unsigned long flags;
517
518         switch (status) {
519         case 0:
520                 /* success */
521                 break;
522         case -ECONNRESET:
523         case -ENOENT:
524         case -ESHUTDOWN:
525                 /* this urb is terminated, clean up */
526                 dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
527                         __func__, status);
528                 return;
529         default:
530                 dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
531                         __func__, status);
532                 goto exit;
533         }
534
535         usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
536
537         /*
538          * Work-a-round: handle the 'usual' bulk-in pipe here
539          */
540         if (urb->transfer_buffer_length > 2) {
541                 if (urb->actual_length) {
542                         tty_insert_flip_string(&port->port, data,
543                                         urb->actual_length);
544                         tty_flip_buffer_push(&port->port);
545                 }
546                 goto exit;
547         }
548
549         /*
550          * The interrupt-in pipe signals exceptional conditions (modem line
551          * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
552          */
553         spin_lock_irqsave(&priv->lock, flags);
554         priv->last_msr = data[MCT_U232_MSR_INDEX];
555
556         /* Record Control Line states */
557         mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
558
559         mct_u232_msr_to_icount(&port->icount, priv->last_msr);
560
561 #if 0
562         /* Not yet handled. See belkin_sa.c for further information */
563         /* Now to report any errors */
564         priv->last_lsr = data[MCT_U232_LSR_INDEX];
565         /*
566          * fill in the flip buffer here, but I do not know the relation
567          * to the current/next receive buffer or characters.  I need
568          * to look in to this before committing any code.
569          */
570         if (priv->last_lsr & MCT_U232_LSR_ERR) {
571                 tty = tty_port_tty_get(&port->port);
572                 /* Overrun Error */
573                 if (priv->last_lsr & MCT_U232_LSR_OE) {
574                 }
575                 /* Parity Error */
576                 if (priv->last_lsr & MCT_U232_LSR_PE) {
577                 }
578                 /* Framing Error */
579                 if (priv->last_lsr & MCT_U232_LSR_FE) {
580                 }
581                 /* Break Indicator */
582                 if (priv->last_lsr & MCT_U232_LSR_BI) {
583                 }
584                 tty_kref_put(tty);
585         }
586 #endif
587         wake_up_interruptible(&port->port.delta_msr_wait);
588         spin_unlock_irqrestore(&priv->lock, flags);
589 exit:
590         retval = usb_submit_urb(urb, GFP_ATOMIC);
591         if (retval)
592                 dev_err(&port->dev,
593                         "%s - usb_submit_urb failed with result %d\n",
594                         __func__, retval);
595 } /* mct_u232_read_int_callback */
596
597 static void mct_u232_set_termios(struct tty_struct *tty,
598                                  struct usb_serial_port *port,
599                                  struct ktermios *old_termios)
600 {
601         struct usb_serial *serial = port->serial;
602         struct mct_u232_private *priv = usb_get_serial_port_data(port);
603         struct ktermios *termios = &tty->termios;
604         unsigned int cflag = termios->c_cflag;
605         unsigned int old_cflag = old_termios->c_cflag;
606         unsigned long flags;
607         unsigned int control_state;
608         unsigned char last_lcr;
609
610         /* get a local copy of the current port settings */
611         spin_lock_irqsave(&priv->lock, flags);
612         control_state = priv->control_state;
613         spin_unlock_irqrestore(&priv->lock, flags);
614         last_lcr = 0;
615
616         /*
617          * Update baud rate.
618          * Do not attempt to cache old rates and skip settings,
619          * disconnects screw such tricks up completely.
620          * Premature optimization is the root of all evil.
621          */
622
623         /* reassert DTR and RTS on transition from B0 */
624         if ((old_cflag & CBAUD) == B0) {
625                 dev_dbg(&port->dev, "%s: baud was B0\n", __func__);
626                 control_state |= TIOCM_DTR | TIOCM_RTS;
627                 mct_u232_set_modem_ctrl(port, control_state);
628         }
629
630         mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty));
631
632         if ((cflag & CBAUD) == B0) {
633                 dev_dbg(&port->dev, "%s: baud is B0\n", __func__);
634                 /* Drop RTS and DTR */
635                 control_state &= ~(TIOCM_DTR | TIOCM_RTS);
636                 mct_u232_set_modem_ctrl(port, control_state);
637         }
638
639         /*
640          * Update line control register (LCR)
641          */
642
643         /* set the parity */
644         if (cflag & PARENB)
645                 last_lcr |= (cflag & PARODD) ?
646                         MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
647         else
648                 last_lcr |= MCT_U232_PARITY_NONE;
649
650         /* set the number of data bits */
651         switch (cflag & CSIZE) {
652         case CS5:
653                 last_lcr |= MCT_U232_DATA_BITS_5; break;
654         case CS6:
655                 last_lcr |= MCT_U232_DATA_BITS_6; break;
656         case CS7:
657                 last_lcr |= MCT_U232_DATA_BITS_7; break;
658         case CS8:
659                 last_lcr |= MCT_U232_DATA_BITS_8; break;
660         default:
661                 dev_err(&port->dev,
662                         "CSIZE was not CS5-CS8, using default of 8\n");
663                 last_lcr |= MCT_U232_DATA_BITS_8;
664                 break;
665         }
666
667         termios->c_cflag &= ~CMSPAR;
668
669         /* set the number of stop bits */
670         last_lcr |= (cflag & CSTOPB) ?
671                 MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
672
673         mct_u232_set_line_ctrl(port, last_lcr);
674
675         /* save off the modified port settings */
676         spin_lock_irqsave(&priv->lock, flags);
677         priv->control_state = control_state;
678         priv->last_lcr = last_lcr;
679         spin_unlock_irqrestore(&priv->lock, flags);
680 } /* mct_u232_set_termios */
681
682 static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
683 {
684         struct usb_serial_port *port = tty->driver_data;
685         struct mct_u232_private *priv = usb_get_serial_port_data(port);
686         unsigned char lcr;
687         unsigned long flags;
688
689         spin_lock_irqsave(&priv->lock, flags);
690         lcr = priv->last_lcr;
691
692         if (break_state)
693                 lcr |= MCT_U232_SET_BREAK;
694         spin_unlock_irqrestore(&priv->lock, flags);
695
696         mct_u232_set_line_ctrl(port, lcr);
697 } /* mct_u232_break_ctl */
698
699
700 static int mct_u232_tiocmget(struct tty_struct *tty)
701 {
702         struct usb_serial_port *port = tty->driver_data;
703         struct mct_u232_private *priv = usb_get_serial_port_data(port);
704         unsigned int control_state;
705         unsigned long flags;
706
707         spin_lock_irqsave(&priv->lock, flags);
708         control_state = priv->control_state;
709         spin_unlock_irqrestore(&priv->lock, flags);
710
711         return control_state;
712 }
713
714 static int mct_u232_tiocmset(struct tty_struct *tty,
715                               unsigned int set, unsigned int clear)
716 {
717         struct usb_serial_port *port = tty->driver_data;
718         struct mct_u232_private *priv = usb_get_serial_port_data(port);
719         unsigned int control_state;
720         unsigned long flags;
721
722         spin_lock_irqsave(&priv->lock, flags);
723         control_state = priv->control_state;
724
725         if (set & TIOCM_RTS)
726                 control_state |= TIOCM_RTS;
727         if (set & TIOCM_DTR)
728                 control_state |= TIOCM_DTR;
729         if (clear & TIOCM_RTS)
730                 control_state &= ~TIOCM_RTS;
731         if (clear & TIOCM_DTR)
732                 control_state &= ~TIOCM_DTR;
733
734         priv->control_state = control_state;
735         spin_unlock_irqrestore(&priv->lock, flags);
736         return mct_u232_set_modem_ctrl(port, control_state);
737 }
738
739 static void mct_u232_throttle(struct tty_struct *tty)
740 {
741         struct usb_serial_port *port = tty->driver_data;
742         struct mct_u232_private *priv = usb_get_serial_port_data(port);
743         unsigned int control_state;
744
745         spin_lock_irq(&priv->lock);
746         priv->rx_flags |= THROTTLED;
747         if (C_CRTSCTS(tty)) {
748                 priv->control_state &= ~TIOCM_RTS;
749                 control_state = priv->control_state;
750                 spin_unlock_irq(&priv->lock);
751                 mct_u232_set_modem_ctrl(port, control_state);
752         } else {
753                 spin_unlock_irq(&priv->lock);
754         }
755 }
756
757 static void mct_u232_unthrottle(struct tty_struct *tty)
758 {
759         struct usb_serial_port *port = tty->driver_data;
760         struct mct_u232_private *priv = usb_get_serial_port_data(port);
761         unsigned int control_state;
762
763         spin_lock_irq(&priv->lock);
764         if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
765                 priv->rx_flags &= ~THROTTLED;
766                 priv->control_state |= TIOCM_RTS;
767                 control_state = priv->control_state;
768                 spin_unlock_irq(&priv->lock);
769                 mct_u232_set_modem_ctrl(port, control_state);
770         } else {
771                 spin_unlock_irq(&priv->lock);
772         }
773 }
774
775 module_usb_serial_driver(serial_drivers, id_table);
776
777 MODULE_AUTHOR(DRIVER_AUTHOR);
778 MODULE_DESCRIPTION(DRIVER_DESC);
779 MODULE_LICENSE("GPL");