linux/drivers/usb/serial/mct_u232.c
<<
>>
Prefs
   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 */
  45static int  mct_u232_port_probe(struct usb_serial_port *port);
  46static int  mct_u232_port_remove(struct usb_serial_port *remove);
  47static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
  48static void mct_u232_close(struct usb_serial_port *port);
  49static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
  50static void mct_u232_read_int_callback(struct urb *urb);
  51static void mct_u232_set_termios(struct tty_struct *tty,
  52                        struct usb_serial_port *port, struct ktermios *old);
  53static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
  54static int  mct_u232_tiocmget(struct tty_struct *tty);
  55static int  mct_u232_tiocmset(struct tty_struct *tty,
  56                        unsigned int set, unsigned int clear);
  57static void mct_u232_throttle(struct tty_struct *tty);
  58static 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 */
  64static 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};
  71MODULE_DEVICE_TABLE(usb, id_table);
  72
  73static 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
  97static struct usb_serial_driver * const serial_drivers[] = {
  98        &mct_u232_device, NULL
  99};
 100
 101struct 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 */
 123static 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
 178static 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
 252static 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
 275static 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
 309static 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
 336static 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
 350static 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
 377static 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
 396static 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
 406static 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
 470error:
 471        return retval;
 472} /* mct_u232_open */
 473
 474static 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
 490static 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
 501static 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);
 581exit:
 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
 589static 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
 674static 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
 692static 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
 706static 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
 731static 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
 749static 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
 767module_usb_serial_driver(serial_drivers, id_table);
 768
 769MODULE_AUTHOR(DRIVER_AUTHOR);
 770MODULE_DESCRIPTION(DRIVER_DESC);
 771MODULE_LICENSE("GPL");
 772