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