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