Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * HID raw devices, giving access to raw HID events.
0004  *
0005  * In comparison to hiddev, this device does not process the
0006  * hid events at all (no parsing, no lookups). This lets applications
0007  * to work on raw hid events as they want to, and avoids a need to
0008  * use a transport-specific userspace libhid/libusb libraries.
0009  *
0010  *  Copyright (c) 2007-2014 Jiri Kosina
0011  */
0012 
0013 
0014 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0015 
0016 #include <linux/fs.h>
0017 #include <linux/module.h>
0018 #include <linux/errno.h>
0019 #include <linux/kernel.h>
0020 #include <linux/init.h>
0021 #include <linux/cdev.h>
0022 #include <linux/poll.h>
0023 #include <linux/device.h>
0024 #include <linux/major.h>
0025 #include <linux/slab.h>
0026 #include <linux/hid.h>
0027 #include <linux/mutex.h>
0028 #include <linux/sched/signal.h>
0029 #include <linux/string.h>
0030 
0031 #include <linux/hidraw.h>
0032 
0033 static int hidraw_major;
0034 static struct cdev hidraw_cdev;
0035 static struct class *hidraw_class;
0036 static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
0037 static DECLARE_RWSEM(minors_rwsem);
0038 
0039 static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
0040 {
0041     struct hidraw_list *list = file->private_data;
0042     int ret = 0, len;
0043     DECLARE_WAITQUEUE(wait, current);
0044 
0045     mutex_lock(&list->read_mutex);
0046 
0047     while (ret == 0) {
0048         if (list->head == list->tail) {
0049             add_wait_queue(&list->hidraw->wait, &wait);
0050             set_current_state(TASK_INTERRUPTIBLE);
0051 
0052             while (list->head == list->tail) {
0053                 if (signal_pending(current)) {
0054                     ret = -ERESTARTSYS;
0055                     break;
0056                 }
0057                 if (!list->hidraw->exist) {
0058                     ret = -EIO;
0059                     break;
0060                 }
0061                 if (file->f_flags & O_NONBLOCK) {
0062                     ret = -EAGAIN;
0063                     break;
0064                 }
0065 
0066                 /* allow O_NONBLOCK to work well from other threads */
0067                 mutex_unlock(&list->read_mutex);
0068                 schedule();
0069                 mutex_lock(&list->read_mutex);
0070                 set_current_state(TASK_INTERRUPTIBLE);
0071             }
0072 
0073             set_current_state(TASK_RUNNING);
0074             remove_wait_queue(&list->hidraw->wait, &wait);
0075         }
0076 
0077         if (ret)
0078             goto out;
0079 
0080         len = list->buffer[list->tail].len > count ?
0081             count : list->buffer[list->tail].len;
0082 
0083         if (list->buffer[list->tail].value) {
0084             if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
0085                 ret = -EFAULT;
0086                 goto out;
0087             }
0088             ret = len;
0089         }
0090 
0091         kfree(list->buffer[list->tail].value);
0092         list->buffer[list->tail].value = NULL;
0093         list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
0094     }
0095 out:
0096     mutex_unlock(&list->read_mutex);
0097     return ret;
0098 }
0099 
0100 /*
0101  * The first byte of the report buffer is expected to be a report number.
0102  */
0103 static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type)
0104 {
0105     unsigned int minor = iminor(file_inode(file));
0106     struct hid_device *dev;
0107     __u8 *buf;
0108     int ret = 0;
0109 
0110     lockdep_assert_held(&minors_rwsem);
0111 
0112     if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
0113         ret = -ENODEV;
0114         goto out;
0115     }
0116 
0117     dev = hidraw_table[minor]->hid;
0118 
0119     if (count > HID_MAX_BUFFER_SIZE) {
0120         hid_warn(dev, "pid %d passed too large report\n",
0121              task_pid_nr(current));
0122         ret = -EINVAL;
0123         goto out;
0124     }
0125 
0126     if (count < 2) {
0127         hid_warn(dev, "pid %d passed too short report\n",
0128              task_pid_nr(current));
0129         ret = -EINVAL;
0130         goto out;
0131     }
0132 
0133     buf = memdup_user(buffer, count);
0134     if (IS_ERR(buf)) {
0135         ret = PTR_ERR(buf);
0136         goto out;
0137     }
0138 
0139     if ((report_type == HID_OUTPUT_REPORT) &&
0140         !(dev->quirks & HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP)) {
0141         ret = hid_hw_output_report(dev, buf, count);
0142         /*
0143          * compatibility with old implementation of USB-HID and I2C-HID:
0144          * if the device does not support receiving output reports,
0145          * on an interrupt endpoint, fallback to SET_REPORT HID command.
0146          */
0147         if (ret != -ENOSYS)
0148             goto out_free;
0149     }
0150 
0151     ret = hid_hw_raw_request(dev, buf[0], buf, count, report_type,
0152                 HID_REQ_SET_REPORT);
0153 
0154 out_free:
0155     kfree(buf);
0156 out:
0157     return ret;
0158 }
0159 
0160 static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
0161 {
0162     ssize_t ret;
0163     down_read(&minors_rwsem);
0164     ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT);
0165     up_read(&minors_rwsem);
0166     return ret;
0167 }
0168 
0169 
0170 /*
0171  * This function performs a Get_Report transfer over the control endpoint
0172  * per section 7.2.1 of the HID specification, version 1.1.  The first byte
0173  * of buffer is the report number to request, or 0x0 if the device does not
0174  * use numbered reports. The report_type parameter can be HID_FEATURE_REPORT
0175  * or HID_INPUT_REPORT.
0176  */
0177 static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type)
0178 {
0179     unsigned int minor = iminor(file_inode(file));
0180     struct hid_device *dev;
0181     __u8 *buf;
0182     int ret = 0, len;
0183     unsigned char report_number;
0184 
0185     lockdep_assert_held(&minors_rwsem);
0186 
0187     if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
0188         ret = -ENODEV;
0189         goto out;
0190     }
0191 
0192     dev = hidraw_table[minor]->hid;
0193 
0194     if (!dev->ll_driver->raw_request) {
0195         ret = -ENODEV;
0196         goto out;
0197     }
0198 
0199     if (count > HID_MAX_BUFFER_SIZE) {
0200         hid_warn(dev, "pid %d passed too large report\n",
0201             task_pid_nr(current));
0202         ret = -EINVAL;
0203         goto out;
0204     }
0205 
0206     if (count < 2) {
0207         hid_warn(dev, "pid %d passed too short report\n",
0208             task_pid_nr(current));
0209         ret = -EINVAL;
0210         goto out;
0211     }
0212 
0213     buf = kmalloc(count, GFP_KERNEL);
0214     if (!buf) {
0215         ret = -ENOMEM;
0216         goto out;
0217     }
0218 
0219     /*
0220      * Read the first byte from the user. This is the report number,
0221      * which is passed to hid_hw_raw_request().
0222      */
0223     if (copy_from_user(&report_number, buffer, 1)) {
0224         ret = -EFAULT;
0225         goto out_free;
0226     }
0227 
0228     ret = hid_hw_raw_request(dev, report_number, buf, count, report_type,
0229                  HID_REQ_GET_REPORT);
0230 
0231     if (ret < 0)
0232         goto out_free;
0233 
0234     len = (ret < count) ? ret : count;
0235 
0236     if (copy_to_user(buffer, buf, len)) {
0237         ret = -EFAULT;
0238         goto out_free;
0239     }
0240 
0241     ret = len;
0242 
0243 out_free:
0244     kfree(buf);
0245 out:
0246     return ret;
0247 }
0248 
0249 static __poll_t hidraw_poll(struct file *file, poll_table *wait)
0250 {
0251     struct hidraw_list *list = file->private_data;
0252     __poll_t mask = EPOLLOUT | EPOLLWRNORM; /* hidraw is always writable */
0253 
0254     poll_wait(file, &list->hidraw->wait, wait);
0255     if (list->head != list->tail)
0256         mask |= EPOLLIN | EPOLLRDNORM;
0257     if (!list->hidraw->exist)
0258         mask |= EPOLLERR | EPOLLHUP;
0259     return mask;
0260 }
0261 
0262 static int hidraw_open(struct inode *inode, struct file *file)
0263 {
0264     unsigned int minor = iminor(inode);
0265     struct hidraw *dev;
0266     struct hidraw_list *list;
0267     unsigned long flags;
0268     int err = 0;
0269 
0270     if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
0271         err = -ENOMEM;
0272         goto out;
0273     }
0274 
0275     down_read(&minors_rwsem);
0276     if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
0277         err = -ENODEV;
0278         goto out_unlock;
0279     }
0280 
0281     dev = hidraw_table[minor];
0282     if (!dev->open++) {
0283         err = hid_hw_power(dev->hid, PM_HINT_FULLON);
0284         if (err < 0) {
0285             dev->open--;
0286             goto out_unlock;
0287         }
0288 
0289         err = hid_hw_open(dev->hid);
0290         if (err < 0) {
0291             hid_hw_power(dev->hid, PM_HINT_NORMAL);
0292             dev->open--;
0293             goto out_unlock;
0294         }
0295     }
0296 
0297     list->hidraw = hidraw_table[minor];
0298     mutex_init(&list->read_mutex);
0299     spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
0300     list_add_tail(&list->node, &hidraw_table[minor]->list);
0301     spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
0302     file->private_data = list;
0303 out_unlock:
0304     up_read(&minors_rwsem);
0305 out:
0306     if (err < 0)
0307         kfree(list);
0308     return err;
0309 
0310 }
0311 
0312 static int hidraw_fasync(int fd, struct file *file, int on)
0313 {
0314     struct hidraw_list *list = file->private_data;
0315 
0316     return fasync_helper(fd, file, on, &list->fasync);
0317 }
0318 
0319 static void drop_ref(struct hidraw *hidraw, int exists_bit)
0320 {
0321     if (exists_bit) {
0322         hidraw->exist = 0;
0323         if (hidraw->open) {
0324             hid_hw_close(hidraw->hid);
0325             wake_up_interruptible(&hidraw->wait);
0326         }
0327         device_destroy(hidraw_class,
0328                    MKDEV(hidraw_major, hidraw->minor));
0329     } else {
0330         --hidraw->open;
0331     }
0332     if (!hidraw->open) {
0333         if (!hidraw->exist) {
0334             hidraw_table[hidraw->minor] = NULL;
0335             kfree(hidraw);
0336         } else {
0337             /* close device for last reader */
0338             hid_hw_close(hidraw->hid);
0339             hid_hw_power(hidraw->hid, PM_HINT_NORMAL);
0340         }
0341     }
0342 }
0343 
0344 static int hidraw_release(struct inode * inode, struct file * file)
0345 {
0346     unsigned int minor = iminor(inode);
0347     struct hidraw_list *list = file->private_data;
0348     unsigned long flags;
0349 
0350     down_write(&minors_rwsem);
0351 
0352     spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
0353     for (int i = list->tail; i < list->head; i++)
0354         kfree(list->buffer[i].value);
0355     list_del(&list->node);
0356     spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
0357     kfree(list);
0358 
0359     drop_ref(hidraw_table[minor], 0);
0360 
0361     up_write(&minors_rwsem);
0362     return 0;
0363 }
0364 
0365 static long hidraw_ioctl(struct file *file, unsigned int cmd,
0366                             unsigned long arg)
0367 {
0368     struct inode *inode = file_inode(file);
0369     unsigned int minor = iminor(inode);
0370     long ret = 0;
0371     struct hidraw *dev;
0372     void __user *user_arg = (void __user*) arg;
0373 
0374     down_read(&minors_rwsem);
0375     dev = hidraw_table[minor];
0376     if (!dev || !dev->exist) {
0377         ret = -ENODEV;
0378         goto out;
0379     }
0380 
0381     switch (cmd) {
0382         case HIDIOCGRDESCSIZE:
0383             if (put_user(dev->hid->rsize, (int __user *)arg))
0384                 ret = -EFAULT;
0385             break;
0386 
0387         case HIDIOCGRDESC:
0388             {
0389                 __u32 len;
0390 
0391                 if (get_user(len, (int __user *)arg))
0392                     ret = -EFAULT;
0393                 else if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
0394                     ret = -EINVAL;
0395                 else if (copy_to_user(user_arg + offsetof(
0396                     struct hidraw_report_descriptor,
0397                     value[0]),
0398                     dev->hid->rdesc,
0399                     min(dev->hid->rsize, len)))
0400                     ret = -EFAULT;
0401                 break;
0402             }
0403         case HIDIOCGRAWINFO:
0404             {
0405                 struct hidraw_devinfo dinfo;
0406 
0407                 dinfo.bustype = dev->hid->bus;
0408                 dinfo.vendor = dev->hid->vendor;
0409                 dinfo.product = dev->hid->product;
0410                 if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
0411                     ret = -EFAULT;
0412                 break;
0413             }
0414         default:
0415             {
0416                 struct hid_device *hid = dev->hid;
0417                 if (_IOC_TYPE(cmd) != 'H') {
0418                     ret = -EINVAL;
0419                     break;
0420                 }
0421 
0422                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSFEATURE(0))) {
0423                     int len = _IOC_SIZE(cmd);
0424                     ret = hidraw_send_report(file, user_arg, len, HID_FEATURE_REPORT);
0425                     break;
0426                 }
0427                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGFEATURE(0))) {
0428                     int len = _IOC_SIZE(cmd);
0429                     ret = hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT);
0430                     break;
0431                 }
0432 
0433                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSINPUT(0))) {
0434                     int len = _IOC_SIZE(cmd);
0435                     ret = hidraw_send_report(file, user_arg, len, HID_INPUT_REPORT);
0436                     break;
0437                 }
0438                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGINPUT(0))) {
0439                     int len = _IOC_SIZE(cmd);
0440                     ret = hidraw_get_report(file, user_arg, len, HID_INPUT_REPORT);
0441                     break;
0442                 }
0443 
0444                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSOUTPUT(0))) {
0445                     int len = _IOC_SIZE(cmd);
0446                     ret = hidraw_send_report(file, user_arg, len, HID_OUTPUT_REPORT);
0447                     break;
0448                 }
0449                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGOUTPUT(0))) {
0450                     int len = _IOC_SIZE(cmd);
0451                     ret = hidraw_get_report(file, user_arg, len, HID_OUTPUT_REPORT);
0452                     break;
0453                 }
0454 
0455                 /* Begin Read-only ioctls. */
0456                 if (_IOC_DIR(cmd) != _IOC_READ) {
0457                     ret = -EINVAL;
0458                     break;
0459                 }
0460 
0461                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
0462                     int len = strlen(hid->name) + 1;
0463                     if (len > _IOC_SIZE(cmd))
0464                         len = _IOC_SIZE(cmd);
0465                     ret = copy_to_user(user_arg, hid->name, len) ?
0466                         -EFAULT : len;
0467                     break;
0468                 }
0469 
0470                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
0471                     int len = strlen(hid->phys) + 1;
0472                     if (len > _IOC_SIZE(cmd))
0473                         len = _IOC_SIZE(cmd);
0474                     ret = copy_to_user(user_arg, hid->phys, len) ?
0475                         -EFAULT : len;
0476                     break;
0477                 }
0478 
0479                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWUNIQ(0))) {
0480                     int len = strlen(hid->uniq) + 1;
0481                     if (len > _IOC_SIZE(cmd))
0482                         len = _IOC_SIZE(cmd);
0483                     ret = copy_to_user(user_arg, hid->uniq, len) ?
0484                         -EFAULT : len;
0485                     break;
0486                 }
0487             }
0488 
0489         ret = -ENOTTY;
0490     }
0491 out:
0492     up_read(&minors_rwsem);
0493     return ret;
0494 }
0495 
0496 static const struct file_operations hidraw_ops = {
0497     .owner =        THIS_MODULE,
0498     .read =         hidraw_read,
0499     .write =        hidraw_write,
0500     .poll =         hidraw_poll,
0501     .open =         hidraw_open,
0502     .release =      hidraw_release,
0503     .unlocked_ioctl = hidraw_ioctl,
0504     .fasync =   hidraw_fasync,
0505     .compat_ioctl   = compat_ptr_ioctl,
0506     .llseek =   noop_llseek,
0507 };
0508 
0509 int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
0510 {
0511     struct hidraw *dev = hid->hidraw;
0512     struct hidraw_list *list;
0513     int ret = 0;
0514     unsigned long flags;
0515 
0516     spin_lock_irqsave(&dev->list_lock, flags);
0517     list_for_each_entry(list, &dev->list, node) {
0518         int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
0519 
0520         if (new_head == list->tail)
0521             continue;
0522 
0523         if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) {
0524             ret = -ENOMEM;
0525             break;
0526         }
0527         list->buffer[list->head].len = len;
0528         list->head = new_head;
0529         kill_fasync(&list->fasync, SIGIO, POLL_IN);
0530     }
0531     spin_unlock_irqrestore(&dev->list_lock, flags);
0532 
0533     wake_up_interruptible(&dev->wait);
0534     return ret;
0535 }
0536 EXPORT_SYMBOL_GPL(hidraw_report_event);
0537 
0538 int hidraw_connect(struct hid_device *hid)
0539 {
0540     int minor, result;
0541     struct hidraw *dev;
0542 
0543     /* we accept any HID device, all applications */
0544 
0545     dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
0546     if (!dev)
0547         return -ENOMEM;
0548 
0549     result = -EINVAL;
0550 
0551     down_write(&minors_rwsem);
0552 
0553     for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) {
0554         if (hidraw_table[minor])
0555             continue;
0556         hidraw_table[minor] = dev;
0557         result = 0;
0558         break;
0559     }
0560 
0561     if (result) {
0562         up_write(&minors_rwsem);
0563         kfree(dev);
0564         goto out;
0565     }
0566 
0567     dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor),
0568                  NULL, "%s%d", "hidraw", minor);
0569 
0570     if (IS_ERR(dev->dev)) {
0571         hidraw_table[minor] = NULL;
0572         up_write(&minors_rwsem);
0573         result = PTR_ERR(dev->dev);
0574         kfree(dev);
0575         goto out;
0576     }
0577 
0578     init_waitqueue_head(&dev->wait);
0579     spin_lock_init(&dev->list_lock);
0580     INIT_LIST_HEAD(&dev->list);
0581 
0582     dev->hid = hid;
0583     dev->minor = minor;
0584 
0585     dev->exist = 1;
0586     hid->hidraw = dev;
0587 
0588     up_write(&minors_rwsem);
0589 out:
0590     return result;
0591 
0592 }
0593 EXPORT_SYMBOL_GPL(hidraw_connect);
0594 
0595 void hidraw_disconnect(struct hid_device *hid)
0596 {
0597     struct hidraw *hidraw = hid->hidraw;
0598 
0599     down_write(&minors_rwsem);
0600 
0601     drop_ref(hidraw, 1);
0602 
0603     up_write(&minors_rwsem);
0604 }
0605 EXPORT_SYMBOL_GPL(hidraw_disconnect);
0606 
0607 int __init hidraw_init(void)
0608 {
0609     int result;
0610     dev_t dev_id;
0611 
0612     result = alloc_chrdev_region(&dev_id, HIDRAW_FIRST_MINOR,
0613             HIDRAW_MAX_DEVICES, "hidraw");
0614     if (result < 0) {
0615         pr_warn("can't get major number\n");
0616         goto out;
0617     }
0618 
0619     hidraw_major = MAJOR(dev_id);
0620 
0621     hidraw_class = class_create(THIS_MODULE, "hidraw");
0622     if (IS_ERR(hidraw_class)) {
0623         result = PTR_ERR(hidraw_class);
0624         goto error_cdev;
0625     }
0626 
0627         cdev_init(&hidraw_cdev, &hidraw_ops);
0628     result = cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES);
0629     if (result < 0)
0630         goto error_class;
0631 
0632     pr_info("raw HID events driver (C) Jiri Kosina\n");
0633 out:
0634     return result;
0635 
0636 error_class:
0637     class_destroy(hidraw_class);
0638 error_cdev:
0639     unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
0640     goto out;
0641 }
0642 
0643 void hidraw_exit(void)
0644 {
0645     dev_t dev_id = MKDEV(hidraw_major, 0);
0646 
0647     cdev_del(&hidraw_cdev);
0648     class_destroy(hidraw_class);
0649     unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
0650 
0651 }