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 int  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 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