Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier...
[deliverable/linux.git] / drivers / hid / hidraw.c
CommitLineData
86166b7b
JK
1/*
2 * HID raw devices, giving access to raw HID events.
3 *
4 * In comparison to hiddev, this device does not process the
5 * hid events at all (no parsing, no lookups). This lets applications
6 * to work on raw hid events as they want to, and avoids a need to
7 * use a transport-specific userspace libhid/libusb libraries.
8 *
9 * Copyright (c) 2007 Jiri Kosina
10 */
11
12/*
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms and conditions of the GNU General Public License,
15 * version 2, as published by the Free Software Foundation.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
4291ee30
JP
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
86166b7b
JK
24#include <linux/fs.h>
25#include <linux/module.h>
26#include <linux/errno.h>
27#include <linux/kernel.h>
28#include <linux/init.h>
29#include <linux/cdev.h>
30#include <linux/poll.h>
31#include <linux/device.h>
32#include <linux/major.h>
5a0e3ad6 33#include <linux/slab.h>
86166b7b
JK
34#include <linux/hid.h>
35#include <linux/mutex.h>
a99bbaf5 36#include <linux/sched.h>
86166b7b
JK
37
38#include <linux/hidraw.h>
39
40static int hidraw_major;
41static struct cdev hidraw_cdev;
42static struct class *hidraw_class;
43static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
7d672cd7 44static DEFINE_MUTEX(minors_lock);
86166b7b
JK
45
46static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
47{
48 struct hidraw_list *list = file->private_data;
49 int ret = 0, len;
86166b7b
JK
50 DECLARE_WAITQUEUE(wait, current);
51
b0e14951 52 mutex_lock(&list->read_mutex);
86166b7b 53
b0e14951 54 while (ret == 0) {
86166b7b
JK
55 if (list->head == list->tail) {
56 add_wait_queue(&list->hidraw->wait, &wait);
57 set_current_state(TASK_INTERRUPTIBLE);
58
59 while (list->head == list->tail) {
60 if (file->f_flags & O_NONBLOCK) {
61 ret = -EAGAIN;
62 break;
63 }
64 if (signal_pending(current)) {
65 ret = -ERESTARTSYS;
66 break;
67 }
68 if (!list->hidraw->exist) {
69 ret = -EIO;
70 break;
71 }
72
73 /* allow O_NONBLOCK to work well from other threads */
74 mutex_unlock(&list->read_mutex);
75 schedule();
76 mutex_lock(&list->read_mutex);
77 set_current_state(TASK_INTERRUPTIBLE);
78 }
79
80 set_current_state(TASK_RUNNING);
81 remove_wait_queue(&list->hidraw->wait, &wait);
82 }
83
84 if (ret)
85 goto out;
86
86166b7b
JK
87 len = list->buffer[list->tail].len > count ?
88 count : list->buffer[list->tail].len;
89
90 if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
91 ret = -EFAULT;
92 goto out;
93 }
cf28a673 94 ret = len;
86166b7b
JK
95
96 kfree(list->buffer[list->tail].value);
97 list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
98 }
99out:
100 mutex_unlock(&list->read_mutex);
101 return ret;
102}
103
104/* the first byte is expected to be a report number */
b4dbde9d
AO
105/* This function is to be called with the minors_lock mutex held */
106static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type)
86166b7b
JK
107{
108 unsigned int minor = iminor(file->f_path.dentry->d_inode);
2e57480b 109 struct hid_device *dev;
86166b7b
JK
110 __u8 *buf;
111 int ret = 0;
112
e42dee9a
AO
113 if (!hidraw_table[minor]) {
114 ret = -ENODEV;
115 goto out;
116 }
117
2e57480b
JK
118 dev = hidraw_table[minor]->hid;
119
120 if (!dev->hid_output_raw_report) {
121 ret = -ENODEV;
122 goto out;
123 }
86166b7b 124
2b107d62 125 if (count > HID_MAX_BUFFER_SIZE) {
4291ee30
JP
126 hid_warn(dev, "pid %d passed too large report\n",
127 task_pid_nr(current));
2e57480b
JK
128 ret = -EINVAL;
129 goto out;
86166b7b
JK
130 }
131
132 if (count < 2) {
4291ee30
JP
133 hid_warn(dev, "pid %d passed too short report\n",
134 task_pid_nr(current));
2e57480b
JK
135 ret = -EINVAL;
136 goto out;
86166b7b
JK
137 }
138
139 buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);
2e57480b
JK
140 if (!buf) {
141 ret = -ENOMEM;
142 goto out;
143 }
86166b7b
JK
144
145 if (copy_from_user(buf, buffer, count)) {
146 ret = -EFAULT;
2e57480b 147 goto out_free;
86166b7b
JK
148 }
149
b4dbde9d 150 ret = dev->hid_output_raw_report(dev, buf, count, report_type);
2e57480b 151out_free:
86166b7b 152 kfree(buf);
2e57480b 153out:
b4dbde9d
AO
154 return ret;
155}
156
157/* the first byte is expected to be a report number */
158static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
159{
160 ssize_t ret;
161 mutex_lock(&minors_lock);
162 ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT);
2e57480b 163 mutex_unlock(&minors_lock);
86166b7b
JK
164 return ret;
165}
166
b4dbde9d
AO
167
168/* This function performs a Get_Report transfer over the control endpoint
169 per section 7.2.1 of the HID specification, version 1.1. The first byte
170 of buffer is the report number to request, or 0x0 if the defice does not
171 use numbered reports. The report_type parameter can be HID_FEATURE_REPORT
172 or HID_INPUT_REPORT. This function is to be called with the minors_lock
173 mutex held. */
174static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type)
175{
176 unsigned int minor = iminor(file->f_path.dentry->d_inode);
177 struct hid_device *dev;
178 __u8 *buf;
179 int ret = 0, len;
180 unsigned char report_number;
181
182 dev = hidraw_table[minor]->hid;
183
184 if (!dev->hid_get_raw_report) {
185 ret = -ENODEV;
186 goto out;
187 }
188
189 if (count > HID_MAX_BUFFER_SIZE) {
190 printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
191 task_pid_nr(current));
192 ret = -EINVAL;
193 goto out;
194 }
195
196 if (count < 2) {
197 printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
198 task_pid_nr(current));
199 ret = -EINVAL;
200 goto out;
201 }
202
203 buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);
204 if (!buf) {
205 ret = -ENOMEM;
206 goto out;
207 }
208
209 /* Read the first byte from the user. This is the report number,
210 which is passed to dev->hid_get_raw_report(). */
211 if (copy_from_user(&report_number, buffer, 1)) {
212 ret = -EFAULT;
213 goto out_free;
214 }
215
216 ret = dev->hid_get_raw_report(dev, report_number, buf, count, report_type);
217
218 if (ret < 0)
219 goto out_free;
220
221 len = (ret < count) ? ret : count;
222
223 if (copy_to_user(buffer, buf, len)) {
224 ret = -EFAULT;
225 goto out_free;
226 }
227
228 ret = len;
229
230out_free:
231 kfree(buf);
232out:
233 return ret;
234}
235
86166b7b
JK
236static unsigned int hidraw_poll(struct file *file, poll_table *wait)
237{
238 struct hidraw_list *list = file->private_data;
239
240 poll_wait(file, &list->hidraw->wait, wait);
241 if (list->head != list->tail)
242 return POLLIN | POLLRDNORM;
243 if (!list->hidraw->exist)
244 return POLLERR | POLLHUP;
245 return 0;
246}
247
248static int hidraw_open(struct inode *inode, struct file *file)
249{
250 unsigned int minor = iminor(inode);
251 struct hidraw *dev;
252 struct hidraw_list *list;
253 int err = 0;
254
255 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
256 err = -ENOMEM;
257 goto out;
258 }
259
7d672cd7 260 mutex_lock(&minors_lock);
86166b7b 261 if (!hidraw_table[minor]) {
86166b7b
JK
262 kfree(list);
263 err = -ENODEV;
264 goto out_unlock;
265 }
266
267 list->hidraw = hidraw_table[minor];
268 mutex_init(&list->read_mutex);
269 list_add_tail(&list->node, &hidraw_table[minor]->list);
270 file->private_data = list;
271
272 dev = hidraw_table[minor];
7d672cd7 273 if (!dev->open++) {
5bea7660
DT
274 err = hid_hw_power(dev->hid, PM_HINT_FULLON);
275 if (err < 0)
276 goto out_unlock;
277
278 err = hid_hw_open(dev->hid);
0361a28d 279 if (err < 0) {
5bea7660 280 hid_hw_power(dev->hid, PM_HINT_NORMAL);
7d672cd7 281 dev->open--;
0361a28d 282 }
7d672cd7 283 }
86166b7b
JK
284
285out_unlock:
7d672cd7 286 mutex_unlock(&minors_lock);
7d672cd7 287out:
86166b7b
JK
288 return err;
289
290}
291
292static int hidraw_release(struct inode * inode, struct file * file)
293{
294 unsigned int minor = iminor(inode);
295 struct hidraw *dev;
296 struct hidraw_list *list = file->private_data;
cb174681 297 int ret;
86166b7b 298
cb174681
JS
299 mutex_lock(&minors_lock);
300 if (!hidraw_table[minor]) {
301 ret = -ENODEV;
302 goto unlock;
303 }
86166b7b
JK
304
305 list_del(&list->node);
306 dev = hidraw_table[minor];
b8a832b1 307 if (!--dev->open) {
0361a28d 308 if (list->hidraw->exist) {
5bea7660
DT
309 hid_hw_power(dev->hid, PM_HINT_NORMAL);
310 hid_hw_close(dev->hid);
0361a28d 311 } else {
86166b7b 312 kfree(list->hidraw);
0361a28d 313 }
86166b7b 314 }
4db1c62c 315 kfree(list);
cb174681
JS
316 ret = 0;
317unlock:
318 mutex_unlock(&minors_lock);
4db1c62c 319
cb174681 320 return ret;
86166b7b
JK
321}
322
979c407e
AC
323static long hidraw_ioctl(struct file *file, unsigned int cmd,
324 unsigned long arg)
86166b7b 325{
979c407e 326 struct inode *inode = file->f_path.dentry->d_inode;
86166b7b 327 unsigned int minor = iminor(inode);
979c407e 328 long ret = 0;
2e57480b 329 struct hidraw *dev;
86166b7b
JK
330 void __user *user_arg = (void __user*) arg;
331
2e57480b
JK
332 mutex_lock(&minors_lock);
333 dev = hidraw_table[minor];
d20d5ffa
AO
334 if (!dev) {
335 ret = -ENODEV;
336 goto out;
337 }
2e57480b 338
86166b7b
JK
339 switch (cmd) {
340 case HIDIOCGRDESCSIZE:
341 if (put_user(dev->hid->rsize, (int __user *)arg))
979c407e
AC
342 ret = -EFAULT;
343 break;
86166b7b
JK
344
345 case HIDIOCGRDESC:
346 {
347 __u32 len;
348
349 if (get_user(len, (int __user *)arg))
979c407e
AC
350 ret = -EFAULT;
351 else if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
352 ret = -EINVAL;
353 else if (copy_to_user(user_arg + offsetof(
354 struct hidraw_report_descriptor,
355 value[0]),
356 dev->hid->rdesc,
357 min(dev->hid->rsize, len)))
358 ret = -EFAULT;
359 break;
86166b7b
JK
360 }
361 case HIDIOCGRAWINFO:
362 {
363 struct hidraw_devinfo dinfo;
364
365 dinfo.bustype = dev->hid->bus;
366 dinfo.vendor = dev->hid->vendor;
367 dinfo.product = dev->hid->product;
368 if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
979c407e
AC
369 ret = -EFAULT;
370 break;
86166b7b
JK
371 }
372 default:
9188e79e
JK
373 {
374 struct hid_device *hid = dev->hid;
b4dbde9d
AO
375 if (_IOC_TYPE(cmd) != 'H') {
376 ret = -EINVAL;
377 break;
378 }
379
380 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSFEATURE(0))) {
381 int len = _IOC_SIZE(cmd);
382 ret = hidraw_send_report(file, user_arg, len, HID_FEATURE_REPORT);
383 break;
384 }
385 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGFEATURE(0))) {
386 int len = _IOC_SIZE(cmd);
387 ret = hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT);
388 break;
389 }
390
391 /* Begin Read-only ioctls. */
392 if (_IOC_DIR(cmd) != _IOC_READ) {
dfd395af
DC
393 ret = -EINVAL;
394 break;
395 }
9188e79e
JK
396
397 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
398 int len;
38089c65
DC
399 if (!hid->name) {
400 ret = 0;
401 break;
402 }
9188e79e
JK
403 len = strlen(hid->name) + 1;
404 if (len > _IOC_SIZE(cmd))
405 len = _IOC_SIZE(cmd);
dfd395af 406 ret = copy_to_user(user_arg, hid->name, len) ?
9188e79e 407 -EFAULT : len;
dfd395af 408 break;
9188e79e
JK
409 }
410
411 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
412 int len;
38089c65
DC
413 if (!hid->phys) {
414 ret = 0;
415 break;
416 }
9188e79e
JK
417 len = strlen(hid->phys) + 1;
418 if (len > _IOC_SIZE(cmd))
419 len = _IOC_SIZE(cmd);
dfd395af 420 ret = copy_to_user(user_arg, hid->phys, len) ?
9188e79e 421 -EFAULT : len;
dfd395af 422 break;
9188e79e 423 }
b4dbde9d 424 }
9188e79e 425
dfd395af 426 ret = -ENOTTY;
86166b7b 427 }
d20d5ffa 428out:
2e57480b 429 mutex_unlock(&minors_lock);
979c407e 430 return ret;
86166b7b
JK
431}
432
433static const struct file_operations hidraw_ops = {
434 .owner = THIS_MODULE,
435 .read = hidraw_read,
436 .write = hidraw_write,
437 .poll = hidraw_poll,
438 .open = hidraw_open,
439 .release = hidraw_release,
979c407e 440 .unlocked_ioctl = hidraw_ioctl,
ae5e49c7
AO
441#ifdef CONFIG_COMPAT
442 .compat_ioctl = hidraw_ioctl,
443#endif
6038f373 444 .llseek = noop_llseek,
86166b7b
JK
445};
446
447void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
448{
449 struct hidraw *dev = hid->hidraw;
450 struct hidraw_list *list;
451
452 list_for_each_entry(list, &dev->list, node) {
453 list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC);
454 list->buffer[list->head].len = len;
455 list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
456 kill_fasync(&list->fasync, SIGIO, POLL_IN);
457 }
458
459 wake_up_interruptible(&dev->wait);
460}
461EXPORT_SYMBOL_GPL(hidraw_report_event);
462
463int hidraw_connect(struct hid_device *hid)
464{
709d27c0 465 int minor, result;
86166b7b
JK
466 struct hidraw *dev;
467
bbe281fa 468 /* we accept any HID device, no matter the applications */
86166b7b 469
709d27c0
MK
470 dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
471 if (!dev)
472 return -ENOMEM;
473
474 result = -EINVAL;
86166b7b 475
7d672cd7 476 mutex_lock(&minors_lock);
86166b7b
JK
477
478 for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) {
479 if (hidraw_table[minor])
480 continue;
481 hidraw_table[minor] = dev;
482 result = 0;
483 break;
484 }
485
709d27c0 486 if (result) {
7d672cd7 487 mutex_unlock(&minors_lock);
709d27c0 488 kfree(dev);
86166b7b 489 goto out;
709d27c0 490 }
86166b7b 491
aae6c286 492 dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor),
a9b12619 493 NULL, "%s%d", "hidraw", minor);
86166b7b
JK
494
495 if (IS_ERR(dev->dev)) {
86166b7b 496 hidraw_table[minor] = NULL;
7d672cd7 497 mutex_unlock(&minors_lock);
86166b7b 498 result = PTR_ERR(dev->dev);
709d27c0 499 kfree(dev);
86166b7b
JK
500 goto out;
501 }
502
7d672cd7 503 mutex_unlock(&minors_lock);
86166b7b
JK
504 init_waitqueue_head(&dev->wait);
505 INIT_LIST_HEAD(&dev->list);
506
507 dev->hid = hid;
508 dev->minor = minor;
509
510 dev->exist = 1;
511 hid->hidraw = dev;
512
513out:
514 return result;
515
516}
517EXPORT_SYMBOL_GPL(hidraw_connect);
518
519void hidraw_disconnect(struct hid_device *hid)
520{
521 struct hidraw *hidraw = hid->hidraw;
522
523 hidraw->exist = 0;
524
3a22ebe9
SA
525 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
526
7d672cd7 527 mutex_lock(&minors_lock);
86166b7b 528 hidraw_table[hidraw->minor] = NULL;
7d672cd7 529 mutex_unlock(&minors_lock);
86166b7b 530
86166b7b 531 if (hidraw->open) {
5bea7660 532 hid_hw_close(hid);
86166b7b
JK
533 wake_up_interruptible(&hidraw->wait);
534 } else {
535 kfree(hidraw);
536 }
537}
538EXPORT_SYMBOL_GPL(hidraw_disconnect);
539
540int __init hidraw_init(void)
541{
542 int result;
543 dev_t dev_id;
544
545 result = alloc_chrdev_region(&dev_id, HIDRAW_FIRST_MINOR,
546 HIDRAW_MAX_DEVICES, "hidraw");
547
548 hidraw_major = MAJOR(dev_id);
549
550 if (result < 0) {
4291ee30 551 pr_warn("can't get major number\n");
86166b7b
JK
552 result = 0;
553 goto out;
554 }
555
556 hidraw_class = class_create(THIS_MODULE, "hidraw");
557 if (IS_ERR(hidraw_class)) {
558 result = PTR_ERR(hidraw_class);
559 unregister_chrdev(hidraw_major, "hidraw");
560 goto out;
561 }
562
563 cdev_init(&hidraw_cdev, &hidraw_ops);
564 cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES);
565out:
566 return result;
567}
568
140ae3eb 569void hidraw_exit(void)
86166b7b
JK
570{
571 dev_t dev_id = MKDEV(hidraw_major, 0);
572
573 cdev_del(&hidraw_cdev);
574 class_destroy(hidraw_class);
575 unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
576
577}
This page took 0.286076 seconds and 5 git commands to generate.