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