linux/drivers/char/pcmcia/scr24x_cs.c
<<
>>
Prefs
   1/*
   2 * SCR24x PCMCIA Smart Card Reader Driver
   3 *
   4 * Copyright (C) 2005-2006 TL Sudheendran
   5 * Copyright (C) 2016 Lubomir Rintel
   6 *
   7 * Derived from "scr24x_v4.2.6_Release.tar.gz" driver by TL Sudheendran.
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2, or (at your option)
  12 * any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; see the file COPYING.  If not, write to
  21 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22 */
  23
  24#include <linux/device.h>
  25#include <linux/module.h>
  26#include <linux/delay.h>
  27#include <linux/cdev.h>
  28#include <linux/slab.h>
  29#include <linux/fs.h>
  30#include <linux/io.h>
  31#include <linux/uaccess.h>
  32
  33#include <pcmcia/cistpl.h>
  34#include <pcmcia/ds.h>
  35
  36#define CCID_HEADER_SIZE        10
  37#define CCID_LENGTH_OFFSET      1
  38#define CCID_MAX_LEN            271
  39
  40#define SCR24X_DATA(n)          (1 + n)
  41#define SCR24X_CMD_STATUS       7
  42#define CMD_START               0x40
  43#define CMD_WRITE_BYTE          0x41
  44#define CMD_READ_BYTE           0x42
  45#define STATUS_BUSY             0x80
  46
  47struct scr24x_dev {
  48        struct device *dev;
  49        struct cdev c_dev;
  50        unsigned char buf[CCID_MAX_LEN];
  51        int devno;
  52        struct mutex lock;
  53        struct kref refcnt;
  54        u8 __iomem *regs;
  55};
  56
  57#define SCR24X_DEVS 8
  58static DECLARE_BITMAP(scr24x_minors, SCR24X_DEVS);
  59
  60static struct class *scr24x_class;
  61static dev_t scr24x_devt;
  62
  63static void scr24x_delete(struct kref *kref)
  64{
  65        struct scr24x_dev *dev = container_of(kref, struct scr24x_dev,
  66                                                                refcnt);
  67
  68        kfree(dev);
  69}
  70
  71static int scr24x_wait_ready(struct scr24x_dev *dev)
  72{
  73        u_char status;
  74        int timeout = 100;
  75
  76        do {
  77                status = ioread8(dev->regs + SCR24X_CMD_STATUS);
  78                if (!(status & STATUS_BUSY))
  79                        return 0;
  80
  81                msleep(20);
  82        } while (--timeout);
  83
  84        return -EIO;
  85}
  86
  87static int scr24x_open(struct inode *inode, struct file *filp)
  88{
  89        struct scr24x_dev *dev = container_of(inode->i_cdev,
  90                                struct scr24x_dev, c_dev);
  91
  92        kref_get(&dev->refcnt);
  93        filp->private_data = dev;
  94
  95        return nonseekable_open(inode, filp);
  96}
  97
  98static int scr24x_release(struct inode *inode, struct file *filp)
  99{
 100        struct scr24x_dev *dev = filp->private_data;
 101
 102        /* We must not take the dev->lock here as scr24x_delete()
 103         * might be called to remove the dev structure altogether.
 104         * We don't need the lock anyway, since after the reference
 105         * acquired in probe() is released in remove() the chrdev
 106         * is already unregistered and noone can possibly acquire
 107         * a reference via open() anymore. */
 108        kref_put(&dev->refcnt, scr24x_delete);
 109        return 0;
 110}
 111
 112static int read_chunk(struct scr24x_dev *dev, size_t offset, size_t limit)
 113{
 114        size_t i, y;
 115        int ret;
 116
 117        for (i = offset; i < limit; i += 5) {
 118                iowrite8(CMD_READ_BYTE, dev->regs + SCR24X_CMD_STATUS);
 119                ret = scr24x_wait_ready(dev);
 120                if (ret < 0)
 121                        return ret;
 122
 123                for (y = 0; y < 5 && i + y < limit; y++)
 124                        dev->buf[i + y] = ioread8(dev->regs + SCR24X_DATA(y));
 125        }
 126
 127        return 0;
 128}
 129
 130static ssize_t scr24x_read(struct file *filp, char __user *buf, size_t count,
 131                                                                loff_t *ppos)
 132{
 133        struct scr24x_dev *dev = filp->private_data;
 134        int ret;
 135        int len;
 136
 137        if (count < CCID_HEADER_SIZE)
 138                return -EINVAL;
 139
 140        if (mutex_lock_interruptible(&dev->lock))
 141                return -ERESTARTSYS;
 142
 143        if (!dev->dev) {
 144                ret = -ENODEV;
 145                goto out;
 146        }
 147
 148        ret = scr24x_wait_ready(dev);
 149        if (ret < 0)
 150                goto out;
 151        len = CCID_HEADER_SIZE;
 152        ret = read_chunk(dev, 0, len);
 153        if (ret < 0)
 154                goto out;
 155
 156        len += le32_to_cpu(*(__le32 *)(&dev->buf[CCID_LENGTH_OFFSET]));
 157        if (len > sizeof(dev->buf)) {
 158                ret = -EIO;
 159                goto out;
 160        }
 161        ret = read_chunk(dev, CCID_HEADER_SIZE, len);
 162        if (ret < 0)
 163                goto out;
 164
 165        if (len < count)
 166                count = len;
 167
 168        if (copy_to_user(buf, dev->buf, count)) {
 169                ret = -EFAULT;
 170                goto out;
 171        }
 172
 173        ret = count;
 174out:
 175        mutex_unlock(&dev->lock);
 176        return ret;
 177}
 178
 179static ssize_t scr24x_write(struct file *filp, const char __user *buf,
 180                                        size_t count, loff_t *ppos)
 181{
 182        struct scr24x_dev *dev = filp->private_data;
 183        size_t i, y;
 184        int ret;
 185
 186        if (mutex_lock_interruptible(&dev->lock))
 187                return -ERESTARTSYS;
 188
 189        if (!dev->dev) {
 190                ret = -ENODEV;
 191                goto out;
 192        }
 193
 194        if (count > sizeof(dev->buf)) {
 195                ret = -EINVAL;
 196                goto out;
 197        }
 198
 199        if (copy_from_user(dev->buf, buf, count)) {
 200                ret = -EFAULT;
 201                goto out;
 202        }
 203
 204        ret = scr24x_wait_ready(dev);
 205        if (ret < 0)
 206                goto out;
 207
 208        iowrite8(CMD_START, dev->regs + SCR24X_CMD_STATUS);
 209        ret = scr24x_wait_ready(dev);
 210        if (ret < 0)
 211                goto out;
 212
 213        for (i = 0; i < count; i += 5) {
 214                for (y = 0; y < 5 && i + y < count; y++)
 215                        iowrite8(dev->buf[i + y], dev->regs + SCR24X_DATA(y));
 216
 217                iowrite8(CMD_WRITE_BYTE, dev->regs + SCR24X_CMD_STATUS);
 218                ret = scr24x_wait_ready(dev);
 219                if (ret < 0)
 220                        goto out;
 221        }
 222
 223        ret = count;
 224out:
 225        mutex_unlock(&dev->lock);
 226        return ret;
 227}
 228
 229static const struct file_operations scr24x_fops = {
 230        .owner          = THIS_MODULE,
 231        .read           = scr24x_read,
 232        .write          = scr24x_write,
 233        .open           = scr24x_open,
 234        .release        = scr24x_release,
 235        .llseek         = no_llseek,
 236};
 237
 238static int scr24x_config_check(struct pcmcia_device *link, void *priv_data)
 239{
 240        if (resource_size(link->resource[PCMCIA_IOPORT_0]) != 0x11)
 241                return -ENODEV;
 242        return pcmcia_request_io(link);
 243}
 244
 245static int scr24x_probe(struct pcmcia_device *link)
 246{
 247        struct scr24x_dev *dev;
 248        int ret;
 249
 250        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 251        if (!dev)
 252                return -ENOMEM;
 253
 254        dev->devno = find_first_zero_bit(scr24x_minors, SCR24X_DEVS);
 255        if (dev->devno >= SCR24X_DEVS) {
 256                ret = -EBUSY;
 257                goto err;
 258        }
 259
 260        mutex_init(&dev->lock);
 261        kref_init(&dev->refcnt);
 262
 263        link->priv = dev;
 264        link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 265
 266        ret = pcmcia_loop_config(link, scr24x_config_check, NULL);
 267        if (ret < 0)
 268                goto err;
 269
 270        dev->dev = &link->dev;
 271        dev->regs = devm_ioport_map(&link->dev,
 272                                link->resource[PCMCIA_IOPORT_0]->start,
 273                                resource_size(link->resource[PCMCIA_IOPORT_0]));
 274        if (!dev->regs) {
 275                ret = -EIO;
 276                goto err;
 277        }
 278
 279        cdev_init(&dev->c_dev, &scr24x_fops);
 280        dev->c_dev.owner = THIS_MODULE;
 281        dev->c_dev.ops = &scr24x_fops;
 282        ret = cdev_add(&dev->c_dev, MKDEV(MAJOR(scr24x_devt), dev->devno), 1);
 283        if (ret < 0)
 284                goto err;
 285
 286        ret = pcmcia_enable_device(link);
 287        if (ret < 0) {
 288                pcmcia_disable_device(link);
 289                goto err;
 290        }
 291
 292        device_create(scr24x_class, NULL, MKDEV(MAJOR(scr24x_devt), dev->devno),
 293                      NULL, "scr24x%d", dev->devno);
 294
 295        dev_info(&link->dev, "SCR24x Chip Card Interface\n");
 296        return 0;
 297
 298err:
 299        if (dev->devno < SCR24X_DEVS)
 300                clear_bit(dev->devno, scr24x_minors);
 301        kfree (dev);
 302        return ret;
 303}
 304
 305static void scr24x_remove(struct pcmcia_device *link)
 306{
 307        struct scr24x_dev *dev = (struct scr24x_dev *)link->priv;
 308
 309        device_destroy(scr24x_class, MKDEV(MAJOR(scr24x_devt), dev->devno));
 310        mutex_lock(&dev->lock);
 311        pcmcia_disable_device(link);
 312        cdev_del(&dev->c_dev);
 313        clear_bit(dev->devno, scr24x_minors);
 314        dev->dev = NULL;
 315        mutex_unlock(&dev->lock);
 316
 317        kref_put(&dev->refcnt, scr24x_delete);
 318}
 319
 320static const struct pcmcia_device_id scr24x_ids[] = {
 321        PCMCIA_DEVICE_PROD_ID12("HP", "PC Card Smart Card Reader",
 322                                        0x53cb94f9, 0xbfdf89a5),
 323        PCMCIA_DEVICE_PROD_ID1("SCR241 PCMCIA", 0x6271efa3),
 324        PCMCIA_DEVICE_PROD_ID1("SCR243 PCMCIA", 0x2054e8de),
 325        PCMCIA_DEVICE_PROD_ID1("SCR24x PCMCIA", 0x54a33665),
 326        PCMCIA_DEVICE_NULL
 327};
 328MODULE_DEVICE_TABLE(pcmcia, scr24x_ids);
 329
 330static struct pcmcia_driver scr24x_driver = {
 331        .owner          = THIS_MODULE,
 332        .name           = "scr24x_cs",
 333        .probe          = scr24x_probe,
 334        .remove         = scr24x_remove,
 335        .id_table       = scr24x_ids,
 336};
 337
 338static int __init scr24x_init(void)
 339{
 340        int ret;
 341
 342        scr24x_class = class_create(THIS_MODULE, "scr24x");
 343        if (IS_ERR(scr24x_class))
 344                return PTR_ERR(scr24x_class);
 345
 346        ret = alloc_chrdev_region(&scr24x_devt, 0, SCR24X_DEVS, "scr24x");
 347        if (ret < 0)  {
 348                class_destroy(scr24x_class);
 349                return ret;
 350        }
 351
 352        ret = pcmcia_register_driver(&scr24x_driver);
 353        if (ret < 0) {
 354                unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
 355                class_destroy(scr24x_class);
 356        }
 357
 358        return ret;
 359}
 360
 361static void __exit scr24x_exit(void)
 362{
 363        pcmcia_unregister_driver(&scr24x_driver);
 364        unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
 365        class_destroy(scr24x_class);
 366}
 367
 368module_init(scr24x_init);
 369module_exit(scr24x_exit);
 370
 371MODULE_AUTHOR("Lubomir Rintel");
 372MODULE_DESCRIPTION("SCR24x PCMCIA Smart Card Reader Driver");
 373MODULE_LICENSE("GPL");
 374