linux/drivers/hid/usbhid/hiddev.c
<<
>>
Prefs
   1/*
   2 *  Copyright (c) 2001 Paul Stewart
   3 *  Copyright (c) 2001 Vojtech Pavlik
   4 *
   5 *  HID char devices, giving access to raw HID device events.
   6 *
   7 */
   8
   9/*
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation; either version 2 of the License, or
  13 * (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23 *
  24 * Should you need to contact me, the author, you can do so either by
  25 * e-mail - mail your message to Paul Stewart <stewart@wetlogic.net>
  26 */
  27
  28#include <linux/poll.h>
  29#include <linux/slab.h>
  30#include <linux/sched/signal.h>
  31#include <linux/module.h>
  32#include <linux/init.h>
  33#include <linux/input.h>
  34#include <linux/usb.h>
  35#include <linux/hid.h>
  36#include <linux/hiddev.h>
  37#include <linux/compat.h>
  38#include <linux/vmalloc.h>
  39#include "usbhid.h"
  40
  41#ifdef CONFIG_USB_DYNAMIC_MINORS
  42#define HIDDEV_MINOR_BASE       0
  43#define HIDDEV_MINORS           256
  44#else
  45#define HIDDEV_MINOR_BASE       96
  46#define HIDDEV_MINORS           16
  47#endif
  48#define HIDDEV_BUFFER_SIZE      2048
  49
  50struct hiddev_list {
  51        struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE];
  52        int head;
  53        int tail;
  54        unsigned flags;
  55        struct fasync_struct *fasync;
  56        struct hiddev *hiddev;
  57        struct list_head node;
  58        struct mutex thread_lock;
  59};
  60
  61/*
  62 * Find a report, given the report's type and ID.  The ID can be specified
  63 * indirectly by REPORT_ID_FIRST (which returns the first report of the given
  64 * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the
  65 * given type which follows old_id.
  66 */
  67static struct hid_report *
  68hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo)
  69{
  70        unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK;
  71        unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK;
  72        struct hid_report_enum *report_enum;
  73        struct hid_report *report;
  74        struct list_head *list;
  75
  76        if (rinfo->report_type < HID_REPORT_TYPE_MIN ||
  77            rinfo->report_type > HID_REPORT_TYPE_MAX)
  78                return NULL;
  79
  80        report_enum = hid->report_enum +
  81                (rinfo->report_type - HID_REPORT_TYPE_MIN);
  82
  83        switch (flags) {
  84        case 0: /* Nothing to do -- report_id is already set correctly */
  85                break;
  86
  87        case HID_REPORT_ID_FIRST:
  88                if (list_empty(&report_enum->report_list))
  89                        return NULL;
  90
  91                list = report_enum->report_list.next;
  92                report = list_entry(list, struct hid_report, list);
  93                rinfo->report_id = report->id;
  94                break;
  95
  96        case HID_REPORT_ID_NEXT:
  97                report = report_enum->report_id_hash[rid];
  98                if (!report)
  99                        return NULL;
 100
 101                list = report->list.next;
 102                if (list == &report_enum->report_list)
 103                        return NULL;
 104
 105                report = list_entry(list, struct hid_report, list);
 106                rinfo->report_id = report->id;
 107                break;
 108
 109        default:
 110                return NULL;
 111        }
 112
 113        return report_enum->report_id_hash[rinfo->report_id];
 114}
 115
 116/*
 117 * Perform an exhaustive search of the report table for a usage, given its
 118 * type and usage id.
 119 */
 120static struct hid_field *
 121hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
 122{
 123        int i, j;
 124        struct hid_report *report;
 125        struct hid_report_enum *report_enum;
 126        struct hid_field *field;
 127
 128        if (uref->report_type < HID_REPORT_TYPE_MIN ||
 129            uref->report_type > HID_REPORT_TYPE_MAX)
 130                return NULL;
 131
 132        report_enum = hid->report_enum +
 133                (uref->report_type - HID_REPORT_TYPE_MIN);
 134
 135        list_for_each_entry(report, &report_enum->report_list, list) {
 136                for (i = 0; i < report->maxfield; i++) {
 137                        field = report->field[i];
 138                        for (j = 0; j < field->maxusage; j++) {
 139                                if (field->usage[j].hid == uref->usage_code) {
 140                                        uref->report_id = report->id;
 141                                        uref->field_index = i;
 142                                        uref->usage_index = j;
 143                                        return field;
 144                                }
 145                        }
 146                }
 147        }
 148
 149        return NULL;
 150}
 151
 152static void hiddev_send_event(struct hid_device *hid,
 153                              struct hiddev_usage_ref *uref)
 154{
 155        struct hiddev *hiddev = hid->hiddev;
 156        struct hiddev_list *list;
 157        unsigned long flags;
 158
 159        spin_lock_irqsave(&hiddev->list_lock, flags);
 160        list_for_each_entry(list, &hiddev->list, node) {
 161                if (uref->field_index != HID_FIELD_INDEX_NONE ||
 162                    (list->flags & HIDDEV_FLAG_REPORT) != 0) {
 163                        list->buffer[list->head] = *uref;
 164                        list->head = (list->head + 1) &
 165                                (HIDDEV_BUFFER_SIZE - 1);
 166                        kill_fasync(&list->fasync, SIGIO, POLL_IN);
 167                }
 168        }
 169        spin_unlock_irqrestore(&hiddev->list_lock, flags);
 170
 171        wake_up_interruptible(&hiddev->wait);
 172}
 173
 174/*
 175 * This is where hid.c calls into hiddev to pass an event that occurred over
 176 * the interrupt pipe
 177 */
 178void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
 179                      struct hid_usage *usage, __s32 value)
 180{
 181        unsigned type = field->report_type;
 182        struct hiddev_usage_ref uref;
 183
 184        uref.report_type =
 185          (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
 186          ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
 187           ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0));
 188        uref.report_id = field->report->id;
 189        uref.field_index = field->index;
 190        uref.usage_index = (usage - field->usage);
 191        uref.usage_code = usage->hid;
 192        uref.value = value;
 193
 194        hiddev_send_event(hid, &uref);
 195}
 196EXPORT_SYMBOL_GPL(hiddev_hid_event);
 197
 198void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
 199{
 200        unsigned type = report->type;
 201        struct hiddev_usage_ref uref;
 202
 203        memset(&uref, 0, sizeof(uref));
 204        uref.report_type =
 205          (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
 206          ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
 207           ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0));
 208        uref.report_id = report->id;
 209        uref.field_index = HID_FIELD_INDEX_NONE;
 210
 211        hiddev_send_event(hid, &uref);
 212}
 213
 214/*
 215 * fasync file op
 216 */
 217static int hiddev_fasync(int fd, struct file *file, int on)
 218{
 219        struct hiddev_list *list = file->private_data;
 220
 221        return fasync_helper(fd, file, on, &list->fasync);
 222}
 223
 224
 225/*
 226 * release file op
 227 */
 228static int hiddev_release(struct inode * inode, struct file * file)
 229{
 230        struct hiddev_list *list = file->private_data;
 231        unsigned long flags;
 232
 233        spin_lock_irqsave(&list->hiddev->list_lock, flags);
 234        list_del(&list->node);
 235        spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
 236
 237        mutex_lock(&list->hiddev->existancelock);
 238        if (!--list->hiddev->open) {
 239                if (list->hiddev->exist) {
 240                        hid_hw_close(list->hiddev->hid);
 241                        hid_hw_power(list->hiddev->hid, PM_HINT_NORMAL);
 242                } else {
 243                        mutex_unlock(&list->hiddev->existancelock);
 244                        kfree(list->hiddev);
 245                        vfree(list);
 246                        return 0;
 247                }
 248        }
 249
 250        mutex_unlock(&list->hiddev->existancelock);
 251        vfree(list);
 252
 253        return 0;
 254}
 255
 256/*
 257 * open file op
 258 */
 259static int hiddev_open(struct inode *inode, struct file *file)
 260{
 261        struct hiddev_list *list;
 262        struct usb_interface *intf;
 263        struct hid_device *hid;
 264        struct hiddev *hiddev;
 265        int res;
 266
 267        intf = usbhid_find_interface(iminor(inode));
 268        if (!intf)
 269                return -ENODEV;
 270        hid = usb_get_intfdata(intf);
 271        hiddev = hid->hiddev;
 272
 273        if (!(list = vzalloc(sizeof(struct hiddev_list))))
 274                return -ENOMEM;
 275        mutex_init(&list->thread_lock);
 276        list->hiddev = hiddev;
 277        file->private_data = list;
 278
 279        /*
 280         * no need for locking because the USB major number
 281         * is shared which usbcore guards against disconnect
 282         */
 283        if (list->hiddev->exist) {
 284                if (!list->hiddev->open++) {
 285                        res = hid_hw_open(hiddev->hid);
 286                        if (res < 0)
 287                                goto bail;
 288                }
 289        } else {
 290                res = -ENODEV;
 291                goto bail;
 292        }
 293
 294        spin_lock_irq(&list->hiddev->list_lock);
 295        list_add_tail(&list->node, &hiddev->list);
 296        spin_unlock_irq(&list->hiddev->list_lock);
 297
 298        mutex_lock(&hiddev->existancelock);
 299        if (!list->hiddev->open++)
 300                if (list->hiddev->exist) {
 301                        struct hid_device *hid = hiddev->hid;
 302                        res = hid_hw_power(hid, PM_HINT_FULLON);
 303                        if (res < 0)
 304                                goto bail_unlock;
 305                        res = hid_hw_open(hid);
 306                        if (res < 0)
 307                                goto bail_normal_power;
 308                }
 309        mutex_unlock(&hiddev->existancelock);
 310        return 0;
 311bail_normal_power:
 312        hid_hw_power(hid, PM_HINT_NORMAL);
 313bail_unlock:
 314        mutex_unlock(&hiddev->existancelock);
 315bail:
 316        file->private_data = NULL;
 317        vfree(list);
 318        return res;
 319}
 320
 321/*
 322 * "write" file op
 323 */
 324static ssize_t hiddev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
 325{
 326        return -EINVAL;
 327}
 328
 329/*
 330 * "read" file op
 331 */
 332static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
 333{
 334        DEFINE_WAIT(wait);
 335        struct hiddev_list *list = file->private_data;
 336        int event_size;
 337        int retval;
 338
 339        event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
 340                sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
 341
 342        if (count < event_size)
 343                return 0;
 344
 345        /* lock against other threads */
 346        retval = mutex_lock_interruptible(&list->thread_lock);
 347        if (retval)
 348                return -ERESTARTSYS;
 349
 350        while (retval == 0) {
 351                if (list->head == list->tail) {
 352                        prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE);
 353
 354                        while (list->head == list->tail) {
 355                                if (signal_pending(current)) {
 356                                        retval = -ERESTARTSYS;
 357                                        break;
 358                                }
 359                                if (!list->hiddev->exist) {
 360                                        retval = -EIO;
 361                                        break;
 362                                }
 363                                if (file->f_flags & O_NONBLOCK) {
 364                                        retval = -EAGAIN;
 365                                        break;
 366                                }
 367
 368                                /* let O_NONBLOCK tasks run */
 369                                mutex_unlock(&list->thread_lock);
 370                                schedule();
 371                                if (mutex_lock_interruptible(&list->thread_lock)) {
 372                                        finish_wait(&list->hiddev->wait, &wait);
 373                                        return -EINTR;
 374                                }
 375                                set_current_state(TASK_INTERRUPTIBLE);
 376                        }
 377                        finish_wait(&list->hiddev->wait, &wait);
 378
 379                }
 380
 381                if (retval) {
 382                        mutex_unlock(&list->thread_lock);
 383                        return retval;
 384                }
 385
 386
 387                while (list->head != list->tail &&
 388                       retval + event_size <= count) {
 389                        if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
 390                                if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE) {
 391                                        struct hiddev_event event;
 392
 393                                        event.hid = list->buffer[list->tail].usage_code;
 394                                        event.value = list->buffer[list->tail].value;
 395                                        if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) {
 396                                                mutex_unlock(&list->thread_lock);
 397                                                return -EFAULT;
 398                                        }
 399                                        retval += sizeof(struct hiddev_event);
 400                                }
 401                        } else {
 402                                if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
 403                                    (list->flags & HIDDEV_FLAG_REPORT) != 0) {
 404
 405                                        if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) {
 406                                                mutex_unlock(&list->thread_lock);
 407                                                return -EFAULT;
 408                                        }
 409                                        retval += sizeof(struct hiddev_usage_ref);
 410                                }
 411                        }
 412                        list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
 413                }
 414
 415        }
 416        mutex_unlock(&list->thread_lock);
 417
 418        return retval;
 419}
 420
 421/*
 422 * "poll" file op
 423 * No kernel lock - fine
 424 */
 425static __poll_t hiddev_poll(struct file *file, poll_table *wait)
 426{
 427        struct hiddev_list *list = file->private_data;
 428
 429        poll_wait(file, &list->hiddev->wait, wait);
 430        if (list->head != list->tail)
 431                return EPOLLIN | EPOLLRDNORM;
 432        if (!list->hiddev->exist)
 433                return EPOLLERR | EPOLLHUP;
 434        return 0;
 435}
 436
 437/*
 438 * "ioctl" file op
 439 */
 440static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, void __user *user_arg)
 441{
 442        struct hid_device *hid = hiddev->hid;
 443        struct hiddev_report_info rinfo;
 444        struct hiddev_usage_ref_multi *uref_multi = NULL;
 445        struct hiddev_usage_ref *uref;
 446        struct hid_report *report;
 447        struct hid_field *field;
 448        int i;
 449
 450        uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
 451        if (!uref_multi)
 452                return -ENOMEM;
 453        uref = &uref_multi->uref;
 454        if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
 455                if (copy_from_user(uref_multi, user_arg,
 456                                   sizeof(*uref_multi)))
 457                        goto fault;
 458        } else {
 459                if (copy_from_user(uref, user_arg, sizeof(*uref)))
 460                        goto fault;
 461        }
 462
 463        switch (cmd) {
 464        case HIDIOCGUCODE:
 465                rinfo.report_type = uref->report_type;
 466                rinfo.report_id = uref->report_id;
 467                if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
 468                        goto inval;
 469
 470                if (uref->field_index >= report->maxfield)
 471                        goto inval;
 472
 473                field = report->field[uref->field_index];
 474                if (uref->usage_index >= field->maxusage)
 475                        goto inval;
 476
 477                uref->usage_code = field->usage[uref->usage_index].hid;
 478
 479                if (copy_to_user(user_arg, uref, sizeof(*uref)))
 480                        goto fault;
 481
 482                goto goodreturn;
 483
 484        default:
 485                if (cmd != HIDIOCGUSAGE &&
 486                    cmd != HIDIOCGUSAGES &&
 487                    uref->report_type == HID_REPORT_TYPE_INPUT)
 488                        goto inval;
 489
 490                if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
 491                        field = hiddev_lookup_usage(hid, uref);
 492                        if (field == NULL)
 493                                goto inval;
 494                } else {
 495                        rinfo.report_type = uref->report_type;
 496                        rinfo.report_id = uref->report_id;
 497                        if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
 498                                goto inval;
 499
 500                        if (uref->field_index >= report->maxfield)
 501                                goto inval;
 502
 503                        field = report->field[uref->field_index];
 504
 505                        if (cmd == HIDIOCGCOLLECTIONINDEX) {
 506                                if (uref->usage_index >= field->maxusage)
 507                                        goto inval;
 508                        } else if (uref->usage_index >= field->report_count)
 509                                goto inval;
 510                }
 511
 512                if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
 513                    (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
 514                     uref->usage_index + uref_multi->num_values > field->report_count))
 515                        goto inval;
 516
 517                switch (cmd) {
 518                case HIDIOCGUSAGE:
 519                        uref->value = field->value[uref->usage_index];
 520                        if (copy_to_user(user_arg, uref, sizeof(*uref)))
 521                                goto fault;
 522                        goto goodreturn;
 523
 524                case HIDIOCSUSAGE:
 525                        field->value[uref->usage_index] = uref->value;
 526                        goto goodreturn;
 527
 528                case HIDIOCGCOLLECTIONINDEX:
 529                        i = field->usage[uref->usage_index].collection_index;
 530                        kfree(uref_multi);
 531                        return i;
 532                case HIDIOCGUSAGES:
 533                        for (i = 0; i < uref_multi->num_values; i++)
 534                                uref_multi->values[i] =
 535                                    field->value[uref->usage_index + i];
 536                        if (copy_to_user(user_arg, uref_multi,
 537                                         sizeof(*uref_multi)))
 538                                goto fault;
 539                        goto goodreturn;
 540                case HIDIOCSUSAGES:
 541                        for (i = 0; i < uref_multi->num_values; i++)
 542                                field->value[uref->usage_index + i] =
 543                                    uref_multi->values[i];
 544                        goto goodreturn;
 545                }
 546
 547goodreturn:
 548                kfree(uref_multi);
 549                return 0;
 550fault:
 551                kfree(uref_multi);
 552                return -EFAULT;
 553inval:
 554                kfree(uref_multi);
 555                return -EINVAL;
 556        }
 557}
 558
 559static noinline int hiddev_ioctl_string(struct hiddev *hiddev, unsigned int cmd, void __user *user_arg)
 560{
 561        struct hid_device *hid = hiddev->hid;
 562        struct usb_device *dev = hid_to_usb_dev(hid);
 563        int idx, len;
 564        char *buf;
 565
 566        if (get_user(idx, (int __user *)user_arg))
 567                return -EFAULT;
 568
 569        if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
 570                return -ENOMEM;
 571
 572        if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
 573                kfree(buf);
 574                return -EINVAL;
 575        }
 576
 577        if (copy_to_user(user_arg+sizeof(int), buf, len+1)) {
 578                kfree(buf);
 579                return -EFAULT;
 580        }
 581
 582        kfree(buf);
 583
 584        return len;
 585}
 586
 587static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 588{
 589        struct hiddev_list *list = file->private_data;
 590        struct hiddev *hiddev = list->hiddev;
 591        struct hid_device *hid;
 592        struct hiddev_collection_info cinfo;
 593        struct hiddev_report_info rinfo;
 594        struct hiddev_field_info finfo;
 595        struct hiddev_devinfo dinfo;
 596        struct hid_report *report;
 597        struct hid_field *field;
 598        void __user *user_arg = (void __user *)arg;
 599        int i, r = -EINVAL;
 600
 601        /* Called without BKL by compat methods so no BKL taken */
 602
 603        mutex_lock(&hiddev->existancelock);
 604        if (!hiddev->exist) {
 605                r = -ENODEV;
 606                goto ret_unlock;
 607        }
 608
 609        hid = hiddev->hid;
 610
 611        switch (cmd) {
 612
 613        case HIDIOCGVERSION:
 614                r = put_user(HID_VERSION, (int __user *)arg) ?
 615                        -EFAULT : 0;
 616                break;
 617
 618        case HIDIOCAPPLICATION:
 619                if (arg >= hid->maxapplication)
 620                        break;
 621
 622                for (i = 0; i < hid->maxcollection; i++)
 623                        if (hid->collection[i].type ==
 624                            HID_COLLECTION_APPLICATION && arg-- == 0)
 625                                break;
 626
 627                if (i < hid->maxcollection)
 628                        r = hid->collection[i].usage;
 629                break;
 630
 631        case HIDIOCGDEVINFO:
 632                {
 633                        struct usb_device *dev = hid_to_usb_dev(hid);
 634                        struct usbhid_device *usbhid = hid->driver_data;
 635
 636                        memset(&dinfo, 0, sizeof(dinfo));
 637
 638                        dinfo.bustype = BUS_USB;
 639                        dinfo.busnum = dev->bus->busnum;
 640                        dinfo.devnum = dev->devnum;
 641                        dinfo.ifnum = usbhid->ifnum;
 642                        dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
 643                        dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
 644                        dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
 645                        dinfo.num_applications = hid->maxapplication;
 646
 647                        r = copy_to_user(user_arg, &dinfo, sizeof(dinfo)) ?
 648                                -EFAULT : 0;
 649                        break;
 650                }
 651
 652        case HIDIOCGFLAG:
 653                r = put_user(list->flags, (int __user *)arg) ?
 654                        -EFAULT : 0;
 655                break;
 656
 657        case HIDIOCSFLAG:
 658                {
 659                        int newflags;
 660
 661                        if (get_user(newflags, (int __user *)arg)) {
 662                                r = -EFAULT;
 663                                break;
 664                        }
 665
 666                        if ((newflags & ~HIDDEV_FLAGS) != 0 ||
 667                            ((newflags & HIDDEV_FLAG_REPORT) != 0 &&
 668                             (newflags & HIDDEV_FLAG_UREF) == 0))
 669                                break;
 670
 671                        list->flags = newflags;
 672
 673                        r = 0;
 674                        break;
 675                }
 676
 677        case HIDIOCGSTRING:
 678                r = hiddev_ioctl_string(hiddev, cmd, user_arg);
 679                break;
 680
 681        case HIDIOCINITREPORT:
 682                usbhid_init_reports(hid);
 683                hiddev->initialized = true;
 684                r = 0;
 685                break;
 686
 687        case HIDIOCGREPORT:
 688                if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) {
 689                        r = -EFAULT;
 690                        break;
 691                }
 692
 693                if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT)
 694                        break;
 695
 696                report = hiddev_lookup_report(hid, &rinfo);
 697                if (report == NULL)
 698                        break;
 699
 700                hid_hw_request(hid, report, HID_REQ_GET_REPORT);
 701                hid_hw_wait(hid);
 702
 703                r = 0;
 704                break;
 705
 706        case HIDIOCSREPORT:
 707                if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) {
 708                        r = -EFAULT;
 709                        break;
 710                }
 711
 712                if (rinfo.report_type == HID_REPORT_TYPE_INPUT)
 713                        break;
 714
 715                report = hiddev_lookup_report(hid, &rinfo);
 716                if (report == NULL)
 717                        break;
 718
 719                hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 720                hid_hw_wait(hid);
 721
 722                r = 0;
 723                break;
 724
 725        case HIDIOCGREPORTINFO:
 726                if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) {
 727                        r = -EFAULT;
 728                        break;
 729                }
 730
 731                report = hiddev_lookup_report(hid, &rinfo);
 732                if (report == NULL)
 733                        break;
 734
 735                rinfo.num_fields = report->maxfield;
 736
 737                r = copy_to_user(user_arg, &rinfo, sizeof(rinfo)) ?
 738                        -EFAULT : 0;
 739                break;
 740
 741        case HIDIOCGFIELDINFO:
 742                if (copy_from_user(&finfo, user_arg, sizeof(finfo))) {
 743                        r = -EFAULT;
 744                        break;
 745                }
 746
 747                rinfo.report_type = finfo.report_type;
 748                rinfo.report_id = finfo.report_id;
 749
 750                report = hiddev_lookup_report(hid, &rinfo);
 751                if (report == NULL)
 752                        break;
 753
 754                if (finfo.field_index >= report->maxfield)
 755                        break;
 756
 757                field = report->field[finfo.field_index];
 758                memset(&finfo, 0, sizeof(finfo));
 759                finfo.report_type = rinfo.report_type;
 760                finfo.report_id = rinfo.report_id;
 761                finfo.field_index = field->report_count - 1;
 762                finfo.maxusage = field->maxusage;
 763                finfo.flags = field->flags;
 764                finfo.physical = field->physical;
 765                finfo.logical = field->logical;
 766                finfo.application = field->application;
 767                finfo.logical_minimum = field->logical_minimum;
 768                finfo.logical_maximum = field->logical_maximum;
 769                finfo.physical_minimum = field->physical_minimum;
 770                finfo.physical_maximum = field->physical_maximum;
 771                finfo.unit_exponent = field->unit_exponent;
 772                finfo.unit = field->unit;
 773
 774                r = copy_to_user(user_arg, &finfo, sizeof(finfo)) ?
 775                        -EFAULT : 0;
 776                break;
 777
 778        case HIDIOCGUCODE:
 779                /* fall through */
 780        case HIDIOCGUSAGE:
 781        case HIDIOCSUSAGE:
 782        case HIDIOCGUSAGES:
 783        case HIDIOCSUSAGES:
 784        case HIDIOCGCOLLECTIONINDEX:
 785                if (!hiddev->initialized) {
 786                        usbhid_init_reports(hid);
 787                        hiddev->initialized = true;
 788                }
 789                r = hiddev_ioctl_usage(hiddev, cmd, user_arg);
 790                break;
 791
 792        case HIDIOCGCOLLECTIONINFO:
 793                if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) {
 794                        r = -EFAULT;
 795                        break;
 796                }
 797
 798                if (cinfo.index >= hid->maxcollection)
 799                        break;
 800
 801                cinfo.type = hid->collection[cinfo.index].type;
 802                cinfo.usage = hid->collection[cinfo.index].usage;
 803                cinfo.level = hid->collection[cinfo.index].level;
 804
 805                r = copy_to_user(user_arg, &cinfo, sizeof(cinfo)) ?
 806                        -EFAULT : 0;
 807                break;
 808
 809        default:
 810                if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
 811                        break;
 812
 813                if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) {
 814                        int len = strlen(hid->name) + 1;
 815                        if (len > _IOC_SIZE(cmd))
 816                                 len = _IOC_SIZE(cmd);
 817                        r = copy_to_user(user_arg, hid->name, len) ?
 818                                -EFAULT : len;
 819                        break;
 820                }
 821
 822                if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) {
 823                        int len = strlen(hid->phys) + 1;
 824                        if (len > _IOC_SIZE(cmd))
 825                                len = _IOC_SIZE(cmd);
 826                        r = copy_to_user(user_arg, hid->phys, len) ?
 827                                -EFAULT : len;
 828                        break;
 829                }
 830        }
 831
 832ret_unlock:
 833        mutex_unlock(&hiddev->existancelock);
 834        return r;
 835}
 836
 837#ifdef CONFIG_COMPAT
 838static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 839{
 840        return hiddev_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
 841}
 842#endif
 843
 844static const struct file_operations hiddev_fops = {
 845        .owner =        THIS_MODULE,
 846        .read =         hiddev_read,
 847        .write =        hiddev_write,
 848        .poll =         hiddev_poll,
 849        .open =         hiddev_open,
 850        .release =      hiddev_release,
 851        .unlocked_ioctl =       hiddev_ioctl,
 852        .fasync =       hiddev_fasync,
 853#ifdef CONFIG_COMPAT
 854        .compat_ioctl   = hiddev_compat_ioctl,
 855#endif
 856        .llseek         = noop_llseek,
 857};
 858
 859static char *hiddev_devnode(struct device *dev, umode_t *mode)
 860{
 861        return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev));
 862}
 863
 864static struct usb_class_driver hiddev_class = {
 865        .name =         "hiddev%d",
 866        .devnode =      hiddev_devnode,
 867        .fops =         &hiddev_fops,
 868        .minor_base =   HIDDEV_MINOR_BASE,
 869};
 870
 871/*
 872 * This is where hid.c calls us to connect a hid device to the hiddev driver
 873 */
 874int hiddev_connect(struct hid_device *hid, unsigned int force)
 875{
 876        struct hiddev *hiddev;
 877        struct usbhid_device *usbhid = hid->driver_data;
 878        int retval;
 879
 880        if (!force) {
 881                unsigned int i;
 882                for (i = 0; i < hid->maxcollection; i++)
 883                        if (hid->collection[i].type ==
 884                            HID_COLLECTION_APPLICATION &&
 885                            !IS_INPUT_APPLICATION(hid->collection[i].usage))
 886                                break;
 887
 888                if (i == hid->maxcollection)
 889                        return -1;
 890        }
 891
 892        if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
 893                return -1;
 894
 895        init_waitqueue_head(&hiddev->wait);
 896        INIT_LIST_HEAD(&hiddev->list);
 897        spin_lock_init(&hiddev->list_lock);
 898        mutex_init(&hiddev->existancelock);
 899        hid->hiddev = hiddev;
 900        hiddev->hid = hid;
 901        hiddev->exist = 1;
 902        retval = usb_register_dev(usbhid->intf, &hiddev_class);
 903        if (retval) {
 904                hid_err(hid, "Not able to get a minor for this device\n");
 905                hid->hiddev = NULL;
 906                kfree(hiddev);
 907                return -1;
 908        }
 909
 910        /*
 911         * If HID_QUIRK_NO_INIT_REPORTS is set, make sure we don't initialize
 912         * the reports.
 913         */
 914        hiddev->initialized = hid->quirks & HID_QUIRK_NO_INIT_REPORTS;
 915
 916        hiddev->minor = usbhid->intf->minor;
 917
 918        return 0;
 919}
 920
 921/*
 922 * This is where hid.c calls us to disconnect a hiddev device from the
 923 * corresponding hid device (usually because the usb device has disconnected)
 924 */
 925static struct usb_class_driver hiddev_class;
 926void hiddev_disconnect(struct hid_device *hid)
 927{
 928        struct hiddev *hiddev = hid->hiddev;
 929        struct usbhid_device *usbhid = hid->driver_data;
 930
 931        usb_deregister_dev(usbhid->intf, &hiddev_class);
 932
 933        mutex_lock(&hiddev->existancelock);
 934        hiddev->exist = 0;
 935
 936        if (hiddev->open) {
 937                mutex_unlock(&hiddev->existancelock);
 938                hid_hw_close(hiddev->hid);
 939                wake_up_interruptible(&hiddev->wait);
 940        } else {
 941                mutex_unlock(&hiddev->existancelock);
 942                kfree(hiddev);
 943        }
 944}
 945