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