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