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        dev_dbg(dev, "Hardware version: %i.%i.%i\n", transfer_buffer[0],
 194                transfer_buffer[1], transfer_buffer[2]);
 195
 196        /* get firmware version */
 197        result = usb_control_msg(port->serial->dev,
 198                          usb_rcvctrlpipe(port->serial->dev, 0),
 199                          SUSBCRequest_GetMisc,
 200                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
 201                          SUSBCR_MSC_GetFWVersion,
 202                          0,
 203                          transfer_buffer,
 204                          transfer_buffer_length,
 205                          KOBIL_TIMEOUT
 206        );
 207        dev_dbg(dev, "%s - Send get_FW_version URB returns: %i\n", __func__, result);
 208        dev_dbg(dev, "Firmware version: %i.%i.%i\n", transfer_buffer[0],
 209                transfer_buffer[1], transfer_buffer[2]);
 210
 211        if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
 212                        priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
 213                /* Setting Baudrate, Parity and Stopbits */
 214                result = usb_control_msg(port->serial->dev,
 215                          usb_sndctrlpipe(port->serial->dev, 0),
 216                          SUSBCRequest_SetBaudRateParityAndStopBits,
 217                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 218                          SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity |
 219                                                        SUSBCR_SPASB_1StopBit,
 220                          0,
 221                          NULL,
 222                          0,
 223                          KOBIL_TIMEOUT
 224                );
 225                dev_dbg(dev, "%s - Send set_baudrate URB returns: %i\n", __func__, result);
 226
 227                /* reset all queues */
 228                result = usb_control_msg(port->serial->dev,
 229                          usb_sndctrlpipe(port->serial->dev, 0),
 230                          SUSBCRequest_Misc,
 231                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 232                          SUSBCR_MSC_ResetAllQueues,
 233                          0,
 234                          NULL,
 235                          0,
 236                          KOBIL_TIMEOUT
 237                );
 238                dev_dbg(dev, "%s - Send reset_all_queues URB returns: %i\n", __func__, result);
 239        }
 240        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
 241            priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
 242            priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
 243                /* start reading (Adapter B 'cause PNP string) */
 244                result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 245                dev_dbg(dev, "%s - Send read URB returns: %i\n", __func__, result);
 246        }
 247
 248        kfree(transfer_buffer);
 249        return 0;
 250}
 251
 252
 253static void kobil_close(struct usb_serial_port *port)
 254{
 255        /* FIXME: Add rts/dtr methods */
 256        usb_kill_urb(port->interrupt_out_urb);
 257        usb_kill_urb(port->interrupt_in_urb);
 258}
 259
 260
 261static void kobil_read_int_callback(struct urb *urb)
 262{
 263        int result;
 264        struct usb_serial_port *port = urb->context;
 265        unsigned char *data = urb->transfer_buffer;
 266        int status = urb->status;
 267
 268        if (status) {
 269                dev_dbg(&port->dev, "%s - Read int status not zero: %d\n", __func__, status);
 270                return;
 271        }
 272
 273        if (urb->actual_length) {
 274                usb_serial_debug_data(&port->dev, __func__, urb->actual_length,
 275                                                                        data);
 276                tty_insert_flip_string(&port->port, data, urb->actual_length);
 277                tty_flip_buffer_push(&port->port);
 278        }
 279
 280        result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
 281        dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result);
 282}
 283
 284
 285static void kobil_write_int_callback(struct urb *urb)
 286{
 287}
 288
 289
 290static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
 291                        const unsigned char *buf, int count)
 292{
 293        int length = 0;
 294        int result = 0;
 295        int todo = 0;
 296        struct kobil_private *priv;
 297
 298        if (count == 0) {
 299                dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__);
 300                return 0;
 301        }
 302
 303        priv = usb_get_serial_port_data(port);
 304
 305        if (count > (KOBIL_BUF_LENGTH - priv->filled)) {
 306                dev_dbg(&port->dev, "%s - Error: write request bigger than buffer size\n", __func__);
 307                return -ENOMEM;
 308        }
 309
 310        /* Copy data to buffer */
 311        memcpy(priv->buf + priv->filled, buf, count);
 312        usb_serial_debug_data(&port->dev, __func__, count, priv->buf + priv->filled);
 313        priv->filled = priv->filled + count;
 314
 315        /* only send complete block. TWIN, KAAN SIM and adapter K
 316           use the same protocol. */
 317        if (((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) ||
 318             ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4)))) {
 319                /* stop reading (except TWIN and KAAN SIM) */
 320                if ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID)
 321                        || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID))
 322                        usb_kill_urb(port->interrupt_in_urb);
 323
 324                todo = priv->filled - priv->cur_pos;
 325
 326                while (todo > 0) {
 327                        /* max 8 byte in one urb (endpoint size) */
 328                        length = min(todo, port->interrupt_out_size);
 329                        /* copy data to transfer buffer */
 330                        memcpy(port->interrupt_out_buffer,
 331                                        priv->buf + priv->cur_pos, length);
 332                        port->interrupt_out_urb->transfer_buffer_length = length;
 333
 334                        priv->cur_pos = priv->cur_pos + length;
 335                        result = usb_submit_urb(port->interrupt_out_urb,
 336                                        GFP_ATOMIC);
 337                        dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result);
 338                        todo = priv->filled - priv->cur_pos;
 339
 340                        if (todo > 0)
 341                                msleep(24);
 342                }
 343
 344                priv->filled = 0;
 345                priv->cur_pos = 0;
 346
 347                /* start reading (except TWIN and KAAN SIM) */
 348                if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
 349                        priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
 350                        result = usb_submit_urb(port->interrupt_in_urb,
 351                                        GFP_ATOMIC);
 352                        dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result);
 353                }
 354        }
 355        return count;
 356}
 357
 358
 359static int kobil_write_room(struct tty_struct *tty)
 360{
 361        /* FIXME */
 362        return 8;
 363}
 364
 365
 366static int kobil_tiocmget(struct tty_struct *tty)
 367{
 368        struct usb_serial_port *port = tty->driver_data;
 369        struct kobil_private *priv;
 370        int result;
 371        unsigned char *transfer_buffer;
 372        int transfer_buffer_length = 8;
 373
 374        priv = usb_get_serial_port_data(port);
 375        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID
 376                        || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
 377                /* This device doesn't support ioctl calls */
 378                return -EINVAL;
 379        }
 380
 381        /* allocate memory for transfer buffer */
 382        transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
 383        if (!transfer_buffer)
 384                return -ENOMEM;
 385
 386        result = usb_control_msg(port->serial->dev,
 387                          usb_rcvctrlpipe(port->serial->dev, 0),
 388                          SUSBCRequest_GetStatusLineState,
 389                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
 390                          0,
 391                          0,
 392                          transfer_buffer,
 393                          transfer_buffer_length,
 394                          KOBIL_TIMEOUT);
 395
 396        dev_dbg(&port->dev, "%s - Send get_status_line_state URB returns: %i. Statusline: %02x\n",
 397                __func__, result, transfer_buffer[0]);
 398
 399        result = 0;
 400        if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0)
 401                result = TIOCM_DSR;
 402        kfree(transfer_buffer);
 403        return result;
 404}
 405
 406static int kobil_tiocmset(struct tty_struct *tty,
 407                           unsigned int set, unsigned int clear)
 408{
 409        struct usb_serial_port *port = tty->driver_data;
 410        struct device *dev = &port->dev;
 411        struct kobil_private *priv;
 412        int result;
 413        int dtr = 0;
 414        int rts = 0;
 415
 416        /* FIXME: locking ? */
 417        priv = usb_get_serial_port_data(port);
 418        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID
 419                || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
 420                /* This device doesn't support ioctl calls */
 421                return -EINVAL;
 422        }
 423
 424        if (set & TIOCM_RTS)
 425                rts = 1;
 426        if (set & TIOCM_DTR)
 427                dtr = 1;
 428        if (clear & TIOCM_RTS)
 429                rts = 0;
 430        if (clear & TIOCM_DTR)
 431                dtr = 0;
 432
 433        if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
 434                if (dtr != 0)
 435                        dev_dbg(dev, "%s - Setting DTR\n", __func__);
 436                else
 437                        dev_dbg(dev, "%s - Clearing DTR\n", __func__);
 438                result = usb_control_msg(port->serial->dev,
 439                          usb_sndctrlpipe(port->serial->dev, 0),
 440                          SUSBCRequest_SetStatusLinesOrQueues,
 441                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 442                          ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
 443                          0,
 444                          NULL,
 445                          0,
 446                          KOBIL_TIMEOUT);
 447        } else {
 448                if (rts != 0)
 449                        dev_dbg(dev, "%s - Setting RTS\n", __func__);
 450                else
 451                        dev_dbg(dev, "%s - Clearing RTS\n", __func__);
 452                result = usb_control_msg(port->serial->dev,
 453                        usb_sndctrlpipe(port->serial->dev, 0),
 454                        SUSBCRequest_SetStatusLinesOrQueues,
 455                        USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 456                        ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
 457                        0,
 458                        NULL,
 459                        0,
 460                        KOBIL_TIMEOUT);
 461        }
 462        dev_dbg(dev, "%s - Send set_status_line URB returns: %i\n", __func__, result);
 463        return (result < 0) ? result : 0;
 464}
 465
 466static void kobil_set_termios(struct tty_struct *tty,
 467                        struct usb_serial_port *port, struct ktermios *old)
 468{
 469        struct kobil_private *priv;
 470        int result;
 471        unsigned short urb_val = 0;
 472        int c_cflag = tty->termios.c_cflag;
 473        speed_t speed;
 474
 475        priv = usb_get_serial_port_data(port);
 476        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
 477                        priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
 478                /* This device doesn't support ioctl calls */
 479                tty_termios_copy_hw(&tty->termios, old);
 480                return;
 481        }
 482
 483        speed = tty_get_baud_rate(tty);
 484        switch (speed) {
 485        case 1200:
 486                urb_val = SUSBCR_SBR_1200;
 487                break;
 488        default:
 489                speed = 9600;
 490                /* fall through */
 491        case 9600:
 492                urb_val = SUSBCR_SBR_9600;
 493                break;
 494        }
 495        urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits :
 496                                                        SUSBCR_SPASB_1StopBit;
 497        if (c_cflag & PARENB) {
 498                if  (c_cflag & PARODD)
 499                        urb_val |= SUSBCR_SPASB_OddParity;
 500                else
 501                        urb_val |= SUSBCR_SPASB_EvenParity;
 502        } else
 503                urb_val |= SUSBCR_SPASB_NoParity;
 504        tty->termios.c_cflag &= ~CMSPAR;
 505        tty_encode_baud_rate(tty, speed, speed);
 506
 507        result = usb_control_msg(port->serial->dev,
 508                  usb_sndctrlpipe(port->serial->dev, 0),
 509                  SUSBCRequest_SetBaudRateParityAndStopBits,
 510                  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 511                  urb_val,
 512                  0,
 513                  NULL,
 514                  0,
 515                  KOBIL_TIMEOUT
 516                );
 517}
 518
 519static int kobil_ioctl(struct tty_struct *tty,
 520                                        unsigned int cmd, unsigned long arg)
 521{
 522        struct usb_serial_port *port = tty->driver_data;
 523        struct kobil_private *priv = usb_get_serial_port_data(port);
 524        int result;
 525
 526        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
 527                        priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
 528                /* This device doesn't support ioctl calls */
 529                return -ENOIOCTLCMD;
 530
 531        switch (cmd) {
 532        case TCFLSH:
 533                result = usb_control_msg(port->serial->dev,
 534                          usb_sndctrlpipe(port->serial->dev, 0),
 535                          SUSBCRequest_Misc,
 536                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 537                          SUSBCR_MSC_ResetAllQueues,
 538                          0,
 539                          NULL,
 540                          0,
 541                          KOBIL_TIMEOUT
 542                        );
 543
 544                dev_dbg(&port->dev,
 545                        "%s - Send reset_all_queues (FLUSH) URB returns: %i\n",
 546                        __func__, result);
 547                return (result < 0) ? -EIO: 0;
 548        default:
 549                return -ENOIOCTLCMD;
 550        }
 551}
 552
 553module_usb_serial_driver(serial_drivers, id_table);
 554
 555MODULE_AUTHOR(DRIVER_AUTHOR);
 556MODULE_DESCRIPTION(DRIVER_DESC);
 557MODULE_LICENSE("GPL");
 558