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