Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * SCR24x PCMCIA Smart Card Reader Driver
0004  *
0005  * Copyright (C) 2005-2006 TL Sudheendran
0006  * Copyright (C) 2016 Lubomir Rintel
0007  *
0008  * Derived from "scr24x_v4.2.6_Release.tar.gz" driver by TL Sudheendran.
0009  */
0010 
0011 #include <linux/device.h>
0012 #include <linux/module.h>
0013 #include <linux/delay.h>
0014 #include <linux/cdev.h>
0015 #include <linux/slab.h>
0016 #include <linux/fs.h>
0017 #include <linux/io.h>
0018 #include <linux/uaccess.h>
0019 
0020 #include <pcmcia/cistpl.h>
0021 #include <pcmcia/ds.h>
0022 
0023 #define CCID_HEADER_SIZE    10
0024 #define CCID_LENGTH_OFFSET  1
0025 #define CCID_MAX_LEN        271
0026 
0027 #define SCR24X_DATA(n)      (1 + n)
0028 #define SCR24X_CMD_STATUS   7
0029 #define CMD_START       0x40
0030 #define CMD_WRITE_BYTE      0x41
0031 #define CMD_READ_BYTE       0x42
0032 #define STATUS_BUSY     0x80
0033 
0034 struct scr24x_dev {
0035     struct device *dev;
0036     struct cdev c_dev;
0037     unsigned char buf[CCID_MAX_LEN];
0038     int devno;
0039     struct mutex lock;
0040     struct kref refcnt;
0041     u8 __iomem *regs;
0042 };
0043 
0044 #define SCR24X_DEVS 8
0045 static DECLARE_BITMAP(scr24x_minors, SCR24X_DEVS);
0046 
0047 static struct class *scr24x_class;
0048 static dev_t scr24x_devt;
0049 
0050 static void scr24x_delete(struct kref *kref)
0051 {
0052     struct scr24x_dev *dev = container_of(kref, struct scr24x_dev,
0053                                 refcnt);
0054 
0055     kfree(dev);
0056 }
0057 
0058 static int scr24x_wait_ready(struct scr24x_dev *dev)
0059 {
0060     u_char status;
0061     int timeout = 100;
0062 
0063     do {
0064         status = ioread8(dev->regs + SCR24X_CMD_STATUS);
0065         if (!(status & STATUS_BUSY))
0066             return 0;
0067 
0068         msleep(20);
0069     } while (--timeout);
0070 
0071     return -EIO;
0072 }
0073 
0074 static int scr24x_open(struct inode *inode, struct file *filp)
0075 {
0076     struct scr24x_dev *dev = container_of(inode->i_cdev,
0077                 struct scr24x_dev, c_dev);
0078 
0079     kref_get(&dev->refcnt);
0080     filp->private_data = dev;
0081 
0082     return stream_open(inode, filp);
0083 }
0084 
0085 static int scr24x_release(struct inode *inode, struct file *filp)
0086 {
0087     struct scr24x_dev *dev = filp->private_data;
0088 
0089     /* We must not take the dev->lock here as scr24x_delete()
0090      * might be called to remove the dev structure altogether.
0091      * We don't need the lock anyway, since after the reference
0092      * acquired in probe() is released in remove() the chrdev
0093      * is already unregistered and noone can possibly acquire
0094      * a reference via open() anymore. */
0095     kref_put(&dev->refcnt, scr24x_delete);
0096     return 0;
0097 }
0098 
0099 static int read_chunk(struct scr24x_dev *dev, size_t offset, size_t limit)
0100 {
0101     size_t i, y;
0102     int ret;
0103 
0104     for (i = offset; i < limit; i += 5) {
0105         iowrite8(CMD_READ_BYTE, dev->regs + SCR24X_CMD_STATUS);
0106         ret = scr24x_wait_ready(dev);
0107         if (ret < 0)
0108             return ret;
0109 
0110         for (y = 0; y < 5 && i + y < limit; y++)
0111             dev->buf[i + y] = ioread8(dev->regs + SCR24X_DATA(y));
0112     }
0113 
0114     return 0;
0115 }
0116 
0117 static ssize_t scr24x_read(struct file *filp, char __user *buf, size_t count,
0118                                 loff_t *ppos)
0119 {
0120     struct scr24x_dev *dev = filp->private_data;
0121     int ret;
0122     int len;
0123 
0124     if (count < CCID_HEADER_SIZE)
0125         return -EINVAL;
0126 
0127     if (mutex_lock_interruptible(&dev->lock))
0128         return -ERESTARTSYS;
0129 
0130     if (!dev->dev) {
0131         ret = -ENODEV;
0132         goto out;
0133     }
0134 
0135     ret = scr24x_wait_ready(dev);
0136     if (ret < 0)
0137         goto out;
0138     len = CCID_HEADER_SIZE;
0139     ret = read_chunk(dev, 0, len);
0140     if (ret < 0)
0141         goto out;
0142 
0143     len += le32_to_cpu(*(__le32 *)(&dev->buf[CCID_LENGTH_OFFSET]));
0144     if (len > sizeof(dev->buf)) {
0145         ret = -EIO;
0146         goto out;
0147     }
0148     ret = read_chunk(dev, CCID_HEADER_SIZE, len);
0149     if (ret < 0)
0150         goto out;
0151 
0152     if (len < count)
0153         count = len;
0154 
0155     if (copy_to_user(buf, dev->buf, count)) {
0156         ret = -EFAULT;
0157         goto out;
0158     }
0159 
0160     ret = count;
0161 out:
0162     mutex_unlock(&dev->lock);
0163     return ret;
0164 }
0165 
0166 static ssize_t scr24x_write(struct file *filp, const char __user *buf,
0167                     size_t count, loff_t *ppos)
0168 {
0169     struct scr24x_dev *dev = filp->private_data;
0170     size_t i, y;
0171     int ret;
0172 
0173     if (mutex_lock_interruptible(&dev->lock))
0174         return -ERESTARTSYS;
0175 
0176     if (!dev->dev) {
0177         ret = -ENODEV;
0178         goto out;
0179     }
0180 
0181     if (count > sizeof(dev->buf)) {
0182         ret = -EINVAL;
0183         goto out;
0184     }
0185 
0186     if (copy_from_user(dev->buf, buf, count)) {
0187         ret = -EFAULT;
0188         goto out;
0189     }
0190 
0191     ret = scr24x_wait_ready(dev);
0192     if (ret < 0)
0193         goto out;
0194 
0195     iowrite8(CMD_START, dev->regs + SCR24X_CMD_STATUS);
0196     ret = scr24x_wait_ready(dev);
0197     if (ret < 0)
0198         goto out;
0199 
0200     for (i = 0; i < count; i += 5) {
0201         for (y = 0; y < 5 && i + y < count; y++)
0202             iowrite8(dev->buf[i + y], dev->regs + SCR24X_DATA(y));
0203 
0204         iowrite8(CMD_WRITE_BYTE, dev->regs + SCR24X_CMD_STATUS);
0205         ret = scr24x_wait_ready(dev);
0206         if (ret < 0)
0207             goto out;
0208     }
0209 
0210     ret = count;
0211 out:
0212     mutex_unlock(&dev->lock);
0213     return ret;
0214 }
0215 
0216 static const struct file_operations scr24x_fops = {
0217     .owner      = THIS_MODULE,
0218     .read       = scr24x_read,
0219     .write      = scr24x_write,
0220     .open       = scr24x_open,
0221     .release    = scr24x_release,
0222     .llseek     = no_llseek,
0223 };
0224 
0225 static int scr24x_config_check(struct pcmcia_device *link, void *priv_data)
0226 {
0227     if (resource_size(link->resource[PCMCIA_IOPORT_0]) != 0x11)
0228         return -ENODEV;
0229     return pcmcia_request_io(link);
0230 }
0231 
0232 static int scr24x_probe(struct pcmcia_device *link)
0233 {
0234     struct scr24x_dev *dev;
0235     int ret;
0236 
0237     dev = kzalloc(sizeof(*dev), GFP_KERNEL);
0238     if (!dev)
0239         return -ENOMEM;
0240 
0241     dev->devno = find_first_zero_bit(scr24x_minors, SCR24X_DEVS);
0242     if (dev->devno >= SCR24X_DEVS) {
0243         ret = -EBUSY;
0244         goto err;
0245     }
0246 
0247     mutex_init(&dev->lock);
0248     kref_init(&dev->refcnt);
0249 
0250     link->priv = dev;
0251     link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
0252 
0253     ret = pcmcia_loop_config(link, scr24x_config_check, NULL);
0254     if (ret < 0)
0255         goto err;
0256 
0257     dev->dev = &link->dev;
0258     dev->regs = devm_ioport_map(&link->dev,
0259                 link->resource[PCMCIA_IOPORT_0]->start,
0260                 resource_size(link->resource[PCMCIA_IOPORT_0]));
0261     if (!dev->regs) {
0262         ret = -EIO;
0263         goto err;
0264     }
0265 
0266     cdev_init(&dev->c_dev, &scr24x_fops);
0267     dev->c_dev.owner = THIS_MODULE;
0268     ret = cdev_add(&dev->c_dev, MKDEV(MAJOR(scr24x_devt), dev->devno), 1);
0269     if (ret < 0)
0270         goto err;
0271 
0272     ret = pcmcia_enable_device(link);
0273     if (ret < 0) {
0274         pcmcia_disable_device(link);
0275         goto err;
0276     }
0277 
0278     device_create(scr24x_class, NULL, MKDEV(MAJOR(scr24x_devt), dev->devno),
0279               NULL, "scr24x%d", dev->devno);
0280 
0281     dev_info(&link->dev, "SCR24x Chip Card Interface\n");
0282     return 0;
0283 
0284 err:
0285     if (dev->devno < SCR24X_DEVS)
0286         clear_bit(dev->devno, scr24x_minors);
0287     kfree (dev);
0288     return ret;
0289 }
0290 
0291 static void scr24x_remove(struct pcmcia_device *link)
0292 {
0293     struct scr24x_dev *dev = (struct scr24x_dev *)link->priv;
0294 
0295     device_destroy(scr24x_class, MKDEV(MAJOR(scr24x_devt), dev->devno));
0296     mutex_lock(&dev->lock);
0297     pcmcia_disable_device(link);
0298     cdev_del(&dev->c_dev);
0299     clear_bit(dev->devno, scr24x_minors);
0300     dev->dev = NULL;
0301     mutex_unlock(&dev->lock);
0302 
0303     kref_put(&dev->refcnt, scr24x_delete);
0304 }
0305 
0306 static const struct pcmcia_device_id scr24x_ids[] = {
0307     PCMCIA_DEVICE_PROD_ID12("HP", "PC Card Smart Card Reader",
0308                     0x53cb94f9, 0xbfdf89a5),
0309     PCMCIA_DEVICE_PROD_ID1("SCR241 PCMCIA", 0x6271efa3),
0310     PCMCIA_DEVICE_PROD_ID1("SCR243 PCMCIA", 0x2054e8de),
0311     PCMCIA_DEVICE_PROD_ID1("SCR24x PCMCIA", 0x54a33665),
0312     PCMCIA_DEVICE_NULL
0313 };
0314 MODULE_DEVICE_TABLE(pcmcia, scr24x_ids);
0315 
0316 static struct pcmcia_driver scr24x_driver = {
0317     .owner      = THIS_MODULE,
0318     .name       = "scr24x_cs",
0319     .probe      = scr24x_probe,
0320     .remove     = scr24x_remove,
0321     .id_table   = scr24x_ids,
0322 };
0323 
0324 static int __init scr24x_init(void)
0325 {
0326     int ret;
0327 
0328     scr24x_class = class_create(THIS_MODULE, "scr24x");
0329     if (IS_ERR(scr24x_class))
0330         return PTR_ERR(scr24x_class);
0331 
0332     ret = alloc_chrdev_region(&scr24x_devt, 0, SCR24X_DEVS, "scr24x");
0333     if (ret < 0)  {
0334         class_destroy(scr24x_class);
0335         return ret;
0336     }
0337 
0338     ret = pcmcia_register_driver(&scr24x_driver);
0339     if (ret < 0) {
0340         unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
0341         class_destroy(scr24x_class);
0342     }
0343 
0344     return ret;
0345 }
0346 
0347 static void __exit scr24x_exit(void)
0348 {
0349     pcmcia_unregister_driver(&scr24x_driver);
0350     unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
0351     class_destroy(scr24x_class);
0352 }
0353 
0354 module_init(scr24x_init);
0355 module_exit(scr24x_exit);
0356 
0357 MODULE_AUTHOR("Lubomir Rintel");
0358 MODULE_DESCRIPTION("SCR24x PCMCIA Smart Card Reader Driver");
0359 MODULE_LICENSE("GPL");