linux/drivers/hid/uhid.c
<<
>>
Prefs
   1/*
   2 * User-space I/O driver support for HID subsystem
   3 * Copyright (c) 2012 David Herrmann
   4 */
   5
   6/*
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License as published by the Free
   9 * Software Foundation; either version 2 of the License, or (at your option)
  10 * any later version.
  11 */
  12
  13#include <linux/atomic.h>
  14#include <linux/device.h>
  15#include <linux/fs.h>
  16#include <linux/hid.h>
  17#include <linux/input.h>
  18#include <linux/miscdevice.h>
  19#include <linux/module.h>
  20#include <linux/mutex.h>
  21#include <linux/poll.h>
  22#include <linux/sched.h>
  23#include <linux/spinlock.h>
  24#include <linux/uhid.h>
  25#include <linux/wait.h>
  26
  27#define UHID_NAME       "uhid"
  28#define UHID_BUFSIZE    32
  29
  30struct uhid_device {
  31        struct mutex devlock;
  32        bool running;
  33
  34        __u8 *rd_data;
  35        uint rd_size;
  36
  37        struct hid_device *hid;
  38        struct uhid_event input_buf;
  39
  40        wait_queue_head_t waitq;
  41        spinlock_t qlock;
  42        __u8 head;
  43        __u8 tail;
  44        struct uhid_event *outq[UHID_BUFSIZE];
  45
  46        struct mutex report_lock;
  47        wait_queue_head_t report_wait;
  48        atomic_t report_done;
  49        atomic_t report_id;
  50        struct uhid_event report_buf;
  51};
  52
  53static struct miscdevice uhid_misc;
  54
  55static void uhid_queue(struct uhid_device *uhid, struct uhid_event *ev)
  56{
  57        __u8 newhead;
  58
  59        newhead = (uhid->head + 1) % UHID_BUFSIZE;
  60
  61        if (newhead != uhid->tail) {
  62                uhid->outq[uhid->head] = ev;
  63                uhid->head = newhead;
  64                wake_up_interruptible(&uhid->waitq);
  65        } else {
  66                hid_warn(uhid->hid, "Output queue is full\n");
  67                kfree(ev);
  68        }
  69}
  70
  71static int uhid_queue_event(struct uhid_device *uhid, __u32 event)
  72{
  73        unsigned long flags;
  74        struct uhid_event *ev;
  75
  76        ev = kzalloc(sizeof(*ev), GFP_KERNEL);
  77        if (!ev)
  78                return -ENOMEM;
  79
  80        ev->type = event;
  81
  82        spin_lock_irqsave(&uhid->qlock, flags);
  83        uhid_queue(uhid, ev);
  84        spin_unlock_irqrestore(&uhid->qlock, flags);
  85
  86        return 0;
  87}
  88
  89static int uhid_hid_start(struct hid_device *hid)
  90{
  91        struct uhid_device *uhid = hid->driver_data;
  92
  93        return uhid_queue_event(uhid, UHID_START);
  94}
  95
  96static void uhid_hid_stop(struct hid_device *hid)
  97{
  98        struct uhid_device *uhid = hid->driver_data;
  99
 100        hid->claimed = 0;
 101        uhid_queue_event(uhid, UHID_STOP);
 102}
 103
 104static int uhid_hid_open(struct hid_device *hid)
 105{
 106        struct uhid_device *uhid = hid->driver_data;
 107
 108        return uhid_queue_event(uhid, UHID_OPEN);
 109}
 110
 111static void uhid_hid_close(struct hid_device *hid)
 112{
 113        struct uhid_device *uhid = hid->driver_data;
 114
 115        uhid_queue_event(uhid, UHID_CLOSE);
 116}
 117
 118static int uhid_hid_input(struct input_dev *input, unsigned int type,
 119                          unsigned int code, int value)
 120{
 121        struct hid_device *hid = input_get_drvdata(input);
 122        struct uhid_device *uhid = hid->driver_data;
 123        unsigned long flags;
 124        struct uhid_event *ev;
 125
 126        ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 127        if (!ev)
 128                return -ENOMEM;
 129
 130        ev->type = UHID_OUTPUT_EV;
 131        ev->u.output_ev.type = type;
 132        ev->u.output_ev.code = code;
 133        ev->u.output_ev.value = value;
 134
 135        spin_lock_irqsave(&uhid->qlock, flags);
 136        uhid_queue(uhid, ev);
 137        spin_unlock_irqrestore(&uhid->qlock, flags);
 138
 139        return 0;
 140}
 141
 142static int uhid_hid_parse(struct hid_device *hid)
 143{
 144        struct uhid_device *uhid = hid->driver_data;
 145
 146        return hid_parse_report(hid, uhid->rd_data, uhid->rd_size);
 147}
 148
 149static int uhid_hid_get_raw(struct hid_device *hid, unsigned char rnum,
 150                            __u8 *buf, size_t count, unsigned char rtype)
 151{
 152        struct uhid_device *uhid = hid->driver_data;
 153        __u8 report_type;
 154        struct uhid_event *ev;
 155        unsigned long flags;
 156        int ret;
 157        size_t uninitialized_var(len);
 158        struct uhid_feature_answer_req *req;
 159
 160        if (!uhid->running)
 161                return -EIO;
 162
 163        switch (rtype) {
 164        case HID_FEATURE_REPORT:
 165                report_type = UHID_FEATURE_REPORT;
 166                break;
 167        case HID_OUTPUT_REPORT:
 168                report_type = UHID_OUTPUT_REPORT;
 169                break;
 170        case HID_INPUT_REPORT:
 171                report_type = UHID_INPUT_REPORT;
 172                break;
 173        default:
 174                return -EINVAL;
 175        }
 176
 177        ret = mutex_lock_interruptible(&uhid->report_lock);
 178        if (ret)
 179                return ret;
 180
 181        ev = kzalloc(sizeof(*ev), GFP_KERNEL);
 182        if (!ev) {
 183                ret = -ENOMEM;
 184                goto unlock;
 185        }
 186
 187        spin_lock_irqsave(&uhid->qlock, flags);
 188        ev->type = UHID_FEATURE;
 189        ev->u.feature.id = atomic_inc_return(&uhid->report_id);
 190        ev->u.feature.rnum = rnum;
 191        ev->u.feature.rtype = report_type;
 192
 193        atomic_set(&uhid->report_done, 0);
 194        uhid_queue(uhid, ev);
 195        spin_unlock_irqrestore(&uhid->qlock, flags);
 196
 197        ret = wait_event_interruptible_timeout(uhid->report_wait,
 198                                atomic_read(&uhid->report_done), 5 * HZ);
 199
 200        /*
 201         * Make sure "uhid->running" is cleared on shutdown before
 202         * "uhid->report_done" is set.
 203         */
 204        smp_rmb();
 205        if (!ret || !uhid->running) {
 206                ret = -EIO;
 207        } else if (ret < 0) {
 208                ret = -ERESTARTSYS;
 209        } else {
 210                spin_lock_irqsave(&uhid->qlock, flags);
 211                req = &uhid->report_buf.u.feature_answer;
 212
 213                if (req->err) {
 214                        ret = -EIO;
 215                } else {
 216                        ret = 0;
 217                        len = min(count,
 218                                min_t(size_t, req->size, UHID_DATA_MAX));
 219                        memcpy(buf, req->data, len);
 220                }
 221
 222                spin_unlock_irqrestore(&uhid->qlock, flags);
 223        }
 224
 225        atomic_set(&uhid->report_done, 1);
 226
 227unlock:
 228        mutex_unlock(&uhid->report_lock);
 229        return ret ? ret : len;
 230}
 231
 232static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count,
 233                               unsigned char report_type)
 234{
 235        struct uhid_device *uhid = hid->driver_data;
 236        __u8 rtype;
 237        unsigned long flags;
 238        struct uhid_event *ev;
 239
 240        switch (report_type) {
 241        case HID_FEATURE_REPORT:
 242                rtype = UHID_FEATURE_REPORT;
 243                break;
 244        case HID_OUTPUT_REPORT:
 245                rtype = UHID_OUTPUT_REPORT;
 246                break;
 247        default:
 248                return -EINVAL;
 249        }
 250
 251        if (count < 1 || count > UHID_DATA_MAX)
 252                return -EINVAL;
 253
 254        ev = kzalloc(sizeof(*ev), GFP_KERNEL);
 255        if (!ev)
 256                return -ENOMEM;
 257
 258        ev->type = UHID_OUTPUT;
 259        ev->u.output.size = count;
 260        ev->u.output.rtype = rtype;
 261        memcpy(ev->u.output.data, buf, count);
 262
 263        spin_lock_irqsave(&uhid->qlock, flags);
 264        uhid_queue(uhid, ev);
 265        spin_unlock_irqrestore(&uhid->qlock, flags);
 266
 267        return count;
 268}
 269
 270static struct hid_ll_driver uhid_hid_driver = {
 271        .start = uhid_hid_start,
 272        .stop = uhid_hid_stop,
 273        .open = uhid_hid_open,
 274        .close = uhid_hid_close,
 275        .hidinput_input_event = uhid_hid_input,
 276        .parse = uhid_hid_parse,
 277};
 278
 279static int uhid_dev_create(struct uhid_device *uhid,
 280                           const struct uhid_event *ev)
 281{
 282        struct hid_device *hid;
 283        int ret;
 284
 285        if (uhid->running)
 286                return -EALREADY;
 287
 288        uhid->rd_size = ev->u.create.rd_size;
 289        if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE)
 290                return -EINVAL;
 291
 292        uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL);
 293        if (!uhid->rd_data)
 294                return -ENOMEM;
 295
 296        if (copy_from_user(uhid->rd_data, ev->u.create.rd_data,
 297                           uhid->rd_size)) {
 298                ret = -EFAULT;
 299                goto err_free;
 300        }
 301
 302        hid = hid_allocate_device();
 303        if (IS_ERR(hid)) {
 304                ret = PTR_ERR(hid);
 305                goto err_free;
 306        }
 307
 308        strncpy(hid->name, ev->u.create.name, 127);
 309        hid->name[127] = 0;
 310        strncpy(hid->phys, ev->u.create.phys, 63);
 311        hid->phys[63] = 0;
 312        strncpy(hid->uniq, ev->u.create.uniq, 63);
 313        hid->uniq[63] = 0;
 314
 315        hid->ll_driver = &uhid_hid_driver;
 316        hid->hid_get_raw_report = uhid_hid_get_raw;
 317        hid->hid_output_raw_report = uhid_hid_output_raw;
 318        hid->bus = ev->u.create.bus;
 319        hid->vendor = ev->u.create.vendor;
 320        hid->product = ev->u.create.product;
 321        hid->version = ev->u.create.version;
 322        hid->country = ev->u.create.country;
 323        hid->driver_data = uhid;
 324        hid->dev.parent = uhid_misc.this_device;
 325
 326        uhid->hid = hid;
 327        uhid->running = true;
 328
 329        ret = hid_add_device(hid);
 330        if (ret) {
 331                hid_err(hid, "Cannot register HID device\n");
 332                goto err_hid;
 333        }
 334
 335        return 0;
 336
 337err_hid:
 338        hid_destroy_device(hid);
 339        uhid->hid = NULL;
 340        uhid->running = false;
 341err_free:
 342        kfree(uhid->rd_data);
 343        return ret;
 344}
 345
 346static int uhid_dev_destroy(struct uhid_device *uhid)
 347{
 348        if (!uhid->running)
 349                return -EINVAL;
 350
 351        /* clear "running" before setting "report_done" */
 352        uhid->running = false;
 353        smp_wmb();
 354        atomic_set(&uhid->report_done, 1);
 355        wake_up_interruptible(&uhid->report_wait);
 356
 357        hid_destroy_device(uhid->hid);
 358        kfree(uhid->rd_data);
 359
 360        return 0;
 361}
 362
 363static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev)
 364{
 365        if (!uhid->running)
 366                return -EINVAL;
 367
 368        hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input.data,
 369                         min_t(size_t, ev->u.input.size, UHID_DATA_MAX), 0);
 370
 371        return 0;
 372}
 373
 374static int uhid_dev_feature_answer(struct uhid_device *uhid,
 375                                   struct uhid_event *ev)
 376{
 377        unsigned long flags;
 378
 379        if (!uhid->running)
 380                return -EINVAL;
 381
 382        spin_lock_irqsave(&uhid->qlock, flags);
 383
 384        /* id for old report; drop it silently */
 385        if (atomic_read(&uhid->report_id) != ev->u.feature_answer.id)
 386                goto unlock;
 387        if (atomic_read(&uhid->report_done))
 388                goto unlock;
 389
 390        memcpy(&uhid->report_buf, ev, sizeof(*ev));
 391        atomic_set(&uhid->report_done, 1);
 392        wake_up_interruptible(&uhid->report_wait);
 393
 394unlock:
 395        spin_unlock_irqrestore(&uhid->qlock, flags);
 396        return 0;
 397}
 398
 399static int uhid_char_open(struct inode *inode, struct file *file)
 400{
 401        struct uhid_device *uhid;
 402
 403        uhid = kzalloc(sizeof(*uhid), GFP_KERNEL);
 404        if (!uhid)
 405                return -ENOMEM;
 406
 407        mutex_init(&uhid->devlock);
 408        mutex_init(&uhid->report_lock);
 409        spin_lock_init(&uhid->qlock);
 410        init_waitqueue_head(&uhid->waitq);
 411        init_waitqueue_head(&uhid->report_wait);
 412        uhid->running = false;
 413        atomic_set(&uhid->report_done, 1);
 414
 415        file->private_data = uhid;
 416        nonseekable_open(inode, file);
 417
 418        return 0;
 419}
 420
 421static int uhid_char_release(struct inode *inode, struct file *file)
 422{
 423        struct uhid_device *uhid = file->private_data;
 424        unsigned int i;
 425
 426        uhid_dev_destroy(uhid);
 427
 428        for (i = 0; i < UHID_BUFSIZE; ++i)
 429                kfree(uhid->outq[i]);
 430
 431        kfree(uhid);
 432
 433        return 0;
 434}
 435
 436static ssize_t uhid_char_read(struct file *file, char __user *buffer,
 437                                size_t count, loff_t *ppos)
 438{
 439        struct uhid_device *uhid = file->private_data;
 440        int ret;
 441        unsigned long flags;
 442        size_t len;
 443
 444        /* they need at least the "type" member of uhid_event */
 445        if (count < sizeof(__u32))
 446                return -EINVAL;
 447
 448try_again:
 449        if (file->f_flags & O_NONBLOCK) {
 450                if (uhid->head == uhid->tail)
 451                        return -EAGAIN;
 452        } else {
 453                ret = wait_event_interruptible(uhid->waitq,
 454                                                uhid->head != uhid->tail);
 455                if (ret)
 456                        return ret;
 457        }
 458
 459        ret = mutex_lock_interruptible(&uhid->devlock);
 460        if (ret)
 461                return ret;
 462
 463        if (uhid->head == uhid->tail) {
 464                mutex_unlock(&uhid->devlock);
 465                goto try_again;
 466        } else {
 467                len = min(count, sizeof(**uhid->outq));
 468                if (copy_to_user(buffer, uhid->outq[uhid->tail], len)) {
 469                        ret = -EFAULT;
 470                } else {
 471                        kfree(uhid->outq[uhid->tail]);
 472                        uhid->outq[uhid->tail] = NULL;
 473
 474                        spin_lock_irqsave(&uhid->qlock, flags);
 475                        uhid->tail = (uhid->tail + 1) % UHID_BUFSIZE;
 476                        spin_unlock_irqrestore(&uhid->qlock, flags);
 477                }
 478        }
 479
 480        mutex_unlock(&uhid->devlock);
 481        return ret ? ret : len;
 482}
 483
 484static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
 485                                size_t count, loff_t *ppos)
 486{
 487        struct uhid_device *uhid = file->private_data;
 488        int ret;
 489        size_t len;
 490
 491        /* we need at least the "type" member of uhid_event */
 492        if (count < sizeof(__u32))
 493                return -EINVAL;
 494
 495        ret = mutex_lock_interruptible(&uhid->devlock);
 496        if (ret)
 497                return ret;
 498
 499        memset(&uhid->input_buf, 0, sizeof(uhid->input_buf));
 500        len = min(count, sizeof(uhid->input_buf));
 501        if (copy_from_user(&uhid->input_buf, buffer, len)) {
 502                ret = -EFAULT;
 503                goto unlock;
 504        }
 505
 506        switch (uhid->input_buf.type) {
 507        case UHID_CREATE:
 508                ret = uhid_dev_create(uhid, &uhid->input_buf);
 509                break;
 510        case UHID_DESTROY:
 511                ret = uhid_dev_destroy(uhid);
 512                break;
 513        case UHID_INPUT:
 514                ret = uhid_dev_input(uhid, &uhid->input_buf);
 515                break;
 516        case UHID_FEATURE_ANSWER:
 517                ret = uhid_dev_feature_answer(uhid, &uhid->input_buf);
 518                break;
 519        default:
 520                ret = -EOPNOTSUPP;
 521        }
 522
 523unlock:
 524        mutex_unlock(&uhid->devlock);
 525
 526        /* return "count" not "len" to not confuse the caller */
 527        return ret ? ret : count;
 528}
 529
 530static unsigned int uhid_char_poll(struct file *file, poll_table *wait)
 531{
 532        struct uhid_device *uhid = file->private_data;
 533
 534        poll_wait(file, &uhid->waitq, wait);
 535
 536        if (uhid->head != uhid->tail)
 537                return POLLIN | POLLRDNORM;
 538
 539        return 0;
 540}
 541
 542static const struct file_operations uhid_fops = {
 543        .owner          = THIS_MODULE,
 544        .open           = uhid_char_open,
 545        .release        = uhid_char_release,
 546        .read           = uhid_char_read,
 547        .write          = uhid_char_write,
 548        .poll           = uhid_char_poll,
 549        .llseek         = no_llseek,
 550};
 551
 552static struct miscdevice uhid_misc = {
 553        .fops           = &uhid_fops,
 554        .minor          = MISC_DYNAMIC_MINOR,
 555        .name           = UHID_NAME,
 556};
 557
 558static int __init uhid_init(void)
 559{
 560        return misc_register(&uhid_misc);
 561}
 562
 563static void __exit uhid_exit(void)
 564{
 565        misc_deregister(&uhid_misc);
 566}
 567
 568module_init(uhid_init);
 569module_exit(uhid_exit);
 570MODULE_LICENSE("GPL");
 571MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
 572MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem");
 573
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.