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