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