Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * MCT (Magic Control Technology Corp.) USB RS232 Converter Driver
0004  *
0005  *   Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.ch)
0006  *
0007  * This program is largely derived from the Belkin USB Serial Adapter Driver
0008  * (see belkin_sa.[ch]). All of the information about the device was acquired
0009  * by using SniffUSB on Windows98. For technical details see mct_u232.h.
0010  *
0011  * William G. Greathouse and Greg Kroah-Hartman provided great help on how to
0012  * do the reverse engineering and how to write a USB serial device driver.
0013  *
0014  * TO BE DONE, TO BE CHECKED:
0015  *   DTR/RTS signal handling may be incomplete or incorrect. I have mainly
0016  *   implemented what I have seen with SniffUSB or found in belkin_sa.c.
0017  *   For further TODOs check also belkin_sa.c.
0018  */
0019 
0020 #include <linux/kernel.h>
0021 #include <linux/errno.h>
0022 #include <linux/slab.h>
0023 #include <linux/tty.h>
0024 #include <linux/tty_driver.h>
0025 #include <linux/tty_flip.h>
0026 #include <linux/module.h>
0027 #include <linux/spinlock.h>
0028 #include <linux/uaccess.h>
0029 #include <asm/unaligned.h>
0030 #include <linux/usb.h>
0031 #include <linux/usb/serial.h>
0032 #include <linux/serial.h>
0033 #include "mct_u232.h"
0034 
0035 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
0036 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
0037 
0038 /*
0039  * Function prototypes
0040  */
0041 static int  mct_u232_port_probe(struct usb_serial_port *port);
0042 static void mct_u232_port_remove(struct usb_serial_port *remove);
0043 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
0044 static void mct_u232_close(struct usb_serial_port *port);
0045 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
0046 static void mct_u232_read_int_callback(struct urb *urb);
0047 static void mct_u232_set_termios(struct tty_struct *tty,
0048             struct usb_serial_port *port, struct ktermios *old);
0049 static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
0050 static int  mct_u232_tiocmget(struct tty_struct *tty);
0051 static int  mct_u232_tiocmset(struct tty_struct *tty,
0052             unsigned int set, unsigned int clear);
0053 static void mct_u232_throttle(struct tty_struct *tty);
0054 static void mct_u232_unthrottle(struct tty_struct *tty);
0055 
0056 
0057 /*
0058  * All of the device info needed for the MCT USB-RS232 converter.
0059  */
0060 static const struct usb_device_id id_table[] = {
0061     { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
0062     { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
0063     { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
0064     { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
0065     { }     /* Terminating entry */
0066 };
0067 MODULE_DEVICE_TABLE(usb, id_table);
0068 
0069 static struct usb_serial_driver mct_u232_device = {
0070     .driver = {
0071         .owner =    THIS_MODULE,
0072         .name =     "mct_u232",
0073     },
0074     .description =       "MCT U232",
0075     .id_table =      id_table,
0076     .num_ports =         1,
0077     .open =          mct_u232_open,
0078     .close =         mct_u232_close,
0079     .dtr_rts =       mct_u232_dtr_rts,
0080     .throttle =      mct_u232_throttle,
0081     .unthrottle =        mct_u232_unthrottle,
0082     .read_int_callback = mct_u232_read_int_callback,
0083     .set_termios =       mct_u232_set_termios,
0084     .break_ctl =         mct_u232_break_ctl,
0085     .tiocmget =      mct_u232_tiocmget,
0086     .tiocmset =      mct_u232_tiocmset,
0087     .tiocmiwait =        usb_serial_generic_tiocmiwait,
0088     .port_probe =        mct_u232_port_probe,
0089     .port_remove =       mct_u232_port_remove,
0090     .get_icount =        usb_serial_generic_get_icount,
0091 };
0092 
0093 static struct usb_serial_driver * const serial_drivers[] = {
0094     &mct_u232_device, NULL
0095 };
0096 
0097 struct mct_u232_private {
0098     struct urb *read_urb;
0099     spinlock_t lock;
0100     unsigned int         control_state; /* Modem Line Setting (TIOCM) */
0101     unsigned char        last_lcr;      /* Line Control Register */
0102     unsigned char        last_lsr;      /* Line Status Register */
0103     unsigned char        last_msr;      /* Modem Status Register */
0104     unsigned int         rx_flags;      /* Throttling flags */
0105 };
0106 
0107 #define THROTTLED       0x01
0108 
0109 /*
0110  * Handle vendor specific USB requests
0111  */
0112 
0113 #define WDR_TIMEOUT 5000 /* default urb timeout */
0114 
0115 /*
0116  * Later day 2.6.0-test kernels have new baud rates like B230400 which
0117  * we do not know how to support. We ignore them for the moment.
0118  */
0119 static int mct_u232_calculate_baud_rate(struct usb_serial *serial,
0120                     speed_t value, speed_t *result)
0121 {
0122     *result = value;
0123 
0124     if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
0125         || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
0126         switch (value) {
0127         case 300:
0128             return 0x01;
0129         case 600:
0130             return 0x02; /* this one not tested */
0131         case 1200:
0132             return 0x03;
0133         case 2400:
0134             return 0x04;
0135         case 4800:
0136             return 0x06;
0137         case 9600:
0138             return 0x08;
0139         case 19200:
0140             return 0x09;
0141         case 38400:
0142             return 0x0a;
0143         case 57600:
0144             return 0x0b;
0145         case 115200:
0146             return 0x0c;
0147         default:
0148             *result = 9600;
0149             return 0x08;
0150         }
0151     } else {
0152         /* FIXME: Can we use any divider - should we do
0153            divider = 115200/value;
0154            real baud = 115200/divider */
0155         switch (value) {
0156         case 300: break;
0157         case 600: break;
0158         case 1200: break;
0159         case 2400: break;
0160         case 4800: break;
0161         case 9600: break;
0162         case 19200: break;
0163         case 38400: break;
0164         case 57600: break;
0165         case 115200: break;
0166         default:
0167             value = 9600;
0168             *result = 9600;
0169         }
0170         return 115200/value;
0171     }
0172 }
0173 
0174 static int mct_u232_set_baud_rate(struct tty_struct *tty,
0175     struct usb_serial *serial, struct usb_serial_port *port, speed_t value)
0176 {
0177     unsigned int divisor;
0178     int rc;
0179     unsigned char *buf;
0180     unsigned char cts_enable_byte = 0;
0181     speed_t speed;
0182 
0183     buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
0184     if (buf == NULL)
0185         return -ENOMEM;
0186 
0187     divisor = mct_u232_calculate_baud_rate(serial, value, &speed);
0188     put_unaligned_le32(divisor, buf);
0189     rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
0190                 MCT_U232_SET_BAUD_RATE_REQUEST,
0191                 MCT_U232_SET_REQUEST_TYPE,
0192                 0, 0, buf, MCT_U232_SET_BAUD_RATE_SIZE,
0193                 WDR_TIMEOUT);
0194     if (rc < 0) /*FIXME: What value speed results */
0195         dev_err(&port->dev, "Set BAUD RATE %d failed (error = %d)\n",
0196             value, rc);
0197     else
0198         tty_encode_baud_rate(tty, speed, speed);
0199     dev_dbg(&port->dev, "set_baud_rate: value: 0x%x, divisor: 0x%x\n", value, divisor);
0200 
0201     /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
0202        always sends two extra USB 'device request' messages after the
0203        'baud rate change' message.  The actual functionality of the
0204        request codes in these messages is not fully understood but these
0205        particular codes are never seen in any operation besides a baud
0206        rate change.  Both of these messages send a single byte of data.
0207        In the first message, the value of this byte is always zero.
0208 
0209        The second message has been determined experimentally to control
0210        whether data will be transmitted to a device which is not asserting
0211        the 'CTS' signal.  If the second message's data byte is zero, data
0212        will be transmitted even if 'CTS' is not asserted (i.e. no hardware
0213        flow control).  if the second message's data byte is nonzero (a
0214        value of 1 is used by this driver), data will not be transmitted to
0215        a device which is not asserting 'CTS'.
0216     */
0217 
0218     buf[0] = 0;
0219     rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
0220                 MCT_U232_SET_UNKNOWN1_REQUEST,
0221                 MCT_U232_SET_REQUEST_TYPE,
0222                 0, 0, buf, MCT_U232_SET_UNKNOWN1_SIZE,
0223                 WDR_TIMEOUT);
0224     if (rc < 0)
0225         dev_err(&port->dev, "Sending USB device request code %d "
0226             "failed (error = %d)\n", MCT_U232_SET_UNKNOWN1_REQUEST,
0227             rc);
0228 
0229     if (port && C_CRTSCTS(tty))
0230        cts_enable_byte = 1;
0231 
0232     dev_dbg(&port->dev, "set_baud_rate: send second control message, data = %02X\n",
0233         cts_enable_byte);
0234     buf[0] = cts_enable_byte;
0235     rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
0236             MCT_U232_SET_CTS_REQUEST,
0237             MCT_U232_SET_REQUEST_TYPE,
0238             0, 0, buf, MCT_U232_SET_CTS_SIZE,
0239             WDR_TIMEOUT);
0240     if (rc < 0)
0241         dev_err(&port->dev, "Sending USB device request code %d "
0242             "failed (error = %d)\n", MCT_U232_SET_CTS_REQUEST, rc);
0243 
0244     kfree(buf);
0245     return rc;
0246 } /* mct_u232_set_baud_rate */
0247 
0248 static int mct_u232_set_line_ctrl(struct usb_serial_port *port,
0249                   unsigned char lcr)
0250 {
0251     int rc;
0252     unsigned char *buf;
0253 
0254     buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
0255     if (buf == NULL)
0256         return -ENOMEM;
0257 
0258     buf[0] = lcr;
0259     rc = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
0260             MCT_U232_SET_LINE_CTRL_REQUEST,
0261             MCT_U232_SET_REQUEST_TYPE,
0262             0, 0, buf, MCT_U232_SET_LINE_CTRL_SIZE,
0263             WDR_TIMEOUT);
0264     if (rc < 0)
0265         dev_err(&port->dev, "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc);
0266     dev_dbg(&port->dev, "set_line_ctrl: 0x%x\n", lcr);
0267     kfree(buf);
0268     return rc;
0269 } /* mct_u232_set_line_ctrl */
0270 
0271 static int mct_u232_set_modem_ctrl(struct usb_serial_port *port,
0272                    unsigned int control_state)
0273 {
0274     int rc;
0275     unsigned char mcr;
0276     unsigned char *buf;
0277 
0278     buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
0279     if (buf == NULL)
0280         return -ENOMEM;
0281 
0282     mcr = MCT_U232_MCR_NONE;
0283     if (control_state & TIOCM_DTR)
0284         mcr |= MCT_U232_MCR_DTR;
0285     if (control_state & TIOCM_RTS)
0286         mcr |= MCT_U232_MCR_RTS;
0287 
0288     buf[0] = mcr;
0289     rc = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
0290             MCT_U232_SET_MODEM_CTRL_REQUEST,
0291             MCT_U232_SET_REQUEST_TYPE,
0292             0, 0, buf, MCT_U232_SET_MODEM_CTRL_SIZE,
0293             WDR_TIMEOUT);
0294     kfree(buf);
0295 
0296     dev_dbg(&port->dev, "set_modem_ctrl: state=0x%x ==> mcr=0x%x\n", control_state, mcr);
0297 
0298     if (rc < 0) {
0299         dev_err(&port->dev, "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
0300         return rc;
0301     }
0302     return 0;
0303 } /* mct_u232_set_modem_ctrl */
0304 
0305 static int mct_u232_get_modem_stat(struct usb_serial_port *port,
0306                    unsigned char *msr)
0307 {
0308     int rc;
0309     unsigned char *buf;
0310 
0311     buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
0312     if (buf == NULL) {
0313         *msr = 0;
0314         return -ENOMEM;
0315     }
0316     rc = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0),
0317             MCT_U232_GET_MODEM_STAT_REQUEST,
0318             MCT_U232_GET_REQUEST_TYPE,
0319             0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE,
0320             WDR_TIMEOUT);
0321     if (rc < MCT_U232_GET_MODEM_STAT_SIZE) {
0322         dev_err(&port->dev, "Get MODEM STATus failed (error = %d)\n", rc);
0323 
0324         if (rc >= 0)
0325             rc = -EIO;
0326 
0327         *msr = 0;
0328     } else {
0329         *msr = buf[0];
0330     }
0331     dev_dbg(&port->dev, "get_modem_stat: 0x%x\n", *msr);
0332     kfree(buf);
0333     return rc;
0334 } /* mct_u232_get_modem_stat */
0335 
0336 static void mct_u232_msr_to_icount(struct async_icount *icount,
0337                         unsigned char msr)
0338 {
0339     /* Translate Control Line states */
0340     if (msr & MCT_U232_MSR_DDSR)
0341         icount->dsr++;
0342     if (msr & MCT_U232_MSR_DCTS)
0343         icount->cts++;
0344     if (msr & MCT_U232_MSR_DRI)
0345         icount->rng++;
0346     if (msr & MCT_U232_MSR_DCD)
0347         icount->dcd++;
0348 } /* mct_u232_msr_to_icount */
0349 
0350 static void mct_u232_msr_to_state(struct usb_serial_port *port,
0351                   unsigned int *control_state, unsigned char msr)
0352 {
0353     /* Translate Control Line states */
0354     if (msr & MCT_U232_MSR_DSR)
0355         *control_state |=  TIOCM_DSR;
0356     else
0357         *control_state &= ~TIOCM_DSR;
0358     if (msr & MCT_U232_MSR_CTS)
0359         *control_state |=  TIOCM_CTS;
0360     else
0361         *control_state &= ~TIOCM_CTS;
0362     if (msr & MCT_U232_MSR_RI)
0363         *control_state |=  TIOCM_RI;
0364     else
0365         *control_state &= ~TIOCM_RI;
0366     if (msr & MCT_U232_MSR_CD)
0367         *control_state |=  TIOCM_CD;
0368     else
0369         *control_state &= ~TIOCM_CD;
0370     dev_dbg(&port->dev, "msr_to_state: msr=0x%x ==> state=0x%x\n", msr, *control_state);
0371 } /* mct_u232_msr_to_state */
0372 
0373 /*
0374  * Driver's tty interface functions
0375  */
0376 
0377 static int mct_u232_port_probe(struct usb_serial_port *port)
0378 {
0379     struct usb_serial *serial = port->serial;
0380     struct mct_u232_private *priv;
0381 
0382     /* check first to simplify error handling */
0383     if (!serial->port[1] || !serial->port[1]->interrupt_in_urb) {
0384         dev_err(&port->dev, "expected endpoint missing\n");
0385         return -ENODEV;
0386     }
0387 
0388     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0389     if (!priv)
0390         return -ENOMEM;
0391 
0392     /* Use second interrupt-in endpoint for reading. */
0393     priv->read_urb = serial->port[1]->interrupt_in_urb;
0394     priv->read_urb->context = port;
0395 
0396     spin_lock_init(&priv->lock);
0397 
0398     usb_set_serial_port_data(port, priv);
0399 
0400     return 0;
0401 }
0402 
0403 static void mct_u232_port_remove(struct usb_serial_port *port)
0404 {
0405     struct mct_u232_private *priv;
0406 
0407     priv = usb_get_serial_port_data(port);
0408     kfree(priv);
0409 }
0410 
0411 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
0412 {
0413     struct usb_serial *serial = port->serial;
0414     struct mct_u232_private *priv = usb_get_serial_port_data(port);
0415     int retval = 0;
0416     unsigned int control_state;
0417     unsigned long flags;
0418     unsigned char last_lcr;
0419     unsigned char last_msr;
0420 
0421     /* Compensate for a hardware bug: although the Sitecom U232-P25
0422      * device reports a maximum output packet size of 32 bytes,
0423      * it seems to be able to accept only 16 bytes (and that's what
0424      * SniffUSB says too...)
0425      */
0426     if (le16_to_cpu(serial->dev->descriptor.idProduct)
0427                         == MCT_U232_SITECOM_PID)
0428         port->bulk_out_size = 16;
0429 
0430     /* Do a defined restart: the normal serial device seems to
0431      * always turn on DTR and RTS here, so do the same. I'm not
0432      * sure if this is really necessary. But it should not harm
0433      * either.
0434      */
0435     spin_lock_irqsave(&priv->lock, flags);
0436     if (tty && C_BAUD(tty))
0437         priv->control_state = TIOCM_DTR | TIOCM_RTS;
0438     else
0439         priv->control_state = 0;
0440 
0441     priv->last_lcr = (MCT_U232_DATA_BITS_8 |
0442               MCT_U232_PARITY_NONE |
0443               MCT_U232_STOP_BITS_1);
0444     control_state = priv->control_state;
0445     last_lcr = priv->last_lcr;
0446     spin_unlock_irqrestore(&priv->lock, flags);
0447     mct_u232_set_modem_ctrl(port, control_state);
0448     mct_u232_set_line_ctrl(port, last_lcr);
0449 
0450     /* Read modem status and update control state */
0451     mct_u232_get_modem_stat(port, &last_msr);
0452     spin_lock_irqsave(&priv->lock, flags);
0453     priv->last_msr = last_msr;
0454     mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
0455     spin_unlock_irqrestore(&priv->lock, flags);
0456 
0457     retval = usb_submit_urb(priv->read_urb, GFP_KERNEL);
0458     if (retval) {
0459         dev_err(&port->dev,
0460             "usb_submit_urb(read) failed pipe 0x%x err %d\n",
0461             port->read_urb->pipe, retval);
0462         goto error;
0463     }
0464 
0465     retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
0466     if (retval) {
0467         usb_kill_urb(priv->read_urb);
0468         dev_err(&port->dev,
0469             "usb_submit_urb(read int) failed pipe 0x%x err %d",
0470             port->interrupt_in_urb->pipe, retval);
0471         goto error;
0472     }
0473     return 0;
0474 
0475 error:
0476     return retval;
0477 } /* mct_u232_open */
0478 
0479 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
0480 {
0481     unsigned int control_state;
0482     struct mct_u232_private *priv = usb_get_serial_port_data(port);
0483 
0484     spin_lock_irq(&priv->lock);
0485     if (on)
0486         priv->control_state |= TIOCM_DTR | TIOCM_RTS;
0487     else
0488         priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
0489     control_state = priv->control_state;
0490     spin_unlock_irq(&priv->lock);
0491 
0492     mct_u232_set_modem_ctrl(port, control_state);
0493 }
0494 
0495 static void mct_u232_close(struct usb_serial_port *port)
0496 {
0497     struct mct_u232_private *priv = usb_get_serial_port_data(port);
0498 
0499     usb_kill_urb(priv->read_urb);
0500     usb_kill_urb(port->interrupt_in_urb);
0501 
0502     usb_serial_generic_close(port);
0503 } /* mct_u232_close */
0504 
0505 
0506 static void mct_u232_read_int_callback(struct urb *urb)
0507 {
0508     struct usb_serial_port *port = urb->context;
0509     struct mct_u232_private *priv = usb_get_serial_port_data(port);
0510     unsigned char *data = urb->transfer_buffer;
0511     int retval;
0512     int status = urb->status;
0513     unsigned long flags;
0514 
0515     switch (status) {
0516     case 0:
0517         /* success */
0518         break;
0519     case -ECONNRESET:
0520     case -ENOENT:
0521     case -ESHUTDOWN:
0522         /* this urb is terminated, clean up */
0523         dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
0524             __func__, status);
0525         return;
0526     default:
0527         dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
0528             __func__, status);
0529         goto exit;
0530     }
0531 
0532     usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
0533 
0534     /*
0535      * Work-a-round: handle the 'usual' bulk-in pipe here
0536      */
0537     if (urb->transfer_buffer_length > 2) {
0538         if (urb->actual_length) {
0539             tty_insert_flip_string(&port->port, data,
0540                     urb->actual_length);
0541             tty_flip_buffer_push(&port->port);
0542         }
0543         goto exit;
0544     }
0545 
0546     /*
0547      * The interrupt-in pipe signals exceptional conditions (modem line
0548      * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
0549      */
0550     spin_lock_irqsave(&priv->lock, flags);
0551     priv->last_msr = data[MCT_U232_MSR_INDEX];
0552 
0553     /* Record Control Line states */
0554     mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
0555 
0556     mct_u232_msr_to_icount(&port->icount, priv->last_msr);
0557 
0558 #if 0
0559     /* Not yet handled. See belkin_sa.c for further information */
0560     /* Now to report any errors */
0561     priv->last_lsr = data[MCT_U232_LSR_INDEX];
0562     /*
0563      * fill in the flip buffer here, but I do not know the relation
0564      * to the current/next receive buffer or characters.  I need
0565      * to look in to this before committing any code.
0566      */
0567     if (priv->last_lsr & MCT_U232_LSR_ERR) {
0568         tty = tty_port_tty_get(&port->port);
0569         /* Overrun Error */
0570         if (priv->last_lsr & MCT_U232_LSR_OE) {
0571         }
0572         /* Parity Error */
0573         if (priv->last_lsr & MCT_U232_LSR_PE) {
0574         }
0575         /* Framing Error */
0576         if (priv->last_lsr & MCT_U232_LSR_FE) {
0577         }
0578         /* Break Indicator */
0579         if (priv->last_lsr & MCT_U232_LSR_BI) {
0580         }
0581         tty_kref_put(tty);
0582     }
0583 #endif
0584     wake_up_interruptible(&port->port.delta_msr_wait);
0585     spin_unlock_irqrestore(&priv->lock, flags);
0586 exit:
0587     retval = usb_submit_urb(urb, GFP_ATOMIC);
0588     if (retval)
0589         dev_err(&port->dev,
0590             "%s - usb_submit_urb failed with result %d\n",
0591             __func__, retval);
0592 } /* mct_u232_read_int_callback */
0593 
0594 static void mct_u232_set_termios(struct tty_struct *tty,
0595                  struct usb_serial_port *port,
0596                  struct ktermios *old_termios)
0597 {
0598     struct usb_serial *serial = port->serial;
0599     struct mct_u232_private *priv = usb_get_serial_port_data(port);
0600     struct ktermios *termios = &tty->termios;
0601     unsigned int cflag = termios->c_cflag;
0602     unsigned int old_cflag = old_termios->c_cflag;
0603     unsigned long flags;
0604     unsigned int control_state;
0605     unsigned char last_lcr;
0606 
0607     /* get a local copy of the current port settings */
0608     spin_lock_irqsave(&priv->lock, flags);
0609     control_state = priv->control_state;
0610     spin_unlock_irqrestore(&priv->lock, flags);
0611     last_lcr = 0;
0612 
0613     /*
0614      * Update baud rate.
0615      * Do not attempt to cache old rates and skip settings,
0616      * disconnects screw such tricks up completely.
0617      * Premature optimization is the root of all evil.
0618      */
0619 
0620     /* reassert DTR and RTS on transition from B0 */
0621     if ((old_cflag & CBAUD) == B0) {
0622         dev_dbg(&port->dev, "%s: baud was B0\n", __func__);
0623         control_state |= TIOCM_DTR | TIOCM_RTS;
0624         mct_u232_set_modem_ctrl(port, control_state);
0625     }
0626 
0627     mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty));
0628 
0629     if ((cflag & CBAUD) == B0) {
0630         dev_dbg(&port->dev, "%s: baud is B0\n", __func__);
0631         /* Drop RTS and DTR */
0632         control_state &= ~(TIOCM_DTR | TIOCM_RTS);
0633         mct_u232_set_modem_ctrl(port, control_state);
0634     }
0635 
0636     /*
0637      * Update line control register (LCR)
0638      */
0639 
0640     /* set the parity */
0641     if (cflag & PARENB)
0642         last_lcr |= (cflag & PARODD) ?
0643             MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
0644     else
0645         last_lcr |= MCT_U232_PARITY_NONE;
0646 
0647     /* set the number of data bits */
0648     switch (cflag & CSIZE) {
0649     case CS5:
0650         last_lcr |= MCT_U232_DATA_BITS_5; break;
0651     case CS6:
0652         last_lcr |= MCT_U232_DATA_BITS_6; break;
0653     case CS7:
0654         last_lcr |= MCT_U232_DATA_BITS_7; break;
0655     case CS8:
0656         last_lcr |= MCT_U232_DATA_BITS_8; break;
0657     default:
0658         dev_err(&port->dev,
0659             "CSIZE was not CS5-CS8, using default of 8\n");
0660         last_lcr |= MCT_U232_DATA_BITS_8;
0661         break;
0662     }
0663 
0664     termios->c_cflag &= ~CMSPAR;
0665 
0666     /* set the number of stop bits */
0667     last_lcr |= (cflag & CSTOPB) ?
0668         MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
0669 
0670     mct_u232_set_line_ctrl(port, last_lcr);
0671 
0672     /* save off the modified port settings */
0673     spin_lock_irqsave(&priv->lock, flags);
0674     priv->control_state = control_state;
0675     priv->last_lcr = last_lcr;
0676     spin_unlock_irqrestore(&priv->lock, flags);
0677 } /* mct_u232_set_termios */
0678 
0679 static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
0680 {
0681     struct usb_serial_port *port = tty->driver_data;
0682     struct mct_u232_private *priv = usb_get_serial_port_data(port);
0683     unsigned char lcr;
0684     unsigned long flags;
0685 
0686     spin_lock_irqsave(&priv->lock, flags);
0687     lcr = priv->last_lcr;
0688 
0689     if (break_state)
0690         lcr |= MCT_U232_SET_BREAK;
0691     spin_unlock_irqrestore(&priv->lock, flags);
0692 
0693     mct_u232_set_line_ctrl(port, lcr);
0694 } /* mct_u232_break_ctl */
0695 
0696 
0697 static int mct_u232_tiocmget(struct tty_struct *tty)
0698 {
0699     struct usb_serial_port *port = tty->driver_data;
0700     struct mct_u232_private *priv = usb_get_serial_port_data(port);
0701     unsigned int control_state;
0702     unsigned long flags;
0703 
0704     spin_lock_irqsave(&priv->lock, flags);
0705     control_state = priv->control_state;
0706     spin_unlock_irqrestore(&priv->lock, flags);
0707 
0708     return control_state;
0709 }
0710 
0711 static int mct_u232_tiocmset(struct tty_struct *tty,
0712                   unsigned int set, unsigned int clear)
0713 {
0714     struct usb_serial_port *port = tty->driver_data;
0715     struct mct_u232_private *priv = usb_get_serial_port_data(port);
0716     unsigned int control_state;
0717     unsigned long flags;
0718 
0719     spin_lock_irqsave(&priv->lock, flags);
0720     control_state = priv->control_state;
0721 
0722     if (set & TIOCM_RTS)
0723         control_state |= TIOCM_RTS;
0724     if (set & TIOCM_DTR)
0725         control_state |= TIOCM_DTR;
0726     if (clear & TIOCM_RTS)
0727         control_state &= ~TIOCM_RTS;
0728     if (clear & TIOCM_DTR)
0729         control_state &= ~TIOCM_DTR;
0730 
0731     priv->control_state = control_state;
0732     spin_unlock_irqrestore(&priv->lock, flags);
0733     return mct_u232_set_modem_ctrl(port, control_state);
0734 }
0735 
0736 static void mct_u232_throttle(struct tty_struct *tty)
0737 {
0738     struct usb_serial_port *port = tty->driver_data;
0739     struct mct_u232_private *priv = usb_get_serial_port_data(port);
0740     unsigned int control_state;
0741 
0742     spin_lock_irq(&priv->lock);
0743     priv->rx_flags |= THROTTLED;
0744     if (C_CRTSCTS(tty)) {
0745         priv->control_state &= ~TIOCM_RTS;
0746         control_state = priv->control_state;
0747         spin_unlock_irq(&priv->lock);
0748         mct_u232_set_modem_ctrl(port, control_state);
0749     } else {
0750         spin_unlock_irq(&priv->lock);
0751     }
0752 }
0753 
0754 static void mct_u232_unthrottle(struct tty_struct *tty)
0755 {
0756     struct usb_serial_port *port = tty->driver_data;
0757     struct mct_u232_private *priv = usb_get_serial_port_data(port);
0758     unsigned int control_state;
0759 
0760     spin_lock_irq(&priv->lock);
0761     if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
0762         priv->rx_flags &= ~THROTTLED;
0763         priv->control_state |= TIOCM_RTS;
0764         control_state = priv->control_state;
0765         spin_unlock_irq(&priv->lock);
0766         mct_u232_set_modem_ctrl(port, control_state);
0767     } else {
0768         spin_unlock_irq(&priv->lock);
0769     }
0770 }
0771 
0772 module_usb_serial_driver(serial_drivers, id_table);
0773 
0774 MODULE_AUTHOR(DRIVER_AUTHOR);
0775 MODULE_DESCRIPTION(DRIVER_DESC);
0776 MODULE_LICENSE("GPL");