linux/drivers/usb/serial/cyberjack.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 *  REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver
   4 *
   5 *  Copyright (C) 2001  REINER SCT
   6 *  Author: Matthias Bruestle
   7 *
   8 *  Contact: support@reiner-sct.com (see MAINTAINERS)
   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 *  In case of problems, please write to the contact e-mail address
  18 *  mentioned above.
  19 *
  20 *  Please note that later models of the cyberjack reader family are
  21 *  supported by a libusb-based userspace device driver.
  22 *
  23 *  Homepage: http://www.reiner-sct.de/support/treiber_cyberjack.php#linux
  24 */
  25
  26
  27#include <linux/kernel.h>
  28#include <linux/errno.h>
  29#include <linux/slab.h>
  30#include <linux/tty.h>
  31#include <linux/tty_driver.h>
  32#include <linux/tty_flip.h>
  33#include <linux/module.h>
  34#include <linux/spinlock.h>
  35#include <linux/uaccess.h>
  36#include <linux/usb.h>
  37#include <linux/usb/serial.h>
  38
  39#define CYBERJACK_LOCAL_BUF_SIZE 32
  40
  41#define DRIVER_AUTHOR "Matthias Bruestle"
  42#define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver"
  43
  44
  45#define CYBERJACK_VENDOR_ID     0x0C4B
  46#define CYBERJACK_PRODUCT_ID    0x0100
  47
  48/* Function prototypes */
  49static int cyberjack_port_probe(struct usb_serial_port *port);
  50static int cyberjack_port_remove(struct usb_serial_port *port);
  51static int  cyberjack_open(struct tty_struct *tty,
  52        struct usb_serial_port *port);
  53static void cyberjack_close(struct usb_serial_port *port);
  54static int cyberjack_write(struct tty_struct *tty,
  55        struct usb_serial_port *port, const unsigned char *buf, int count);
  56static int cyberjack_write_room(struct tty_struct *tty);
  57static void cyberjack_read_int_callback(struct urb *urb);
  58static void cyberjack_read_bulk_callback(struct urb *urb);
  59static void cyberjack_write_bulk_callback(struct urb *urb);
  60
  61static const struct usb_device_id id_table[] = {
  62        { USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) },
  63        { }                     /* Terminating entry */
  64};
  65
  66MODULE_DEVICE_TABLE(usb, id_table);
  67
  68static struct usb_serial_driver cyberjack_device = {
  69        .driver = {
  70                .owner =        THIS_MODULE,
  71                .name =         "cyberjack",
  72        },
  73        .description =          "Reiner SCT Cyberjack USB card reader",
  74        .id_table =             id_table,
  75        .num_ports =            1,
  76        .num_bulk_out =         1,
  77        .port_probe =           cyberjack_port_probe,
  78        .port_remove =          cyberjack_port_remove,
  79        .open =                 cyberjack_open,
  80        .close =                cyberjack_close,
  81        .write =                cyberjack_write,
  82        .write_room =           cyberjack_write_room,
  83        .read_int_callback =    cyberjack_read_int_callback,
  84        .read_bulk_callback =   cyberjack_read_bulk_callback,
  85        .write_bulk_callback =  cyberjack_write_bulk_callback,
  86};
  87
  88static struct usb_serial_driver * const serial_drivers[] = {
  89        &cyberjack_device, NULL
  90};
  91
  92struct cyberjack_private {
  93        spinlock_t      lock;           /* Lock for SMP */
  94        short           rdtodo;         /* Bytes still to read */
  95        unsigned char   wrbuf[5*64];    /* Buffer for collecting data to write */
  96        short           wrfilled;       /* Overall data size we already got */
  97        short           wrsent;         /* Data already sent */
  98};
  99
 100static int cyberjack_port_probe(struct usb_serial_port *port)
 101{
 102        struct cyberjack_private *priv;
 103        int result;
 104
 105        priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
 106        if (!priv)
 107                return -ENOMEM;
 108
 109        spin_lock_init(&priv->lock);
 110        priv->rdtodo = 0;
 111        priv->wrfilled = 0;
 112        priv->wrsent = 0;
 113
 114        usb_set_serial_port_data(port, priv);
 115
 116        result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 117        if (result)
 118                dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
 119
 120        return 0;
 121}
 122
 123static int cyberjack_port_remove(struct usb_serial_port *port)
 124{
 125        struct cyberjack_private *priv;
 126
 127        usb_kill_urb(port->interrupt_in_urb);
 128
 129        priv = usb_get_serial_port_data(port);
 130        kfree(priv);
 131
 132        return 0;
 133}
 134
 135static int  cyberjack_open(struct tty_struct *tty,
 136                                        struct usb_serial_port *port)
 137{
 138        struct cyberjack_private *priv;
 139        unsigned long flags;
 140
 141        dev_dbg(&port->dev, "%s - usb_clear_halt\n", __func__);
 142        usb_clear_halt(port->serial->dev, port->write_urb->pipe);
 143
 144        priv = usb_get_serial_port_data(port);
 145        spin_lock_irqsave(&priv->lock, flags);
 146        priv->rdtodo = 0;
 147        priv->wrfilled = 0;
 148        priv->wrsent = 0;
 149        spin_unlock_irqrestore(&priv->lock, flags);
 150
 151        return 0;
 152}
 153
 154static void cyberjack_close(struct usb_serial_port *port)
 155{
 156        usb_kill_urb(port->write_urb);
 157        usb_kill_urb(port->read_urb);
 158}
 159
 160static int cyberjack_write(struct tty_struct *tty,
 161        struct usb_serial_port *port, const unsigned char *buf, int count)
 162{
 163        struct device *dev = &port->dev;
 164        struct cyberjack_private *priv = usb_get_serial_port_data(port);
 165        unsigned long flags;
 166        int result;
 167        int wrexpected;
 168
 169        if (count == 0) {
 170                dev_dbg(dev, "%s - write request of 0 bytes\n", __func__);
 171                return 0;
 172        }
 173
 174        if (!test_and_clear_bit(0, &port->write_urbs_free)) {
 175                dev_dbg(dev, "%s - already writing\n", __func__);
 176                return 0;
 177        }
 178
 179        spin_lock_irqsave(&priv->lock, flags);
 180
 181        if (count+priv->wrfilled > sizeof(priv->wrbuf)) {
 182                /* To much data for buffer. Reset buffer. */
 183                priv->wrfilled = 0;
 184                spin_unlock_irqrestore(&priv->lock, flags);
 185                set_bit(0, &port->write_urbs_free);
 186                return 0;
 187        }
 188
 189        /* Copy data */
 190        memcpy(priv->wrbuf + priv->wrfilled, buf, count);
 191
 192        usb_serial_debug_data(dev, __func__, count, priv->wrbuf + priv->wrfilled);
 193        priv->wrfilled += count;
 194
 195        if (priv->wrfilled >= 3) {
 196                wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
 197                dev_dbg(dev, "%s - expected data: %d\n", __func__, wrexpected);
 198        } else
 199                wrexpected = sizeof(priv->wrbuf);
 200
 201        if (priv->wrfilled >= wrexpected) {
 202                /* We have enough data to begin transmission */
 203                int length;
 204
 205                dev_dbg(dev, "%s - transmitting data (frame 1)\n", __func__);
 206                length = (wrexpected > port->bulk_out_size) ?
 207                                        port->bulk_out_size : wrexpected;
 208
 209                memcpy(port->write_urb->transfer_buffer, priv->wrbuf, length);
 210                priv->wrsent = length;
 211
 212                /* set up our urb */
 213                port->write_urb->transfer_buffer_length = length;
 214
 215                /* send the data out the bulk port */
 216                result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 217                if (result) {
 218                        dev_err(&port->dev,
 219                                "%s - failed submitting write urb, error %d\n",
 220                                __func__, result);
 221                        /* Throw away data. No better idea what to do with it. */
 222                        priv->wrfilled = 0;
 223                        priv->wrsent = 0;
 224                        spin_unlock_irqrestore(&priv->lock, flags);
 225                        set_bit(0, &port->write_urbs_free);
 226                        return 0;
 227                }
 228
 229                dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent);
 230                dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled);
 231
 232                if (priv->wrsent >= priv->wrfilled) {
 233                        dev_dbg(dev, "%s - buffer cleaned\n", __func__);
 234                        memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
 235                        priv->wrfilled = 0;
 236                        priv->wrsent = 0;
 237                }
 238        }
 239
 240        spin_unlock_irqrestore(&priv->lock, flags);
 241
 242        return count;
 243}
 244
 245static int cyberjack_write_room(struct tty_struct *tty)
 246{
 247        /* FIXME: .... */
 248        return CYBERJACK_LOCAL_BUF_SIZE;
 249}
 250
 251static void cyberjack_read_int_callback(struct urb *urb)
 252{
 253        struct usb_serial_port *port = urb->context;
 254        struct cyberjack_private *priv = usb_get_serial_port_data(port);
 255        struct device *dev = &port->dev;
 256        unsigned char *data = urb->transfer_buffer;
 257        int status = urb->status;
 258        unsigned long flags;
 259        int result;
 260
 261        /* the urb might have been killed. */
 262        if (status)
 263                return;
 264
 265        usb_serial_debug_data(dev, __func__, urb->actual_length, data);
 266
 267        /* React only to interrupts signaling a bulk_in transfer */
 268        if (urb->actual_length == 4 && data[0] == 0x01) {
 269                short old_rdtodo;
 270
 271                /* This is a announcement of coming bulk_ins. */
 272                unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3;
 273
 274                spin_lock_irqsave(&priv->lock, flags);
 275
 276                old_rdtodo = priv->rdtodo;
 277
 278                if (old_rdtodo > SHRT_MAX - size) {
 279                        dev_dbg(dev, "To many bulk_in urbs to do.\n");
 280                        spin_unlock_irqrestore(&priv->lock, flags);
 281                        goto resubmit;
 282                }
 283
 284                /* "+=" is probably more fault tolerant than "=" */
 285                priv->rdtodo += size;
 286
 287                dev_dbg(dev, "%s - rdtodo: %d\n", __func__, priv->rdtodo);
 288
 289                spin_unlock_irqrestore(&priv->lock, flags);
 290
 291                if (!old_rdtodo) {
 292                        result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 293                        if (result)
 294                                dev_err(dev, "%s - failed resubmitting read urb, error %d\n",
 295                                        __func__, result);
 296                        dev_dbg(dev, "%s - usb_submit_urb(read urb)\n", __func__);
 297                }
 298        }
 299
 300resubmit:
 301        result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
 302        if (result)
 303                dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
 304        dev_dbg(dev, "%s - usb_submit_urb(int urb)\n", __func__);
 305}
 306
 307static void cyberjack_read_bulk_callback(struct urb *urb)
 308{
 309        struct usb_serial_port *port = urb->context;
 310        struct cyberjack_private *priv = usb_get_serial_port_data(port);
 311        struct device *dev = &port->dev;
 312        unsigned char *data = urb->transfer_buffer;
 313        unsigned long flags;
 314        short todo;
 315        int result;
 316        int status = urb->status;
 317
 318        usb_serial_debug_data(dev, __func__, urb->actual_length, data);
 319        if (status) {
 320                dev_dbg(dev, "%s - nonzero read bulk status received: %d\n",
 321                        __func__, status);
 322                return;
 323        }
 324
 325        if (urb->actual_length) {
 326                tty_insert_flip_string(&port->port, data, urb->actual_length);
 327                tty_flip_buffer_push(&port->port);
 328        }
 329
 330        spin_lock_irqsave(&priv->lock, flags);
 331
 332        /* Reduce urbs to do by one. */
 333        priv->rdtodo -= urb->actual_length;
 334        /* Just to be sure */
 335        if (priv->rdtodo < 0)
 336                priv->rdtodo = 0;
 337        todo = priv->rdtodo;
 338
 339        spin_unlock_irqrestore(&priv->lock, flags);
 340
 341        dev_dbg(dev, "%s - rdtodo: %d\n", __func__, todo);
 342
 343        /* Continue to read if we have still urbs to do. */
 344        if (todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/) {
 345                result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 346                if (result)
 347                        dev_err(dev, "%s - failed resubmitting read urb, error %d\n",
 348                                __func__, result);
 349                dev_dbg(dev, "%s - usb_submit_urb(read urb)\n", __func__);
 350        }
 351}
 352
 353static void cyberjack_write_bulk_callback(struct urb *urb)
 354{
 355        struct usb_serial_port *port = urb->context;
 356        struct cyberjack_private *priv = usb_get_serial_port_data(port);
 357        struct device *dev = &port->dev;
 358        int status = urb->status;
 359        unsigned long flags;
 360
 361        set_bit(0, &port->write_urbs_free);
 362        if (status) {
 363                dev_dbg(dev, "%s - nonzero write bulk status received: %d\n",
 364                        __func__, status);
 365                return;
 366        }
 367
 368        spin_lock_irqsave(&priv->lock, flags);
 369
 370        /* only do something if we have more data to send */
 371        if (priv->wrfilled) {
 372                int length, blksize, result;
 373
 374                dev_dbg(dev, "%s - transmitting data (frame n)\n", __func__);
 375
 376                length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
 377                        port->bulk_out_size : (priv->wrfilled - priv->wrsent);
 378
 379                memcpy(port->write_urb->transfer_buffer,
 380                                        priv->wrbuf + priv->wrsent, length);
 381                priv->wrsent += length;
 382
 383                /* set up our urb */
 384                port->write_urb->transfer_buffer_length = length;
 385
 386                /* send the data out the bulk port */
 387                result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 388                if (result) {
 389                        dev_err(dev, "%s - failed submitting write urb, error %d\n",
 390                                __func__, result);
 391                        /* Throw away data. No better idea what to do with it. */
 392                        priv->wrfilled = 0;
 393                        priv->wrsent = 0;
 394                        goto exit;
 395                }
 396
 397                dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent);
 398                dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled);
 399
 400                blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
 401
 402                if (priv->wrsent >= priv->wrfilled ||
 403                                        priv->wrsent >= blksize) {
 404                        dev_dbg(dev, "%s - buffer cleaned\n", __func__);
 405                        memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
 406                        priv->wrfilled = 0;
 407                        priv->wrsent = 0;
 408                }
 409        }
 410
 411exit:
 412        spin_unlock_irqrestore(&priv->lock, flags);
 413        usb_serial_port_softint(port);
 414}
 415
 416module_usb_serial_driver(serial_drivers, id_table);
 417
 418MODULE_AUTHOR(DRIVER_AUTHOR);
 419MODULE_DESCRIPTION(DRIVER_DESC);
 420MODULE_LICENSE("GPL");
 421