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