root/drivers/char/pcmcia/scr24x_cs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. scr24x_delete
  2. scr24x_wait_ready
  3. scr24x_open
  4. scr24x_release
  5. read_chunk
  6. scr24x_read
  7. scr24x_write
  8. scr24x_config_check
  9. scr24x_probe
  10. scr24x_remove
  11. scr24x_init
  12. scr24x_exit

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

/* [<][>][^][v][top][bottom][index][help] */