linux/drivers/usb/serial/ssu100.c
<<
>>
Prefs
   1/*
   2 * usb-serial driver for Quatech SSU-100
   3 *
   4 * based on ftdi_sio.c and the original serqt_usb.c from Quatech
   5 *
   6 */
   7
   8#include <linux/errno.h>
   9#include <linux/init.h>
  10#include <linux/slab.h>
  11#include <linux/tty.h>
  12#include <linux/tty_driver.h>
  13#include <linux/tty_flip.h>
  14#include <linux/module.h>
  15#include <linux/serial.h>
  16#include <linux/usb.h>
  17#include <linux/usb/serial.h>
  18#include <linux/serial_reg.h>
  19#include <linux/uaccess.h>
  20
  21#define QT_OPEN_CLOSE_CHANNEL       0xca
  22#define QT_SET_GET_DEVICE           0xc2
  23#define QT_SET_GET_REGISTER         0xc0
  24#define QT_GET_SET_PREBUF_TRIG_LVL  0xcc
  25#define QT_SET_ATF                  0xcd
  26#define QT_GET_SET_UART             0xc1
  27#define QT_TRANSFER_IN              0xc0
  28#define QT_HW_FLOW_CONTROL_MASK     0xc5
  29#define QT_SW_FLOW_CONTROL_MASK     0xc6
  30
  31#define  SERIAL_MSR_MASK            0xf0
  32
  33#define  SERIAL_CRTSCTS ((UART_MCR_RTS << 8) | UART_MSR_CTS)
  34
  35#define  SERIAL_EVEN_PARITY         (UART_LCR_PARITY | UART_LCR_EPAR)
  36
  37#define  MAX_BAUD_RATE              460800
  38
  39#define ATC_DISABLED                0x00
  40#define DUPMODE_BITS        0xc0
  41#define RR_BITS             0x03
  42#define LOOPMODE_BITS       0x41
  43#define RS232_MODE          0x00
  44#define RTSCTS_TO_CONNECTOR 0x40
  45#define CLKS_X4             0x02
  46#define FULLPWRBIT          0x00000080
  47#define NEXT_BOARD_POWER_BIT        0x00000004
  48
  49#define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver"
  50
  51#define USB_VENDOR_ID_QUATECH   0x061d  /* Quatech VID */
  52#define QUATECH_SSU100  0xC020  /* SSU100 */
  53
  54static const struct usb_device_id id_table[] = {
  55        {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)},
  56        {}                      /* Terminating entry */
  57};
  58MODULE_DEVICE_TABLE(usb, id_table);
  59
  60struct ssu100_port_private {
  61        spinlock_t status_lock;
  62        u8 shadowLSR;
  63        u8 shadowMSR;
  64};
  65
  66static inline int ssu100_control_msg(struct usb_device *dev,
  67                                     u8 request, u16 data, u16 index)
  68{
  69        return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  70                               request, 0x40, data, index,
  71                               NULL, 0, 300);
  72}
  73
  74static inline int ssu100_setdevice(struct usb_device *dev, u8 *data)
  75{
  76        u16 x = ((u16)(data[1] << 8) | (u16)(data[0]));
  77
  78        return ssu100_control_msg(dev, QT_SET_GET_DEVICE, x, 0);
  79}
  80
  81
  82static inline int ssu100_getdevice(struct usb_device *dev, u8 *data)
  83{
  84        return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  85                               QT_SET_GET_DEVICE, 0xc0, 0, 0,
  86                               data, 3, 300);
  87}
  88
  89static inline int ssu100_getregister(struct usb_device *dev,
  90                                     unsigned short uart,
  91                                     unsigned short reg,
  92                                     u8 *data)
  93{
  94        return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  95                               QT_SET_GET_REGISTER, 0xc0, reg,
  96                               uart, data, sizeof(*data), 300);
  97
  98}
  99
 100
 101static inline int ssu100_setregister(struct usb_device *dev,
 102                                     unsigned short uart,
 103                                     unsigned short reg,
 104                                     u16 data)
 105{
 106        u16 value = (data << 8) | reg;
 107
 108        return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 109                               QT_SET_GET_REGISTER, 0x40, value, uart,
 110                               NULL, 0, 300);
 111
 112}
 113
 114#define set_mctrl(dev, set)             update_mctrl((dev), (set), 0)
 115#define clear_mctrl(dev, clear) update_mctrl((dev), 0, (clear))
 116
 117/* these do not deal with device that have more than 1 port */
 118static inline int update_mctrl(struct usb_device *dev, unsigned int set,
 119                               unsigned int clear)
 120{
 121        unsigned urb_value;
 122        int result;
 123
 124        if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
 125                dev_dbg(&dev->dev, "%s - DTR|RTS not being set|cleared\n", __func__);
 126                return 0;       /* no change */
 127        }
 128
 129        clear &= ~set;  /* 'set' takes precedence over 'clear' */
 130        urb_value = 0;
 131        if (set & TIOCM_DTR)
 132                urb_value |= UART_MCR_DTR;
 133        if (set & TIOCM_RTS)
 134                urb_value |= UART_MCR_RTS;
 135
 136        result = ssu100_setregister(dev, 0, UART_MCR, urb_value);
 137        if (result < 0)
 138                dev_dbg(&dev->dev, "%s Error from MODEM_CTRL urb\n", __func__);
 139
 140        return result;
 141}
 142
 143static int ssu100_initdevice(struct usb_device *dev)
 144{
 145        u8 *data;
 146        int result = 0;
 147
 148        data = kzalloc(3, GFP_KERNEL);
 149        if (!data)
 150                return -ENOMEM;
 151
 152        result = ssu100_getdevice(dev, data);
 153        if (result < 0) {
 154                dev_dbg(&dev->dev, "%s - get_device failed %i\n", __func__, result);
 155                goto out;
 156        }
 157
 158        data[1] &= ~FULLPWRBIT;
 159
 160        result = ssu100_setdevice(dev, data);
 161        if (result < 0) {
 162                dev_dbg(&dev->dev, "%s - setdevice failed %i\n", __func__, result);
 163                goto out;
 164        }
 165
 166        result = ssu100_control_msg(dev, QT_GET_SET_PREBUF_TRIG_LVL, 128, 0);
 167        if (result < 0) {
 168                dev_dbg(&dev->dev, "%s - set prebuffer level failed %i\n", __func__, result);
 169                goto out;
 170        }
 171
 172        result = ssu100_control_msg(dev, QT_SET_ATF, ATC_DISABLED, 0);
 173        if (result < 0) {
 174                dev_dbg(&dev->dev, "%s - set ATFprebuffer level failed %i\n", __func__, result);
 175                goto out;
 176        }
 177
 178        result = ssu100_getdevice(dev, data);
 179        if (result < 0) {
 180                dev_dbg(&dev->dev, "%s - get_device failed %i\n", __func__, result);
 181                goto out;
 182        }
 183
 184        data[0] &= ~(RR_BITS | DUPMODE_BITS);
 185        data[0] |= CLKS_X4;
 186        data[1] &= ~(LOOPMODE_BITS);
 187        data[1] |= RS232_MODE;
 188
 189        result = ssu100_setdevice(dev, data);
 190        if (result < 0) {
 191                dev_dbg(&dev->dev, "%s - setdevice failed %i\n", __func__, result);
 192                goto out;
 193        }
 194
 195out:    kfree(data);
 196        return result;
 197
 198}
 199
 200
 201static void ssu100_set_termios(struct tty_struct *tty,
 202                               struct usb_serial_port *port,
 203                               struct ktermios *old_termios)
 204{
 205        struct usb_device *dev = port->serial->dev;
 206        struct ktermios *termios = &tty->termios;
 207        u16 baud, divisor, remainder;
 208        unsigned int cflag = termios->c_cflag;
 209        u16 urb_value = 0; /* will hold the new flags */
 210        int result;
 211
 212        if (cflag & PARENB) {
 213                if (cflag & PARODD)
 214                        urb_value |= UART_LCR_PARITY;
 215                else
 216                        urb_value |= SERIAL_EVEN_PARITY;
 217        }
 218
 219        switch (cflag & CSIZE) {
 220        case CS5:
 221                urb_value |= UART_LCR_WLEN5;
 222                break;
 223        case CS6:
 224                urb_value |= UART_LCR_WLEN6;
 225                break;
 226        case CS7:
 227                urb_value |= UART_LCR_WLEN7;
 228                break;
 229        default:
 230        case CS8:
 231                urb_value |= UART_LCR_WLEN8;
 232                break;
 233        }
 234
 235        baud = tty_get_baud_rate(tty);
 236        if (!baud)
 237                baud = 9600;
 238
 239        dev_dbg(&port->dev, "%s - got baud = %d\n", __func__, baud);
 240
 241
 242        divisor = MAX_BAUD_RATE / baud;
 243        remainder = MAX_BAUD_RATE % baud;
 244        if (((remainder * 2) >= baud) && (baud != 110))
 245                divisor++;
 246
 247        urb_value = urb_value << 8;
 248
 249        result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value);
 250        if (result < 0)
 251                dev_dbg(&port->dev, "%s - set uart failed\n", __func__);
 252
 253        if (cflag & CRTSCTS)
 254                result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
 255                                            SERIAL_CRTSCTS, 0);
 256        else
 257                result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
 258                                            0, 0);
 259        if (result < 0)
 260                dev_dbg(&port->dev, "%s - set HW flow control failed\n", __func__);
 261
 262        if (I_IXOFF(tty) || I_IXON(tty)) {
 263                u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty)));
 264
 265                result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
 266                                            x, 0);
 267        } else
 268                result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
 269                                            0, 0);
 270
 271        if (result < 0)
 272                dev_dbg(&port->dev, "%s - set SW flow control failed\n", __func__);
 273
 274}
 275
 276
 277static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
 278{
 279        struct usb_device *dev = port->serial->dev;
 280        struct ssu100_port_private *priv = usb_get_serial_port_data(port);
 281        u8 *data;
 282        int result;
 283        unsigned long flags;
 284
 285        data = kzalloc(2, GFP_KERNEL);
 286        if (!data)
 287                return -ENOMEM;
 288
 289        result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 290                                 QT_OPEN_CLOSE_CHANNEL,
 291                                 QT_TRANSFER_IN, 0x01,
 292                                 0, data, 2, 300);
 293        if (result < 0) {
 294                dev_dbg(&port->dev, "%s - open failed %i\n", __func__, result);
 295                kfree(data);
 296                return result;
 297        }
 298
 299        spin_lock_irqsave(&priv->status_lock, flags);
 300        priv->shadowLSR = data[0];
 301        priv->shadowMSR = data[1];
 302        spin_unlock_irqrestore(&priv->status_lock, flags);
 303
 304        kfree(data);
 305
 306/* set to 9600 */
 307        result = ssu100_control_msg(dev, QT_GET_SET_UART, 0x30, 0x0300);
 308        if (result < 0)
 309                dev_dbg(&port->dev, "%s - set uart failed\n", __func__);
 310
 311        if (tty)
 312                ssu100_set_termios(tty, port, &tty->termios);
 313
 314        return usb_serial_generic_open(tty, port);
 315}
 316
 317static int get_serial_info(struct usb_serial_port *port,
 318                           struct serial_struct __user *retinfo)
 319{
 320        struct serial_struct tmp;
 321
 322        if (!retinfo)
 323                return -EFAULT;
 324
 325        memset(&tmp, 0, sizeof(tmp));
 326        tmp.line                = port->minor;
 327        tmp.port                = 0;
 328        tmp.irq                 = 0;
 329        tmp.flags               = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
 330        tmp.xmit_fifo_size      = port->bulk_out_size;
 331        tmp.baud_base           = 9600;
 332        tmp.close_delay         = 5*HZ;
 333        tmp.closing_wait        = 30*HZ;
 334
 335        if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
 336                return -EFAULT;
 337        return 0;
 338}
 339
 340static int ssu100_ioctl(struct tty_struct *tty,
 341                    unsigned int cmd, unsigned long arg)
 342{
 343        struct usb_serial_port *port = tty->driver_data;
 344
 345        dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd);
 346
 347        switch (cmd) {
 348        case TIOCGSERIAL:
 349                return get_serial_info(port,
 350                                       (struct serial_struct __user *) arg);
 351        default:
 352                break;
 353        }
 354
 355        dev_dbg(&port->dev, "%s arg not supported\n", __func__);
 356
 357        return -ENOIOCTLCMD;
 358}
 359
 360static int ssu100_attach(struct usb_serial *serial)
 361{
 362        return ssu100_initdevice(serial->dev);
 363}
 364
 365static int ssu100_port_probe(struct usb_serial_port *port)
 366{
 367        struct ssu100_port_private *priv;
 368
 369        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 370        if (!priv)
 371                return -ENOMEM;
 372
 373        spin_lock_init(&priv->status_lock);
 374
 375        usb_set_serial_port_data(port, priv);
 376
 377        return 0;
 378}
 379
 380static int ssu100_port_remove(struct usb_serial_port *port)
 381{
 382        struct ssu100_port_private *priv;
 383
 384        priv = usb_get_serial_port_data(port);
 385        kfree(priv);
 386
 387        return 0;
 388}
 389
 390static int ssu100_tiocmget(struct tty_struct *tty)
 391{
 392        struct usb_serial_port *port = tty->driver_data;
 393        struct usb_device *dev = port->serial->dev;
 394        u8 *d;
 395        int r;
 396
 397        d = kzalloc(2, GFP_KERNEL);
 398        if (!d)
 399                return -ENOMEM;
 400
 401        r = ssu100_getregister(dev, 0, UART_MCR, d);
 402        if (r < 0)
 403                goto mget_out;
 404
 405        r = ssu100_getregister(dev, 0, UART_MSR, d+1);
 406        if (r < 0)
 407                goto mget_out;
 408
 409        r = (d[0] & UART_MCR_DTR ? TIOCM_DTR : 0) |
 410                (d[0] & UART_MCR_RTS ? TIOCM_RTS : 0) |
 411                (d[1] & UART_MSR_CTS ? TIOCM_CTS : 0) |
 412                (d[1] & UART_MSR_DCD ? TIOCM_CAR : 0) |
 413                (d[1] & UART_MSR_RI ? TIOCM_RI : 0) |
 414                (d[1] & UART_MSR_DSR ? TIOCM_DSR : 0);
 415
 416mget_out:
 417        kfree(d);
 418        return r;
 419}
 420
 421static int ssu100_tiocmset(struct tty_struct *tty,
 422                           unsigned int set, unsigned int clear)
 423{
 424        struct usb_serial_port *port = tty->driver_data;
 425        struct usb_device *dev = port->serial->dev;
 426
 427        return update_mctrl(dev, set, clear);
 428}
 429
 430static void ssu100_dtr_rts(struct usb_serial_port *port, int on)
 431{
 432        struct usb_device *dev = port->serial->dev;
 433
 434        /* Disable flow control */
 435        if (!on) {
 436                if (ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
 437                        dev_err(&port->dev, "error from flowcontrol urb\n");
 438        }
 439        /* drop RTS and DTR */
 440        if (on)
 441                set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
 442        else
 443                clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
 444}
 445
 446static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
 447{
 448        struct ssu100_port_private *priv = usb_get_serial_port_data(port);
 449        unsigned long flags;
 450
 451        spin_lock_irqsave(&priv->status_lock, flags);
 452        priv->shadowMSR = msr;
 453        spin_unlock_irqrestore(&priv->status_lock, flags);
 454
 455        if (msr & UART_MSR_ANY_DELTA) {
 456                /* update input line counters */
 457                if (msr & UART_MSR_DCTS)
 458                        port->icount.cts++;
 459                if (msr & UART_MSR_DDSR)
 460                        port->icount.dsr++;
 461                if (msr & UART_MSR_DDCD)
 462                        port->icount.dcd++;
 463                if (msr & UART_MSR_TERI)
 464                        port->icount.rng++;
 465                wake_up_interruptible(&port->port.delta_msr_wait);
 466        }
 467}
 468
 469static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
 470                              char *tty_flag)
 471{
 472        struct ssu100_port_private *priv = usb_get_serial_port_data(port);
 473        unsigned long flags;
 474
 475        spin_lock_irqsave(&priv->status_lock, flags);
 476        priv->shadowLSR = lsr;
 477        spin_unlock_irqrestore(&priv->status_lock, flags);
 478
 479        *tty_flag = TTY_NORMAL;
 480        if (lsr & UART_LSR_BRK_ERROR_BITS) {
 481                /* we always want to update icount, but we only want to
 482                 * update tty_flag for one case */
 483                if (lsr & UART_LSR_BI) {
 484                        port->icount.brk++;
 485                        *tty_flag = TTY_BREAK;
 486                        usb_serial_handle_break(port);
 487                }
 488                if (lsr & UART_LSR_PE) {
 489                        port->icount.parity++;
 490                        if (*tty_flag == TTY_NORMAL)
 491                                *tty_flag = TTY_PARITY;
 492                }
 493                if (lsr & UART_LSR_FE) {
 494                        port->icount.frame++;
 495                        if (*tty_flag == TTY_NORMAL)
 496                                *tty_flag = TTY_FRAME;
 497                }
 498                if (lsr & UART_LSR_OE){
 499                        port->icount.overrun++;
 500                        if (*tty_flag == TTY_NORMAL)
 501                                *tty_flag = TTY_OVERRUN;
 502                }
 503        }
 504
 505}
 506
 507static void ssu100_process_read_urb(struct urb *urb)
 508{
 509        struct usb_serial_port *port = urb->context;
 510        char *packet = (char *)urb->transfer_buffer;
 511        char flag = TTY_NORMAL;
 512        u32 len = urb->actual_length;
 513        int i;
 514        char *ch;
 515
 516        if ((len >= 4) &&
 517            (packet[0] == 0x1b) && (packet[1] == 0x1b) &&
 518            ((packet[2] == 0x00) || (packet[2] == 0x01))) {
 519                if (packet[2] == 0x00) {
 520                        ssu100_update_lsr(port, packet[3], &flag);
 521                        if (flag == TTY_OVERRUN)
 522                                tty_insert_flip_char(&port->port, 0,
 523                                                TTY_OVERRUN);
 524                }
 525                if (packet[2] == 0x01)
 526                        ssu100_update_msr(port, packet[3]);
 527
 528                len -= 4;
 529                ch = packet + 4;
 530        } else
 531                ch = packet;
 532
 533        if (!len)
 534                return; /* status only */
 535
 536        if (port->port.console && port->sysrq) {
 537                for (i = 0; i < len; i++, ch++) {
 538                        if (!usb_serial_handle_sysrq_char(port, *ch))
 539                                tty_insert_flip_char(&port->port, *ch, flag);
 540                }
 541        } else
 542                tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len);
 543
 544        tty_flip_buffer_push(&port->port);
 545}
 546
 547static struct usb_serial_driver ssu100_device = {
 548        .driver = {
 549                .owner = THIS_MODULE,
 550                .name = "ssu100",
 551        },
 552        .description         = DRIVER_DESC,
 553        .id_table            = id_table,
 554        .num_ports           = 1,
 555        .open                = ssu100_open,
 556        .attach              = ssu100_attach,
 557        .port_probe          = ssu100_port_probe,
 558        .port_remove         = ssu100_port_remove,
 559        .dtr_rts             = ssu100_dtr_rts,
 560        .process_read_urb    = ssu100_process_read_urb,
 561        .tiocmget            = ssu100_tiocmget,
 562        .tiocmset            = ssu100_tiocmset,
 563        .tiocmiwait          = usb_serial_generic_tiocmiwait,
 564        .get_icount          = usb_serial_generic_get_icount,
 565        .ioctl               = ssu100_ioctl,
 566        .set_termios         = ssu100_set_termios,
 567};
 568
 569static struct usb_serial_driver * const serial_drivers[] = {
 570        &ssu100_device, NULL
 571};
 572
 573module_usb_serial_driver(serial_drivers, id_table);
 574
 575MODULE_DESCRIPTION(DRIVER_DESC);
 576MODULE_LICENSE("GPL");
 577