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