root/drivers/hid/hidraw.c

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

DEFINITIONS

This source file includes following definitions.
  1. hidraw_read
  2. hidraw_send_report
  3. hidraw_write
  4. hidraw_get_report
  5. hidraw_poll
  6. hidraw_open
  7. hidraw_fasync
  8. drop_ref
  9. hidraw_release
  10. hidraw_ioctl
  11. hidraw_report_event
  12. hidraw_connect
  13. hidraw_disconnect
  14. hidraw_init
  15. hidraw_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * HID raw devices, giving access to raw HID events.
   4  *
   5  * In comparison to hiddev, this device does not process the
   6  * hid events at all (no parsing, no lookups). This lets applications
   7  * to work on raw hid events as they want to, and avoids a need to
   8  * use a transport-specific userspace libhid/libusb libraries.
   9  *
  10  *  Copyright (c) 2007-2014 Jiri Kosina
  11  */
  12 
  13 
  14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  15 
  16 #include <linux/fs.h>
  17 #include <linux/module.h>
  18 #include <linux/errno.h>
  19 #include <linux/kernel.h>
  20 #include <linux/init.h>
  21 #include <linux/cdev.h>
  22 #include <linux/poll.h>
  23 #include <linux/device.h>
  24 #include <linux/major.h>
  25 #include <linux/slab.h>
  26 #include <linux/hid.h>
  27 #include <linux/mutex.h>
  28 #include <linux/sched/signal.h>
  29 #include <linux/string.h>
  30 
  31 #include <linux/hidraw.h>
  32 
  33 static int hidraw_major;
  34 static struct cdev hidraw_cdev;
  35 static struct class *hidraw_class;
  36 static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
  37 static DEFINE_MUTEX(minors_lock);
  38 
  39 static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
  40 {
  41         struct hidraw_list *list = file->private_data;
  42         int ret = 0, len;
  43         DECLARE_WAITQUEUE(wait, current);
  44 
  45         mutex_lock(&list->read_mutex);
  46 
  47         while (ret == 0) {
  48                 if (list->head == list->tail) {
  49                         add_wait_queue(&list->hidraw->wait, &wait);
  50                         set_current_state(TASK_INTERRUPTIBLE);
  51 
  52                         while (list->head == list->tail) {
  53                                 if (signal_pending(current)) {
  54                                         ret = -ERESTARTSYS;
  55                                         break;
  56                                 }
  57                                 if (!list->hidraw->exist) {
  58                                         ret = -EIO;
  59                                         break;
  60                                 }
  61                                 if (file->f_flags & O_NONBLOCK) {
  62                                         ret = -EAGAIN;
  63                                         break;
  64                                 }
  65 
  66                                 /* allow O_NONBLOCK to work well from other threads */
  67                                 mutex_unlock(&list->read_mutex);
  68                                 schedule();
  69                                 mutex_lock(&list->read_mutex);
  70                                 set_current_state(TASK_INTERRUPTIBLE);
  71                         }
  72 
  73                         set_current_state(TASK_RUNNING);
  74                         remove_wait_queue(&list->hidraw->wait, &wait);
  75                 }
  76 
  77                 if (ret)
  78                         goto out;
  79 
  80                 len = list->buffer[list->tail].len > count ?
  81                         count : list->buffer[list->tail].len;
  82 
  83                 if (list->buffer[list->tail].value) {
  84                         if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
  85                                 ret = -EFAULT;
  86                                 goto out;
  87                         }
  88                         ret = len;
  89                 }
  90 
  91                 kfree(list->buffer[list->tail].value);
  92                 list->buffer[list->tail].value = NULL;
  93                 list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
  94         }
  95 out:
  96         mutex_unlock(&list->read_mutex);
  97         return ret;
  98 }
  99 
 100 /*
 101  * The first byte of the report buffer is expected to be a report number.
 102  */
 103 static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type)
 104 {
 105         unsigned int minor = iminor(file_inode(file));
 106         struct hid_device *dev;
 107         __u8 *buf;
 108         int ret = 0;
 109 
 110         lockdep_assert_held(&minors_lock);
 111 
 112         if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
 113                 ret = -ENODEV;
 114                 goto out;
 115         }
 116 
 117         dev = hidraw_table[minor]->hid;
 118 
 119         if (count > HID_MAX_BUFFER_SIZE) {
 120                 hid_warn(dev, "pid %d passed too large report\n",
 121                          task_pid_nr(current));
 122                 ret = -EINVAL;
 123                 goto out;
 124         }
 125 
 126         if (count < 2) {
 127                 hid_warn(dev, "pid %d passed too short report\n",
 128                          task_pid_nr(current));
 129                 ret = -EINVAL;
 130                 goto out;
 131         }
 132 
 133         buf = memdup_user(buffer, count);
 134         if (IS_ERR(buf)) {
 135                 ret = PTR_ERR(buf);
 136                 goto out;
 137         }
 138 
 139         if ((report_type == HID_OUTPUT_REPORT) &&
 140             !(dev->quirks & HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP)) {
 141                 ret = hid_hw_output_report(dev, buf, count);
 142                 /*
 143                  * compatibility with old implementation of USB-HID and I2C-HID:
 144                  * if the device does not support receiving output reports,
 145                  * on an interrupt endpoint, fallback to SET_REPORT HID command.
 146                  */
 147                 if (ret != -ENOSYS)
 148                         goto out_free;
 149         }
 150 
 151         ret = hid_hw_raw_request(dev, buf[0], buf, count, report_type,
 152                                 HID_REQ_SET_REPORT);
 153 
 154 out_free:
 155         kfree(buf);
 156 out:
 157         return ret;
 158 }
 159 
 160 static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 161 {
 162         ssize_t ret;
 163         mutex_lock(&minors_lock);
 164         ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT);
 165         mutex_unlock(&minors_lock);
 166         return ret;
 167 }
 168 
 169 
 170 /*
 171  * This function performs a Get_Report transfer over the control endpoint
 172  * per section 7.2.1 of the HID specification, version 1.1.  The first byte
 173  * of buffer is the report number to request, or 0x0 if the defice does not
 174  * use numbered reports. The report_type parameter can be HID_FEATURE_REPORT
 175  * or HID_INPUT_REPORT.
 176  */
 177 static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type)
 178 {
 179         unsigned int minor = iminor(file_inode(file));
 180         struct hid_device *dev;
 181         __u8 *buf;
 182         int ret = 0, len;
 183         unsigned char report_number;
 184 
 185         lockdep_assert_held(&minors_lock);
 186 
 187         if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
 188                 ret = -ENODEV;
 189                 goto out;
 190         }
 191 
 192         dev = hidraw_table[minor]->hid;
 193 
 194         if (!dev->ll_driver->raw_request) {
 195                 ret = -ENODEV;
 196                 goto out;
 197         }
 198 
 199         if (count > HID_MAX_BUFFER_SIZE) {
 200                 printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
 201                                 task_pid_nr(current));
 202                 ret = -EINVAL;
 203                 goto out;
 204         }
 205 
 206         if (count < 2) {
 207                 printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
 208                                 task_pid_nr(current));
 209                 ret = -EINVAL;
 210                 goto out;
 211         }
 212 
 213         buf = kmalloc(count, GFP_KERNEL);
 214         if (!buf) {
 215                 ret = -ENOMEM;
 216                 goto out;
 217         }
 218 
 219         /*
 220          * Read the first byte from the user. This is the report number,
 221          * which is passed to hid_hw_raw_request().
 222          */
 223         if (copy_from_user(&report_number, buffer, 1)) {
 224                 ret = -EFAULT;
 225                 goto out_free;
 226         }
 227 
 228         ret = hid_hw_raw_request(dev, report_number, buf, count, report_type,
 229                                  HID_REQ_GET_REPORT);
 230 
 231         if (ret < 0)
 232                 goto out_free;
 233 
 234         len = (ret < count) ? ret : count;
 235 
 236         if (copy_to_user(buffer, buf, len)) {
 237                 ret = -EFAULT;
 238                 goto out_free;
 239         }
 240 
 241         ret = len;
 242 
 243 out_free:
 244         kfree(buf);
 245 out:
 246         return ret;
 247 }
 248 
 249 static __poll_t hidraw_poll(struct file *file, poll_table *wait)
 250 {
 251         struct hidraw_list *list = file->private_data;
 252         __poll_t mask = EPOLLOUT | EPOLLWRNORM; /* hidraw is always writable */
 253 
 254         poll_wait(file, &list->hidraw->wait, wait);
 255         if (list->head != list->tail)
 256                 mask |= EPOLLIN | EPOLLRDNORM;
 257         if (!list->hidraw->exist)
 258                 mask |= EPOLLERR | EPOLLHUP;
 259         return mask;
 260 }
 261 
 262 static int hidraw_open(struct inode *inode, struct file *file)
 263 {
 264         unsigned int minor = iminor(inode);
 265         struct hidraw *dev;
 266         struct hidraw_list *list;
 267         unsigned long flags;
 268         int err = 0;
 269 
 270         if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
 271                 err = -ENOMEM;
 272                 goto out;
 273         }
 274 
 275         mutex_lock(&minors_lock);
 276         if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
 277                 err = -ENODEV;
 278                 goto out_unlock;
 279         }
 280 
 281         dev = hidraw_table[minor];
 282         if (!dev->open++) {
 283                 err = hid_hw_power(dev->hid, PM_HINT_FULLON);
 284                 if (err < 0) {
 285                         dev->open--;
 286                         goto out_unlock;
 287                 }
 288 
 289                 err = hid_hw_open(dev->hid);
 290                 if (err < 0) {
 291                         hid_hw_power(dev->hid, PM_HINT_NORMAL);
 292                         dev->open--;
 293                         goto out_unlock;
 294                 }
 295         }
 296 
 297         list->hidraw = hidraw_table[minor];
 298         mutex_init(&list->read_mutex);
 299         spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
 300         list_add_tail(&list->node, &hidraw_table[minor]->list);
 301         spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
 302         file->private_data = list;
 303 out_unlock:
 304         mutex_unlock(&minors_lock);
 305 out:
 306         if (err < 0)
 307                 kfree(list);
 308         return err;
 309 
 310 }
 311 
 312 static int hidraw_fasync(int fd, struct file *file, int on)
 313 {
 314         struct hidraw_list *list = file->private_data;
 315 
 316         return fasync_helper(fd, file, on, &list->fasync);
 317 }
 318 
 319 static void drop_ref(struct hidraw *hidraw, int exists_bit)
 320 {
 321         if (exists_bit) {
 322                 hidraw->exist = 0;
 323                 if (hidraw->open) {
 324                         hid_hw_close(hidraw->hid);
 325                         wake_up_interruptible(&hidraw->wait);
 326                 }
 327                 device_destroy(hidraw_class,
 328                                MKDEV(hidraw_major, hidraw->minor));
 329         } else {
 330                 --hidraw->open;
 331         }
 332         if (!hidraw->open) {
 333                 if (!hidraw->exist) {
 334                         hidraw_table[hidraw->minor] = NULL;
 335                         kfree(hidraw);
 336                 } else {
 337                         /* close device for last reader */
 338                         hid_hw_close(hidraw->hid);
 339                         hid_hw_power(hidraw->hid, PM_HINT_NORMAL);
 340                 }
 341         }
 342 }
 343 
 344 static int hidraw_release(struct inode * inode, struct file * file)
 345 {
 346         unsigned int minor = iminor(inode);
 347         struct hidraw_list *list = file->private_data;
 348         unsigned long flags;
 349 
 350         mutex_lock(&minors_lock);
 351 
 352         spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
 353         list_del(&list->node);
 354         spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
 355         kfree(list);
 356 
 357         drop_ref(hidraw_table[minor], 0);
 358 
 359         mutex_unlock(&minors_lock);
 360         return 0;
 361 }
 362 
 363 static long hidraw_ioctl(struct file *file, unsigned int cmd,
 364                                                         unsigned long arg)
 365 {
 366         struct inode *inode = file_inode(file);
 367         unsigned int minor = iminor(inode);
 368         long ret = 0;
 369         struct hidraw *dev;
 370         void __user *user_arg = (void __user*) arg;
 371 
 372         mutex_lock(&minors_lock);
 373         dev = hidraw_table[minor];
 374         if (!dev || !dev->exist) {
 375                 ret = -ENODEV;
 376                 goto out;
 377         }
 378 
 379         switch (cmd) {
 380                 case HIDIOCGRDESCSIZE:
 381                         if (put_user(dev->hid->rsize, (int __user *)arg))
 382                                 ret = -EFAULT;
 383                         break;
 384 
 385                 case HIDIOCGRDESC:
 386                         {
 387                                 __u32 len;
 388 
 389                                 if (get_user(len, (int __user *)arg))
 390                                         ret = -EFAULT;
 391                                 else if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
 392                                         ret = -EINVAL;
 393                                 else if (copy_to_user(user_arg + offsetof(
 394                                         struct hidraw_report_descriptor,
 395                                         value[0]),
 396                                         dev->hid->rdesc,
 397                                         min(dev->hid->rsize, len)))
 398                                         ret = -EFAULT;
 399                                 break;
 400                         }
 401                 case HIDIOCGRAWINFO:
 402                         {
 403                                 struct hidraw_devinfo dinfo;
 404 
 405                                 dinfo.bustype = dev->hid->bus;
 406                                 dinfo.vendor = dev->hid->vendor;
 407                                 dinfo.product = dev->hid->product;
 408                                 if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
 409                                         ret = -EFAULT;
 410                                 break;
 411                         }
 412                 default:
 413                         {
 414                                 struct hid_device *hid = dev->hid;
 415                                 if (_IOC_TYPE(cmd) != 'H') {
 416                                         ret = -EINVAL;
 417                                         break;
 418                                 }
 419 
 420                                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSFEATURE(0))) {
 421                                         int len = _IOC_SIZE(cmd);
 422                                         ret = hidraw_send_report(file, user_arg, len, HID_FEATURE_REPORT);
 423                                         break;
 424                                 }
 425                                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGFEATURE(0))) {
 426                                         int len = _IOC_SIZE(cmd);
 427                                         ret = hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT);
 428                                         break;
 429                                 }
 430 
 431                                 /* Begin Read-only ioctls. */
 432                                 if (_IOC_DIR(cmd) != _IOC_READ) {
 433                                         ret = -EINVAL;
 434                                         break;
 435                                 }
 436 
 437                                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
 438                                         int len = strlen(hid->name) + 1;
 439                                         if (len > _IOC_SIZE(cmd))
 440                                                 len = _IOC_SIZE(cmd);
 441                                         ret = copy_to_user(user_arg, hid->name, len) ?
 442                                                 -EFAULT : len;
 443                                         break;
 444                                 }
 445 
 446                                 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
 447                                         int len = strlen(hid->phys) + 1;
 448                                         if (len > _IOC_SIZE(cmd))
 449                                                 len = _IOC_SIZE(cmd);
 450                                         ret = copy_to_user(user_arg, hid->phys, len) ?
 451                                                 -EFAULT : len;
 452                                         break;
 453                                 }
 454                         }
 455 
 456                 ret = -ENOTTY;
 457         }
 458 out:
 459         mutex_unlock(&minors_lock);
 460         return ret;
 461 }
 462 
 463 static const struct file_operations hidraw_ops = {
 464         .owner =        THIS_MODULE,
 465         .read =         hidraw_read,
 466         .write =        hidraw_write,
 467         .poll =         hidraw_poll,
 468         .open =         hidraw_open,
 469         .release =      hidraw_release,
 470         .unlocked_ioctl = hidraw_ioctl,
 471         .fasync =       hidraw_fasync,
 472 #ifdef CONFIG_COMPAT
 473         .compat_ioctl   = hidraw_ioctl,
 474 #endif
 475         .llseek =       noop_llseek,
 476 };
 477 
 478 int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
 479 {
 480         struct hidraw *dev = hid->hidraw;
 481         struct hidraw_list *list;
 482         int ret = 0;
 483         unsigned long flags;
 484 
 485         spin_lock_irqsave(&dev->list_lock, flags);
 486         list_for_each_entry(list, &dev->list, node) {
 487                 int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
 488 
 489                 if (new_head == list->tail)
 490                         continue;
 491 
 492                 if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) {
 493                         ret = -ENOMEM;
 494                         break;
 495                 }
 496                 list->buffer[list->head].len = len;
 497                 list->head = new_head;
 498                 kill_fasync(&list->fasync, SIGIO, POLL_IN);
 499         }
 500         spin_unlock_irqrestore(&dev->list_lock, flags);
 501 
 502         wake_up_interruptible(&dev->wait);
 503         return ret;
 504 }
 505 EXPORT_SYMBOL_GPL(hidraw_report_event);
 506 
 507 int hidraw_connect(struct hid_device *hid)
 508 {
 509         int minor, result;
 510         struct hidraw *dev;
 511 
 512         /* we accept any HID device, all applications */
 513 
 514         dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
 515         if (!dev)
 516                 return -ENOMEM;
 517 
 518         result = -EINVAL;
 519 
 520         mutex_lock(&minors_lock);
 521 
 522         for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) {
 523                 if (hidraw_table[minor])
 524                         continue;
 525                 hidraw_table[minor] = dev;
 526                 result = 0;
 527                 break;
 528         }
 529 
 530         if (result) {
 531                 mutex_unlock(&minors_lock);
 532                 kfree(dev);
 533                 goto out;
 534         }
 535 
 536         dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor),
 537                                  NULL, "%s%d", "hidraw", minor);
 538 
 539         if (IS_ERR(dev->dev)) {
 540                 hidraw_table[minor] = NULL;
 541                 mutex_unlock(&minors_lock);
 542                 result = PTR_ERR(dev->dev);
 543                 kfree(dev);
 544                 goto out;
 545         }
 546 
 547         init_waitqueue_head(&dev->wait);
 548         spin_lock_init(&dev->list_lock);
 549         INIT_LIST_HEAD(&dev->list);
 550 
 551         dev->hid = hid;
 552         dev->minor = minor;
 553 
 554         dev->exist = 1;
 555         hid->hidraw = dev;
 556 
 557         mutex_unlock(&minors_lock);
 558 out:
 559         return result;
 560 
 561 }
 562 EXPORT_SYMBOL_GPL(hidraw_connect);
 563 
 564 void hidraw_disconnect(struct hid_device *hid)
 565 {
 566         struct hidraw *hidraw = hid->hidraw;
 567 
 568         mutex_lock(&minors_lock);
 569 
 570         drop_ref(hidraw, 1);
 571 
 572         mutex_unlock(&minors_lock);
 573 }
 574 EXPORT_SYMBOL_GPL(hidraw_disconnect);
 575 
 576 int __init hidraw_init(void)
 577 {
 578         int result;
 579         dev_t dev_id;
 580 
 581         result = alloc_chrdev_region(&dev_id, HIDRAW_FIRST_MINOR,
 582                         HIDRAW_MAX_DEVICES, "hidraw");
 583         if (result < 0) {
 584                 pr_warn("can't get major number\n");
 585                 goto out;
 586         }
 587 
 588         hidraw_major = MAJOR(dev_id);
 589 
 590         hidraw_class = class_create(THIS_MODULE, "hidraw");
 591         if (IS_ERR(hidraw_class)) {
 592                 result = PTR_ERR(hidraw_class);
 593                 goto error_cdev;
 594         }
 595 
 596         cdev_init(&hidraw_cdev, &hidraw_ops);
 597         result = cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES);
 598         if (result < 0)
 599                 goto error_class;
 600 
 601         printk(KERN_INFO "hidraw: raw HID events driver (C) Jiri Kosina\n");
 602 out:
 603         return result;
 604 
 605 error_class:
 606         class_destroy(hidraw_class);
 607 error_cdev:
 608         unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
 609         goto out;
 610 }
 611 
 612 void hidraw_exit(void)
 613 {
 614         dev_t dev_id = MKDEV(hidraw_major, 0);
 615 
 616         cdev_del(&hidraw_cdev);
 617         class_destroy(hidraw_class);
 618         unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
 619 
 620 }

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