Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/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(cpu_to_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 < 0) {
326                 dev_err(&port->dev, "Get MODEM STATus failed (error = %d)\n", rc);
327                 *msr = 0;
328         } else {
329                 *msr = buf[0];
330         }
331         dev_dbg(&port->dev, "get_modem_stat: 0x%x\n", *msr);
332         kfree(buf);
333         return rc;
334 } /* mct_u232_get_modem_stat */
335 
336 static void mct_u232_msr_to_icount(struct async_icount *icount,
337                                                 unsigned char msr)
338 {
339         /* Translate Control Line states */
340         if (msr & MCT_U232_MSR_DDSR)
341                 icount->dsr++;
342         if (msr & MCT_U232_MSR_DCTS)
343                 icount->cts++;
344         if (msr & MCT_U232_MSR_DRI)
345                 icount->rng++;
346         if (msr & MCT_U232_MSR_DCD)
347                 icount->dcd++;
348 } /* mct_u232_msr_to_icount */
349 
350 static void mct_u232_msr_to_state(struct usb_serial_port *port,
351                                   unsigned int *control_state, unsigned char msr)
352 {
353         /* Translate Control Line states */
354         if (msr & MCT_U232_MSR_DSR)
355                 *control_state |=  TIOCM_DSR;
356         else
357                 *control_state &= ~TIOCM_DSR;
358         if (msr & MCT_U232_MSR_CTS)
359                 *control_state |=  TIOCM_CTS;
360         else
361                 *control_state &= ~TIOCM_CTS;
362         if (msr & MCT_U232_MSR_RI)
363                 *control_state |=  TIOCM_RI;
364         else
365                 *control_state &= ~TIOCM_RI;
366         if (msr & MCT_U232_MSR_CD)
367                 *control_state |=  TIOCM_CD;
368         else
369                 *control_state &= ~TIOCM_CD;
370         dev_dbg(&port->dev, "msr_to_state: msr=0x%x ==> state=0x%x\n", msr, *control_state);
371 } /* mct_u232_msr_to_state */
372 
373 /*
374  * Driver's tty interface functions
375  */
376 
377 static int mct_u232_port_probe(struct usb_serial_port *port)
378 {
379         struct mct_u232_private *priv;
380 
381         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
382         if (!priv)
383                 return -ENOMEM;
384 
385         /* Use second interrupt-in endpoint for reading. */
386         priv->read_urb = port->serial->port[1]->interrupt_in_urb;
387         priv->read_urb->context = port;
388 
389         spin_lock_init(&priv->lock);
390 
391         usb_set_serial_port_data(port, priv);
392 
393         return 0;
394 }
395 
396 static int mct_u232_port_remove(struct usb_serial_port *port)
397 {
398         struct mct_u232_private *priv;
399 
400         priv = usb_get_serial_port_data(port);
401         kfree(priv);
402 
403         return 0;
404 }
405 
406 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
407 {
408         struct usb_serial *serial = port->serial;
409         struct mct_u232_private *priv = usb_get_serial_port_data(port);
410         int retval = 0;
411         unsigned int control_state;
412         unsigned long flags;
413         unsigned char last_lcr;
414         unsigned char last_msr;
415 
416         /* Compensate for a hardware bug: although the Sitecom U232-P25
417          * device reports a maximum output packet size of 32 bytes,
418          * it seems to be able to accept only 16 bytes (and that's what
419          * SniffUSB says too...)
420          */
421         if (le16_to_cpu(serial->dev->descriptor.idProduct)
422                                                 == MCT_U232_SITECOM_PID)
423                 port->bulk_out_size = 16;
424 
425         /* Do a defined restart: the normal serial device seems to
426          * always turn on DTR and RTS here, so do the same. I'm not
427          * sure if this is really necessary. But it should not harm
428          * either.
429          */
430         spin_lock_irqsave(&priv->lock, flags);
431         if (tty && (tty->termios.c_cflag & CBAUD))
432                 priv->control_state = TIOCM_DTR | TIOCM_RTS;
433         else
434                 priv->control_state = 0;
435 
436         priv->last_lcr = (MCT_U232_DATA_BITS_8 |
437                           MCT_U232_PARITY_NONE |
438                           MCT_U232_STOP_BITS_1);
439         control_state = priv->control_state;
440         last_lcr = priv->last_lcr;
441         spin_unlock_irqrestore(&priv->lock, flags);
442         mct_u232_set_modem_ctrl(port, control_state);
443         mct_u232_set_line_ctrl(port, last_lcr);
444 
445         /* Read modem status and update control state */
446         mct_u232_get_modem_stat(port, &last_msr);
447         spin_lock_irqsave(&priv->lock, flags);
448         priv->last_msr = last_msr;
449         mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
450         spin_unlock_irqrestore(&priv->lock, flags);
451 
452         retval = usb_submit_urb(priv->read_urb, GFP_KERNEL);
453         if (retval) {
454                 dev_err(&port->dev,
455                         "usb_submit_urb(read) failed pipe 0x%x err %d\n",
456                         port->read_urb->pipe, retval);
457                 goto error;
458         }
459 
460         retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
461         if (retval) {
462                 usb_kill_urb(priv->read_urb);
463                 dev_err(&port->dev,
464                         "usb_submit_urb(read int) failed pipe 0x%x err %d",
465                         port->interrupt_in_urb->pipe, retval);
466                 goto error;
467         }
468         return 0;
469 
470 error:
471         return retval;
472 } /* mct_u232_open */
473 
474 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
475 {
476         unsigned int control_state;
477         struct mct_u232_private *priv = usb_get_serial_port_data(port);
478 
479         spin_lock_irq(&priv->lock);
480         if (on)
481                 priv->control_state |= TIOCM_DTR | TIOCM_RTS;
482         else
483                 priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
484         control_state = priv->control_state;
485         spin_unlock_irq(&priv->lock);
486 
487         mct_u232_set_modem_ctrl(port, control_state);
488 }
489 
490 static void mct_u232_close(struct usb_serial_port *port)
491 {
492         struct mct_u232_private *priv = usb_get_serial_port_data(port);
493 
494         usb_kill_urb(priv->read_urb);
495         usb_kill_urb(port->interrupt_in_urb);
496 
497         usb_serial_generic_close(port);
498 } /* mct_u232_close */
499 
500 
501 static void mct_u232_read_int_callback(struct urb *urb)
502 {
503         struct usb_serial_port *port = urb->context;
504         struct mct_u232_private *priv = usb_get_serial_port_data(port);
505         unsigned char *data = urb->transfer_buffer;
506         int retval;
507         int status = urb->status;
508         unsigned long flags;
509 
510         switch (status) {
511         case 0:
512                 /* success */
513                 break;
514         case -ECONNRESET:
515         case -ENOENT:
516         case -ESHUTDOWN:
517                 /* this urb is terminated, clean up */
518                 dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
519                         __func__, status);
520                 return;
521         default:
522                 dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
523                         __func__, status);
524                 goto exit;
525         }
526 
527         usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
528 
529         /*
530          * Work-a-round: handle the 'usual' bulk-in pipe here
531          */
532         if (urb->transfer_buffer_length > 2) {
533                 if (urb->actual_length) {
534                         tty_insert_flip_string(&port->port, data,
535                                         urb->actual_length);
536                         tty_flip_buffer_push(&port->port);
537                 }
538                 goto exit;
539         }
540 
541         /*
542          * The interrupt-in pipe signals exceptional conditions (modem line
543          * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
544          */
545         spin_lock_irqsave(&priv->lock, flags);
546         priv->last_msr = data[MCT_U232_MSR_INDEX];
547 
548         /* Record Control Line states */
549         mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
550 
551         mct_u232_msr_to_icount(&port->icount, priv->last_msr);
552 
553 #if 0
554         /* Not yet handled. See belkin_sa.c for further information */
555         /* Now to report any errors */
556         priv->last_lsr = data[MCT_U232_LSR_INDEX];
557         /*
558          * fill in the flip buffer here, but I do not know the relation
559          * to the current/next receive buffer or characters.  I need
560          * to look in to this before committing any code.
561          */
562         if (priv->last_lsr & MCT_U232_LSR_ERR) {
563                 tty = tty_port_tty_get(&port->port);
564                 /* Overrun Error */
565                 if (priv->last_lsr & MCT_U232_LSR_OE) {
566                 }
567                 /* Parity Error */
568                 if (priv->last_lsr & MCT_U232_LSR_PE) {
569                 }
570                 /* Framing Error */
571                 if (priv->last_lsr & MCT_U232_LSR_FE) {
572                 }
573                 /* Break Indicator */
574                 if (priv->last_lsr & MCT_U232_LSR_BI) {
575                 }
576                 tty_kref_put(tty);
577         }
578 #endif
579         wake_up_interruptible(&port->port.delta_msr_wait);
580         spin_unlock_irqrestore(&priv->lock, flags);
581 exit:
582         retval = usb_submit_urb(urb, GFP_ATOMIC);
583         if (retval)
584                 dev_err(&port->dev,
585                         "%s - usb_submit_urb failed with result %d\n",
586                         __func__, retval);
587 } /* mct_u232_read_int_callback */
588 
589 static void mct_u232_set_termios(struct tty_struct *tty,
590                                  struct usb_serial_port *port,
591                                  struct ktermios *old_termios)
592 {
593         struct usb_serial *serial = port->serial;
594         struct mct_u232_private *priv = usb_get_serial_port_data(port);
595         struct ktermios *termios = &tty->termios;
596         unsigned int cflag = termios->c_cflag;
597         unsigned int old_cflag = old_termios->c_cflag;
598         unsigned long flags;
599         unsigned int control_state;
600         unsigned char last_lcr;
601 
602         /* get a local copy of the current port settings */
603         spin_lock_irqsave(&priv->lock, flags);
604         control_state = priv->control_state;
605         spin_unlock_irqrestore(&priv->lock, flags);
606         last_lcr = 0;
607 
608         /*
609          * Update baud rate.
610          * Do not attempt to cache old rates and skip settings,
611          * disconnects screw such tricks up completely.
612          * Premature optimization is the root of all evil.
613          */
614 
615         /* reassert DTR and RTS on transition from B0 */
616         if ((old_cflag & CBAUD) == B0) {
617                 dev_dbg(&port->dev, "%s: baud was B0\n", __func__);
618                 control_state |= TIOCM_DTR | TIOCM_RTS;
619                 mct_u232_set_modem_ctrl(port, control_state);
620         }
621 
622         mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty));
623 
624         if ((cflag & CBAUD) == B0) {
625                 dev_dbg(&port->dev, "%s: baud is B0\n", __func__);
626                 /* Drop RTS and DTR */
627                 control_state &= ~(TIOCM_DTR | TIOCM_RTS);
628                 mct_u232_set_modem_ctrl(port, control_state);
629         }
630 
631         /*
632          * Update line control register (LCR)
633          */
634 
635         /* set the parity */
636         if (cflag & PARENB)
637                 last_lcr |= (cflag & PARODD) ?
638                         MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
639         else
640                 last_lcr |= MCT_U232_PARITY_NONE;
641 
642         /* set the number of data bits */
643         switch (cflag & CSIZE) {
644         case CS5:
645                 last_lcr |= MCT_U232_DATA_BITS_5; break;
646         case CS6:
647                 last_lcr |= MCT_U232_DATA_BITS_6; break;
648         case CS7:
649                 last_lcr |= MCT_U232_DATA_BITS_7; break;
650         case CS8:
651                 last_lcr |= MCT_U232_DATA_BITS_8; break;
652         default:
653                 dev_err(&port->dev,
654                         "CSIZE was not CS5-CS8, using default of 8\n");
655                 last_lcr |= MCT_U232_DATA_BITS_8;
656                 break;
657         }
658 
659         termios->c_cflag &= ~CMSPAR;
660 
661         /* set the number of stop bits */
662         last_lcr |= (cflag & CSTOPB) ?
663                 MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
664 
665         mct_u232_set_line_ctrl(port, last_lcr);
666 
667         /* save off the modified port settings */
668         spin_lock_irqsave(&priv->lock, flags);
669         priv->control_state = control_state;
670         priv->last_lcr = last_lcr;
671         spin_unlock_irqrestore(&priv->lock, flags);
672 } /* mct_u232_set_termios */
673 
674 static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
675 {
676         struct usb_serial_port *port = tty->driver_data;
677         struct mct_u232_private *priv = usb_get_serial_port_data(port);
678         unsigned char lcr;
679         unsigned long flags;
680 
681         spin_lock_irqsave(&priv->lock, flags);
682         lcr = priv->last_lcr;
683 
684         if (break_state)
685                 lcr |= MCT_U232_SET_BREAK;
686         spin_unlock_irqrestore(&priv->lock, flags);
687 
688         mct_u232_set_line_ctrl(port, lcr);
689 } /* mct_u232_break_ctl */
690 
691 
692 static int mct_u232_tiocmget(struct tty_struct *tty)
693 {
694         struct usb_serial_port *port = tty->driver_data;
695         struct mct_u232_private *priv = usb_get_serial_port_data(port);
696         unsigned int control_state;
697         unsigned long flags;
698 
699         spin_lock_irqsave(&priv->lock, flags);
700         control_state = priv->control_state;
701         spin_unlock_irqrestore(&priv->lock, flags);
702 
703         return control_state;
704 }
705 
706 static int mct_u232_tiocmset(struct tty_struct *tty,
707                               unsigned int set, unsigned int clear)
708 {
709         struct usb_serial_port *port = tty->driver_data;
710         struct mct_u232_private *priv = usb_get_serial_port_data(port);
711         unsigned int control_state;
712         unsigned long flags;
713 
714         spin_lock_irqsave(&priv->lock, flags);
715         control_state = priv->control_state;
716 
717         if (set & TIOCM_RTS)
718                 control_state |= TIOCM_RTS;
719         if (set & TIOCM_DTR)
720                 control_state |= TIOCM_DTR;
721         if (clear & TIOCM_RTS)
722                 control_state &= ~TIOCM_RTS;
723         if (clear & TIOCM_DTR)
724                 control_state &= ~TIOCM_DTR;
725 
726         priv->control_state = control_state;
727         spin_unlock_irqrestore(&priv->lock, flags);
728         return mct_u232_set_modem_ctrl(port, control_state);
729 }
730 
731 static void mct_u232_throttle(struct tty_struct *tty)
732 {
733         struct usb_serial_port *port = tty->driver_data;
734         struct mct_u232_private *priv = usb_get_serial_port_data(port);
735         unsigned int control_state;
736 
737         spin_lock_irq(&priv->lock);
738         priv->rx_flags |= THROTTLED;
739         if (C_CRTSCTS(tty)) {
740                 priv->control_state &= ~TIOCM_RTS;
741                 control_state = priv->control_state;
742                 spin_unlock_irq(&priv->lock);
743                 mct_u232_set_modem_ctrl(port, control_state);
744         } else {
745                 spin_unlock_irq(&priv->lock);
746         }
747 }
748 
749 static void mct_u232_unthrottle(struct tty_struct *tty)
750 {
751         struct usb_serial_port *port = tty->driver_data;
752         struct mct_u232_private *priv = usb_get_serial_port_data(port);
753         unsigned int control_state;
754 
755         spin_lock_irq(&priv->lock);
756         if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
757                 priv->rx_flags &= ~THROTTLED;
758                 priv->control_state |= TIOCM_RTS;
759                 control_state = priv->control_state;
760                 spin_unlock_irq(&priv->lock);
761                 mct_u232_set_modem_ctrl(port, control_state);
762         } else {
763                 spin_unlock_irq(&priv->lock);
764         }
765 }
766 
767 module_usb_serial_driver(serial_drivers, id_table);
768 
769 MODULE_AUTHOR(DRIVER_AUTHOR);
770 MODULE_DESCRIPTION(DRIVER_DESC);
771 MODULE_LICENSE("GPL");
772 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us