diff options
author | Petri Gynther <pgynther@google.com> | 2014-03-24 16:50:01 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-04-01 12:27:33 -0400 |
commit | 4522643aa9630be17238edf1b4c0b690c5dd7f5d (patch) | |
tree | 4476b31d4cab4643baeaf0877e21da51f69c7ad2 | |
parent | c3d77fab51f40821de91a744e4b514e9e4e76a7c (diff) |
HID: uhid: Add UHID_CREATE2 + UHID_INPUT2
UHID_CREATE2:
HID report descriptor data (rd_data) is an array in struct uhid_create2_req,
instead of a pointer. Enables use from languages that don't support pointers,
e.g. Python.
UHID_INPUT2:
Data array is the last field of struct uhid_input2_req. Enables userspace to
write only the required bytes to kernel (ev.type + ev.u.input2.size + the part
of the data array that matters), instead of the entire struct uhid_input2_req.
Note:
UHID_CREATE2 increases the total size of struct uhid_event slightly, thus
increasing the size of messages that are queued for userspace. However, this
won't affect the userspace processing of these events.
[Jiri Kosina <jkosina@suse.cz>: adjust to hid_get_raw_report() and
hid_output_raw_report() API changes]
Signed-off-by: Petri Gynther <pgynther@google.com>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | Documentation/hid/uhid.txt | 11 | ||||
-rw-r--r-- | drivers/hid/uhid.c | 78 | ||||
-rw-r--r-- | include/uapi/linux/uhid.h | 23 |
3 files changed, 112 insertions, 0 deletions
diff --git a/Documentation/hid/uhid.txt b/Documentation/hid/uhid.txt index dc35a2b75eee..ee6593608c8e 100644 --- a/Documentation/hid/uhid.txt +++ b/Documentation/hid/uhid.txt | |||
@@ -93,6 +93,11 @@ the request was handled successfully. | |||
93 | event to the kernel. The payload is of type struct uhid_create_req and | 93 | event to the kernel. The payload is of type struct uhid_create_req and |
94 | contains information about your device. You can start I/O now. | 94 | contains information about your device. You can start I/O now. |
95 | 95 | ||
96 | UHID_CREATE2: | ||
97 | Same as UHID_CREATE, but the HID report descriptor data (rd_data) is an array | ||
98 | inside struct uhid_create2_req, instead of a pointer to a separate array. | ||
99 | Enables use from languages that don't support pointers, e.g. Python. | ||
100 | |||
96 | UHID_DESTROY: | 101 | UHID_DESTROY: |
97 | This destroys the internal HID device. No further I/O will be accepted. There | 102 | This destroys the internal HID device. No further I/O will be accepted. There |
98 | may still be pending messages that you can receive with read() but no further | 103 | may still be pending messages that you can receive with read() but no further |
@@ -105,6 +110,12 @@ the request was handled successfully. | |||
105 | contains a data-payload. This is the raw data that you read from your device. | 110 | contains a data-payload. This is the raw data that you read from your device. |
106 | The kernel will parse the HID reports and react on it. | 111 | The kernel will parse the HID reports and react on it. |
107 | 112 | ||
113 | UHID_INPUT2: | ||
114 | Same as UHID_INPUT, but the data array is the last field of uhid_input2_req. | ||
115 | Enables userspace to write only the required bytes to kernel (ev.type + | ||
116 | ev.u.input2.size + the part of the data array that matters), instead of | ||
117 | the entire struct uhid_input2_req. | ||
118 | |||
108 | UHID_FEATURE_ANSWER: | 119 | UHID_FEATURE_ANSWER: |
109 | If you receive a UHID_FEATURE request you must answer with this request. You | 120 | If you receive a UHID_FEATURE request you must answer with this request. You |
110 | must copy the "id" field from the request into the answer. Set the "err" field | 121 | must copy the "id" field from the request into the answer. Set the "err" field |
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 7ed79be2686a..0d078c32db4f 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c | |||
@@ -428,6 +428,67 @@ err_free: | |||
428 | return ret; | 428 | return ret; |
429 | } | 429 | } |
430 | 430 | ||
431 | static int uhid_dev_create2(struct uhid_device *uhid, | ||
432 | const struct uhid_event *ev) | ||
433 | { | ||
434 | struct hid_device *hid; | ||
435 | int ret; | ||
436 | |||
437 | if (uhid->running) | ||
438 | return -EALREADY; | ||
439 | |||
440 | uhid->rd_size = ev->u.create2.rd_size; | ||
441 | if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE) | ||
442 | return -EINVAL; | ||
443 | |||
444 | uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL); | ||
445 | if (!uhid->rd_data) | ||
446 | return -ENOMEM; | ||
447 | |||
448 | memcpy(uhid->rd_data, ev->u.create2.rd_data, uhid->rd_size); | ||
449 | |||
450 | hid = hid_allocate_device(); | ||
451 | if (IS_ERR(hid)) { | ||
452 | ret = PTR_ERR(hid); | ||
453 | goto err_free; | ||
454 | } | ||
455 | |||
456 | strncpy(hid->name, ev->u.create2.name, 127); | ||
457 | hid->name[127] = 0; | ||
458 | strncpy(hid->phys, ev->u.create2.phys, 63); | ||
459 | hid->phys[63] = 0; | ||
460 | strncpy(hid->uniq, ev->u.create2.uniq, 63); | ||
461 | hid->uniq[63] = 0; | ||
462 | |||
463 | hid->ll_driver = &uhid_hid_driver; | ||
464 | hid->bus = ev->u.create2.bus; | ||
465 | hid->vendor = ev->u.create2.vendor; | ||
466 | hid->product = ev->u.create2.product; | ||
467 | hid->version = ev->u.create2.version; | ||
468 | hid->country = ev->u.create2.country; | ||
469 | hid->driver_data = uhid; | ||
470 | hid->dev.parent = uhid_misc.this_device; | ||
471 | |||
472 | uhid->hid = hid; | ||
473 | uhid->running = true; | ||
474 | |||
475 | ret = hid_add_device(hid); | ||
476 | if (ret) { | ||
477 | hid_err(hid, "Cannot register HID device\n"); | ||
478 | goto err_hid; | ||
479 | } | ||
480 | |||
481 | return 0; | ||
482 | |||
483 | err_hid: | ||
484 | hid_destroy_device(hid); | ||
485 | uhid->hid = NULL; | ||
486 | uhid->running = false; | ||
487 | err_free: | ||
488 | kfree(uhid->rd_data); | ||
489 | return ret; | ||
490 | } | ||
491 | |||
431 | static int uhid_dev_destroy(struct uhid_device *uhid) | 492 | static int uhid_dev_destroy(struct uhid_device *uhid) |
432 | { | 493 | { |
433 | if (!uhid->running) | 494 | if (!uhid->running) |
@@ -456,6 +517,17 @@ static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev) | |||
456 | return 0; | 517 | return 0; |
457 | } | 518 | } |
458 | 519 | ||
520 | static int uhid_dev_input2(struct uhid_device *uhid, struct uhid_event *ev) | ||
521 | { | ||
522 | if (!uhid->running) | ||
523 | return -EINVAL; | ||
524 | |||
525 | hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input2.data, | ||
526 | min_t(size_t, ev->u.input2.size, UHID_DATA_MAX), 0); | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
459 | static int uhid_dev_feature_answer(struct uhid_device *uhid, | 531 | static int uhid_dev_feature_answer(struct uhid_device *uhid, |
460 | struct uhid_event *ev) | 532 | struct uhid_event *ev) |
461 | { | 533 | { |
@@ -592,12 +664,18 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer, | |||
592 | case UHID_CREATE: | 664 | case UHID_CREATE: |
593 | ret = uhid_dev_create(uhid, &uhid->input_buf); | 665 | ret = uhid_dev_create(uhid, &uhid->input_buf); |
594 | break; | 666 | break; |
667 | case UHID_CREATE2: | ||
668 | ret = uhid_dev_create2(uhid, &uhid->input_buf); | ||
669 | break; | ||
595 | case UHID_DESTROY: | 670 | case UHID_DESTROY: |
596 | ret = uhid_dev_destroy(uhid); | 671 | ret = uhid_dev_destroy(uhid); |
597 | break; | 672 | break; |
598 | case UHID_INPUT: | 673 | case UHID_INPUT: |
599 | ret = uhid_dev_input(uhid, &uhid->input_buf); | 674 | ret = uhid_dev_input(uhid, &uhid->input_buf); |
600 | break; | 675 | break; |
676 | case UHID_INPUT2: | ||
677 | ret = uhid_dev_input2(uhid, &uhid->input_buf); | ||
678 | break; | ||
601 | case UHID_FEATURE_ANSWER: | 679 | case UHID_FEATURE_ANSWER: |
602 | ret = uhid_dev_feature_answer(uhid, &uhid->input_buf); | 680 | ret = uhid_dev_feature_answer(uhid, &uhid->input_buf); |
603 | break; | 681 | break; |
diff --git a/include/uapi/linux/uhid.h b/include/uapi/linux/uhid.h index 414b74be4da1..1e3b09c191cd 100644 --- a/include/uapi/linux/uhid.h +++ b/include/uapi/linux/uhid.h | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <linux/input.h> | 22 | #include <linux/input.h> |
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/hid.h> | ||
24 | 25 | ||
25 | enum uhid_event_type { | 26 | enum uhid_event_type { |
26 | UHID_CREATE, | 27 | UHID_CREATE, |
@@ -34,6 +35,8 @@ enum uhid_event_type { | |||
34 | UHID_INPUT, | 35 | UHID_INPUT, |
35 | UHID_FEATURE, | 36 | UHID_FEATURE, |
36 | UHID_FEATURE_ANSWER, | 37 | UHID_FEATURE_ANSWER, |
38 | UHID_CREATE2, | ||
39 | UHID_INPUT2, | ||
37 | }; | 40 | }; |
38 | 41 | ||
39 | struct uhid_create_req { | 42 | struct uhid_create_req { |
@@ -50,6 +53,19 @@ struct uhid_create_req { | |||
50 | __u32 country; | 53 | __u32 country; |
51 | } __attribute__((__packed__)); | 54 | } __attribute__((__packed__)); |
52 | 55 | ||
56 | struct uhid_create2_req { | ||
57 | __u8 name[128]; | ||
58 | __u8 phys[64]; | ||
59 | __u8 uniq[64]; | ||
60 | __u16 rd_size; | ||
61 | __u16 bus; | ||
62 | __u32 vendor; | ||
63 | __u32 product; | ||
64 | __u32 version; | ||
65 | __u32 country; | ||
66 | __u8 rd_data[HID_MAX_DESCRIPTOR_SIZE]; | ||
67 | } __attribute__((__packed__)); | ||
68 | |||
53 | #define UHID_DATA_MAX 4096 | 69 | #define UHID_DATA_MAX 4096 |
54 | 70 | ||
55 | enum uhid_report_type { | 71 | enum uhid_report_type { |
@@ -63,6 +79,11 @@ struct uhid_input_req { | |||
63 | __u16 size; | 79 | __u16 size; |
64 | } __attribute__((__packed__)); | 80 | } __attribute__((__packed__)); |
65 | 81 | ||
82 | struct uhid_input2_req { | ||
83 | __u16 size; | ||
84 | __u8 data[UHID_DATA_MAX]; | ||
85 | } __attribute__((__packed__)); | ||
86 | |||
66 | struct uhid_output_req { | 87 | struct uhid_output_req { |
67 | __u8 data[UHID_DATA_MAX]; | 88 | __u8 data[UHID_DATA_MAX]; |
68 | __u16 size; | 89 | __u16 size; |
@@ -100,6 +121,8 @@ struct uhid_event { | |||
100 | struct uhid_output_ev_req output_ev; | 121 | struct uhid_output_ev_req output_ev; |
101 | struct uhid_feature_req feature; | 122 | struct uhid_feature_req feature; |
102 | struct uhid_feature_answer_req feature_answer; | 123 | struct uhid_feature_answer_req feature_answer; |
124 | struct uhid_create2_req create2; | ||
125 | struct uhid_input2_req input2; | ||
103 | } u; | 126 | } u; |
104 | } __attribute__((__packed__)); | 127 | } __attribute__((__packed__)); |
105 | 128 | ||