linux/drivers/usb/serial/kobil_sct.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 *  KOBIL USB Smart Card Terminal Driver
   4 *
   5 *  Copyright (C) 2002  KOBIL Systems GmbH
   6 *  Author: Thomas Wahrenbruch
   7 *
   8 *  Contact: linuxusb@kobil.de
   9 *
  10 *  This program is largely derived from work by the linux-usb group
  11 *  and associated source files.  Please see the usb/serial files for
  12 *  individual credits and copyrights.
  13 *
  14 *  Thanks to Greg Kroah-Hartman (greg@kroah.com) for his help and
  15 *  patience.
  16 *
  17 * Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus
  18 * (Adapter K), B1 Professional and KAAN Professional (Adapter B)
  19 */
  20
  21
  22#include <linux/kernel.h>
  23#include <linux/errno.h>
  24#include <linux/slab.h>
  25#include <linux/tty.h>
  26#include <linux/tty_driver.h>
  27#include <linux/tty_flip.h>
  28#include <linux/module.h>
  29#include <linux/spinlock.h>
  30#include <linux/uaccess.h>
  31#include <linux/usb.h>
  32#include <linux/usb/serial.h>
  33#include <linux/ioctl.h>
  34#include "kobil_sct.h"
  35
  36#define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com"
  37#define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)"
  38
  39#define KOBIL_VENDOR_ID                 0x0D46
  40#define KOBIL_ADAPTER_B_PRODUCT_ID      0x2011
  41#define KOBIL_ADAPTER_K_PRODUCT_ID      0x2012
  42#define KOBIL_USBTWIN_PRODUCT_ID        0x0078
  43#define KOBIL_KAAN_SIM_PRODUCT_ID       0x0081
  44
  45#define KOBIL_TIMEOUT           500
  46#define KOBIL_BUF_LENGTH        300
  47
  48
  49/* Function prototypes */
  50static int kobil_port_probe(struct usb_serial_port *probe);
  51static int kobil_port_remove(struct usb_serial_port *probe);
  52static int  kobil_open(struct tty_struct *tty, struct usb_serial_port *port);
  53static void kobil_close(struct usb_serial_port *port);
  54static int  kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
  55                         const unsigned char *buf, int count);
  56static int  kobil_write_room(struct tty_struct *tty);
  57static int  kobil_ioctl(struct tty_struct *tty,
  58                        unsigned int cmd, unsigned long arg);
  59static int  kobil_tiocmget(struct tty_struct *tty);
  60static int  kobil_tiocmset(struct tty_struct *tty,
  61                           unsigned int set, unsigned int clear);
  62static void kobil_read_int_callback(struct urb *urb);
  63static void kobil_write_int_callback(struct urb *urb);
  64static void kobil_set_termios(struct tty_struct *tty,
  65                        struct usb_serial_port *port, struct ktermios *old);
  66static void kobil_init_termios(struct tty_struct *tty);
  67
  68static const struct usb_device_id id_table[] = {
  69        { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) },
  70        { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_K_PRODUCT_ID) },
  71        { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_USBTWIN_PRODUCT_ID) },
  72        { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_KAAN_SIM_PRODUCT_ID) },
  73        { }                     /* Terminating entry */
  74};
  75MODULE_DEVICE_TABLE(usb, id_table);
  76
  77static struct usb_serial_driver kobil_device = {
  78        .driver = {
  79                .owner =        THIS_MODULE,
  80                .name =         "kobil",
  81        },
  82        .description =          "KOBIL USB smart card terminal",
  83        .id_table =             id_table,
  84        .num_ports =            1,
  85        .num_interrupt_out =    1,
  86        .port_probe =           kobil_port_probe,
  87        .port_remove =          kobil_port_remove,
  88        .ioctl =                kobil_ioctl,
  89        .set_termios =          kobil_set_termios,
  90        .init_termios =         kobil_init_termios,
  91        .tiocmget =             kobil_tiocmget,
  92        .tiocmset =             kobil_tiocmset,
  93        .open =                 kobil_open,
  94        .close =                kobil_close,
  95        .write =                kobil_write,
  96        .write_room =           kobil_write_room,
  97        .read_int_callback =    kobil_read_int_callback,
  98        .write_int_callback =   kobil_write_int_callback,
  99};
 100
 101static struct usb_serial_driver * const serial_drivers[] = {
 102        &kobil_device, NULL
 103};
 104
 105struct kobil_private {
 106        unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */
 107        int filled;  /* index of the last char in buf */
 108        int cur_pos; /* index of the next char to send in buf */
 109        __u16 device_type;
 110};
 111
 112
 113static int kobil_port_probe(struct usb_serial_port *port)
 114{
 115        struct usb_serial *serial = port->serial;
 116        struct kobil_private *priv;
 117
 118        priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);
 119        if (!priv)
 120                return -ENOMEM;
 121
 122        priv->filled = 0;
 123        priv->cur_pos = 0;
 124        priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct);
 125
 126        switch (priv->device_type) {
 127        case KOBIL_ADAPTER_B_PRODUCT_ID:
 128                dev_dbg(&serial->dev->dev, "KOBIL B1 PRO / KAAN PRO detected\n");
 129                break;
 130        case KOBIL_ADAPTER_K_PRODUCT_ID:
 131                dev_dbg(&serial->dev->dev, "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n");
 132                break;
 133        case KOBIL_USBTWIN_PRODUCT_ID:
 134                dev_dbg(&serial->dev->dev, "KOBIL USBTWIN detected\n");
 135                break;
 136        case KOBIL_KAAN_SIM_PRODUCT_ID:
 137                dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n");
 138                break;
 139        }
 140        usb_set_serial_port_data(port, priv);
 141
 142        return 0;
 143}
 144
 145
 146static int kobil_port_remove(struct usb_serial_port *port)
 147{
 148        struct kobil_private *priv;
 149
 150        priv = usb_get_serial_port_data(port);
 151        kfree(priv);
 152
 153        return 0;
 154}
 155
 156static void kobil_init_termios(struct tty_struct *tty)
 157{
 158        /* Default to echo off and other sane device settings */
 159        tty->termios.c_lflag = 0;
 160        tty->termios.c_iflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
 161        tty->termios.c_iflag |= IGNBRK | IGNPAR | IXOFF;
 162        /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
 163        tty->termios.c_oflag &= ~ONLCR;
 164}
 165
 166static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
 167{
 168        struct device *dev = &port->dev;
 169        int result = 0;
 170        struct kobil_private *priv;
 171        unsigned char *transfer_buffer;
 172        int transfer_buffer_length = 8;
 173
 174        priv = usb_get_serial_port_data(port);
 175
 176        /* allocate memory for transfer buffer */
 177        transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
 178        if (!transfer_buffer)
 179                return -ENOMEM;
 180
 181        /* get hardware version */
 182        result = usb_control_msg(port->serial->dev,
 183                          usb_rcvctrlpipe(port->serial->dev, 0),
 184                          SUSBCRequest_GetMisc,
 185                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
 186                          SUSBCR_MSC_GetHWVersion,
 187                          0,
 188                          transfer_buffer,
 189                          transfer_buffer_length,
 190                          KOBIL_TIMEOUT
 191        );
 192        dev_dbg(dev, "%s - Send get_HW_version URB returns: %i\n", __func__, result);
 193        if (result >= 3) {
 194                dev_dbg(dev, "Hardware version: %i.%i.%i\n", transfer_buffer[0],
 195                                transfer_buffer[1], transfer_buffer[2]);
 196        }
 197
 198        /* get firmware version */
 199        result = usb_control_msg(port->serial->dev,
 200                          usb_rcvctrlpipe(port->serial->dev, 0),
 201                          SUSBCRequest_GetMisc,
 202                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
 203                          SUSBCR_MSC_GetFWVersion,
 204                          0,
 205                          transfer_buffer,
 206                          transfer_buffer_length,
 207                          KOBIL_TIMEOUT
 208        );
 209        dev_dbg(dev, "%s - Send get_FW_version URB returns: %i\n", __func__, result);
 210        if (result >= 3) {
 211                dev_dbg(dev, "Firmware version: %i.%i.%i\n", transfer_buffer[0],
 212                                transfer_buffer[1], transfer_buffer[2]);
 213        }
 214
 215        if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
 216                        priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
 217                /* Setting Baudrate, Parity and Stopbits */
 218                result = usb_control_msg(port->serial->dev,
 219                          usb_sndctrlpipe(port->serial->dev, 0),
 220                          SUSBCRequest_SetBaudRateParityAndStopBits,
 221                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 222                          SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity |
 223                                                        SUSBCR_SPASB_1StopBit,
 224                          0,
 225                          NULL,
 226                          0,
 227                          KOBIL_TIMEOUT
 228                );
 229                dev_dbg(dev, "%s - Send set_baudrate URB returns: %i\n", __func__, result);
 230
 231                /* reset all queues */
 232                result = usb_control_msg(port->serial->dev,
 233                          usb_sndctrlpipe(port->serial->dev, 0),
 234                          SUSBCRequest_Misc,
 235                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 236                          SUSBCR_MSC_ResetAllQueues,
 237                          0,
 238                          NULL,
 239                          0,
 240                          KOBIL_TIMEOUT
 241                );
 242                dev_dbg(dev, "%s - Send reset_all_queues URB returns: %i\n", __func__, result);
 243        }
 244        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
 245            priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
 246            priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
 247                /* start reading (Adapter B 'cause PNP string) */
 248                result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 249                dev_dbg(dev, "%s - Send read URB returns: %i\n", __func__, result);
 250        }
 251
 252        kfree(transfer_buffer);
 253        return 0;
 254}
 255
 256
 257static void kobil_close(struct usb_serial_port *port)
 258{
 259        /* FIXME: Add rts/dtr methods */
 260        usb_kill_urb(port->interrupt_out_urb);
 261        usb_kill_urb(port->interrupt_in_urb);
 262}
 263
 264
 265static void kobil_read_int_callback(struct urb *urb)
 266{
 267        int result;
 268        struct usb_serial_port *port = urb->context;
 269        unsigned char *data = urb->transfer_buffer;
 270        int status = urb->status;
 271
 272        if (status) {
 273                dev_dbg(&port->dev, "%s - Read int status not zero: %d\n", __func__, status);
 274                return;
 275        }
 276
 277        if (urb->actual_length) {
 278                usb_serial_debug_data(&port->dev, __func__, urb->actual_length,
 279                                                                        data);
 280                tty_insert_flip_string(&port->port, data, urb->actual_length);
 281                tty_flip_buffer_push(&port->port);
 282        }
 283
 284        result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
 285        dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result);
 286}
 287
 288
 289static void kobil_write_int_callback(struct urb *urb)
 290{
 291}
 292
 293
 294static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
 295                        const unsigned char *buf, int count)
 296{
 297        int length = 0;
 298        int result = 0;
 299        int todo = 0;
 300        struct kobil_private *priv;
 301
 302        if (count == 0) {
 303                dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__);
 304                return 0;
 305        }
 306
 307        priv = usb_get_serial_port_data(port);
 308
 309        if (count > (KOBIL_BUF_LENGTH - priv->filled)) {
 310                dev_dbg(&port->dev, "%s - Error: write request bigger than buffer size\n", __func__);
 311                return -ENOMEM;
 312        }
 313
 314        /* Copy data to buffer */
 315        memcpy(priv->buf + priv->filled, buf, count);
 316        usb_serial_debug_data(&port->dev, __func__, count, priv->buf + priv->filled);
 317        priv->filled = priv->filled + count;
 318
 319        /* only send complete block. TWIN, KAAN SIM and adapter K
 320           use the same protocol. */
 321        if (((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) ||
 322             ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4)))) {
 323                /* stop reading (except TWIN and KAAN SIM) */
 324                if ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID)
 325                        || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID))
 326                        usb_kill_urb(port->interrupt_in_urb);
 327
 328                todo = priv->filled - priv->cur_pos;
 329
 330                while (todo > 0) {
 331                        /* max 8 byte in one urb (endpoint size) */
 332                        length = min(todo, port->interrupt_out_size);
 333                        /* copy data to transfer buffer */
 334                        memcpy(port->interrupt_out_buffer,
 335                                        priv->buf + priv->cur_pos, length);
 336                        port->interrupt_out_urb->transfer_buffer_length = length;
 337
 338                        priv->cur_pos = priv->cur_pos + length;
 339                        result = usb_submit_urb(port->interrupt_out_urb,
 340                                        GFP_ATOMIC);
 341                        dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result);
 342                        todo = priv->filled - priv->cur_pos;
 343
 344                        if (todo > 0)
 345                                msleep(24);
 346                }
 347
 348                priv->filled = 0;
 349                priv->cur_pos = 0;
 350
 351                /* start reading (except TWIN and KAAN SIM) */
 352                if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
 353                        priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
 354                        result = usb_submit_urb(port->interrupt_in_urb,
 355                                        GFP_ATOMIC);
 356                        dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result);
 357                }
 358        }
 359        return count;
 360}
 361
 362
 363static int kobil_write_room(struct tty_struct *tty)
 364{
 365        /* FIXME */
 366        return 8;
 367}
 368
 369
 370static int kobil_tiocmget(struct tty_struct *tty)
 371{
 372        struct usb_serial_port *port = tty->driver_data;
 373        struct kobil_private *priv;
 374        int result;
 375        unsigned char *transfer_buffer;
 376        int transfer_buffer_length = 8;
 377
 378        priv = usb_get_serial_port_data(port);
 379        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID
 380                        || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
 381                /* This device doesn't support ioctl calls */
 382                return -EINVAL;
 383        }
 384
 385        /* allocate memory for transfer buffer */
 386        transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
 387        if (!transfer_buffer)
 388                return -ENOMEM;
 389
 390        result = usb_control_msg(port->serial->dev,
 391                          usb_rcvctrlpipe(port->serial->dev, 0),
 392                          SUSBCRequest_GetStatusLineState,
 393                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
 394                          0,
 395                          0,
 396                          transfer_buffer,
 397                          transfer_buffer_length,
 398                          KOBIL_TIMEOUT);
 399
 400        dev_dbg(&port->dev, "Send get_status_line_state URB returns: %i\n",
 401                        result);
 402        if (result < 1) {
 403                if (result >= 0)
 404                        result = -EIO;
 405                goto out_free;
 406        }
 407
 408        dev_dbg(&port->dev, "Statusline: %02x\n", transfer_buffer[0]);
 409
 410        result = 0;
 411        if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0)
 412                result = TIOCM_DSR;
 413out_free:
 414        kfree(transfer_buffer);
 415        return result;
 416}
 417
 418static int kobil_tiocmset(struct tty_struct *tty,
 419                           unsigned int set, unsigned int clear)
 420{
 421        struct usb_serial_port *port = tty->driver_data;
 422        struct device *dev = &port->dev;
 423        struct kobil_private *priv;
 424        int result;
 425        int dtr = 0;
 426        int rts = 0;
 427
 428        /* FIXME: locking ? */
 429        priv = usb_get_serial_port_data(port);
 430        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID
 431                || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
 432                /* This device doesn't support ioctl calls */
 433                return -EINVAL;
 434        }
 435
 436        if (set & TIOCM_RTS)
 437                rts = 1;
 438        if (set & TIOCM_DTR)
 439                dtr = 1;
 440        if (clear & TIOCM_RTS)
 441                rts = 0;
 442        if (clear & TIOCM_DTR)
 443                dtr = 0;
 444
 445        if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
 446                if (dtr != 0)
 447                        dev_dbg(dev, "%s - Setting DTR\n", __func__);
 448                else
 449                        dev_dbg(dev, "%s - Clearing DTR\n", __func__);
 450                result = usb_control_msg(port->serial->dev,
 451                          usb_sndctrlpipe(port->serial->dev, 0),
 452                          SUSBCRequest_SetStatusLinesOrQueues,
 453                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 454                          ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
 455                          0,
 456                          NULL,
 457                          0,
 458                          KOBIL_TIMEOUT);
 459        } else {
 460                if (rts != 0)
 461                        dev_dbg(dev, "%s - Setting RTS\n", __func__);
 462                else
 463                        dev_dbg(dev, "%s - Clearing RTS\n", __func__);
 464                result = usb_control_msg(port->serial->dev,
 465                        usb_sndctrlpipe(port->serial->dev, 0),
 466                        SUSBCRequest_SetStatusLinesOrQueues,
 467                        USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 468                        ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
 469                        0,
 470                        NULL,
 471                        0,
 472                        KOBIL_TIMEOUT);
 473        }
 474        dev_dbg(dev, "%s - Send set_status_line URB returns: %i\n", __func__, result);
 475        return (result < 0) ? result : 0;
 476}
 477
 478static void kobil_set_termios(struct tty_struct *tty,
 479                        struct usb_serial_port *port, struct ktermios *old)
 480{
 481        struct kobil_private *priv;
 482        int result;
 483        unsigned short urb_val = 0;
 484        int c_cflag = tty->termios.c_cflag;
 485        speed_t speed;
 486
 487        priv = usb_get_serial_port_data(port);
 488        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
 489                        priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
 490                /* This device doesn't support ioctl calls */
 491                tty_termios_copy_hw(&tty->termios, old);
 492                return;
 493        }
 494
 495        speed = tty_get_baud_rate(tty);
 496        switch (speed) {
 497        case 1200:
 498                urb_val = SUSBCR_SBR_1200;
 499                break;
 500        default:
 501                speed = 9600;
 502                /* fall through */
 503        case 9600:
 504                urb_val = SUSBCR_SBR_9600;
 505                break;
 506        }
 507        urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits :
 508                                                        SUSBCR_SPASB_1StopBit;
 509        if (c_cflag & PARENB) {
 510                if  (c_cflag & PARODD)
 511                        urb_val |= SUSBCR_SPASB_OddParity;
 512                else
 513                        urb_val |= SUSBCR_SPASB_EvenParity;
 514        } else
 515                urb_val |= SUSBCR_SPASB_NoParity;
 516        tty->termios.c_cflag &= ~CMSPAR;
 517        tty_encode_baud_rate(tty, speed, speed);
 518
 519        result = usb_control_msg(port->serial->dev,
 520                  usb_sndctrlpipe(port->serial->dev, 0),
 521                  SUSBCRequest_SetBaudRateParityAndStopBits,
 522                  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 523                  urb_val,
 524                  0,
 525                  NULL,
 526                  0,
 527                  KOBIL_TIMEOUT
 528                );
 529}
 530
 531static int kobil_ioctl(struct tty_struct *tty,
 532                                        unsigned int cmd, unsigned long arg)
 533{
 534        struct usb_serial_port *port = tty->driver_data;
 535        struct kobil_private *priv = usb_get_serial_port_data(port);
 536        int result;
 537
 538        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
 539                        priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
 540                /* This device doesn't support ioctl calls */
 541                return -ENOIOCTLCMD;
 542
 543        switch (cmd) {
 544        case TCFLSH:
 545                result = usb_control_msg(port->serial->dev,
 546                          usb_sndctrlpipe(port->serial->dev, 0),
 547                          SUSBCRequest_Misc,
 548                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 549                          SUSBCR_MSC_ResetAllQueues,
 550                          0,
 551                          NULL,
 552                          0,
 553                          KOBIL_TIMEOUT
 554                        );
 555
 556                dev_dbg(&port->dev,
 557                        "%s - Send reset_all_queues (FLUSH) URB returns: %i\n",
 558                        __func__, result);
 559                return (result < 0) ? -EIO: 0;
 560        default:
 561                return -ENOIOCTLCMD;
 562        }
 563}
 564
 565module_usb_serial_driver(serial_drivers, id_table);
 566
 567MODULE_AUTHOR(DRIVER_AUTHOR);
 568MODULE_DESCRIPTION(DRIVER_DESC);
 569MODULE_LICENSE("GPL");
 570