aboutsummaryrefslogtreecommitdiffstats
path: root/samples
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-24 16:30:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-24 16:30:14 -0400
commite8ff13b0bf88b5e696323a1eec877783d965b3c6 (patch)
treeaa55093da5ee435f0d2fa8ffede8973f426dbd67 /samples
parent0cd5ff591ab6473355d5a6a47f7694def28e451d (diff)
parentc062c4d1de57789bf15f7641a24c429eeb8a1c6a (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina: "The list of changes worth pointing out explicitly: - We are getting 'UHID', which is a new framework for implementing HID transport drivers in userspace (this is different from HIDRAW, which is transport-independent and provides report parsing facilities; uhid is for the other (transport) part of the pipeline). It's needed for (and currently being used by) Bluetooth-LowEnergy, as its specification mandates things we don't want in the kernel. Written by David Herrmann. - there have been quite a few bugs in runtime suspend/resume paths (probably never reported to actually happen in the wild, but still). Alan Stern fixed those. - a few other driver updates and fixes and random new device support." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (45 commits) HID: add ASUS AIO keyboard model AK1D HID: add support for Cypress barcode scanner 04B4:ED81 HID: Allow drivers to be their own listener HID: usbhid: fix error paths in suspend HID: usbhid: check for suspend or reset before restarting HID: usbhid: replace HID_REPORTED_IDLE with HID_SUSPENDED HID: usbhid: inline some simple routines HID: usbhid: fix autosuspend calls HID: usbhid: fix use-after-free bug HID: hid-core: optimize in case of hidraw HID: hidraw: fix list->buffer memleak HID: uhid: Fix sending events with invalid data HID: roccat: added sensor sysfs attribute for Savu HID: Add driver for Holtek based keyboards with broken HID HID: Add suport for the brightness control keys on HP keyboards HID: magicmouse: Implement Multi-touch Protocol B (MT-B) HID: magicmouse: Removing report_touches switch HID: roccat: rename roccat_common functions to roccat_common2 HID: roccat: fix wrong hid_err usage on struct usb_device HID: roccat: move functionality to roccat-common ...
Diffstat (limited to 'samples')
-rw-r--r--samples/uhid/Makefile10
-rw-r--r--samples/uhid/uhid-example.c381
2 files changed, 391 insertions, 0 deletions
diff --git a/samples/uhid/Makefile b/samples/uhid/Makefile
new file mode 100644
index 000000000000..c95a696560a7
--- /dev/null
+++ b/samples/uhid/Makefile
@@ -0,0 +1,10 @@
1# kbuild trick to avoid linker error. Can be omitted if a module is built.
2obj- := dummy.o
3
4# List of programs to build
5hostprogs-y := uhid-example
6
7# Tell kbuild to always build the programs
8always := $(hostprogs-y)
9
10HOSTCFLAGS_uhid-example.o += -I$(objtree)/usr/include
diff --git a/samples/uhid/uhid-example.c b/samples/uhid/uhid-example.c
new file mode 100644
index 000000000000..03ce3c059a5e
--- /dev/null
+++ b/samples/uhid/uhid-example.c
@@ -0,0 +1,381 @@
1/*
2 * UHID Example
3 *
4 * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
5 *
6 * The code may be used by anyone for any purpose,
7 * and can serve as a starting point for developing
8 * applications using uhid.
9 */
10
11/* UHID Example
12 * This example emulates a basic 3 buttons mouse with wheel over UHID. Run this
13 * program as root and then use the following keys to control the mouse:
14 * q: Quit the application
15 * 1: Toggle left button (down, up, ...)
16 * 2: Toggle right button
17 * 3: Toggle middle button
18 * a: Move mouse left
19 * d: Move mouse right
20 * w: Move mouse up
21 * s: Move mouse down
22 * r: Move wheel up
23 * f: Move wheel down
24 *
25 * If uhid is not available as /dev/uhid, then you can pass a different path as
26 * first argument.
27 * If <linux/uhid.h> is not installed in /usr, then compile this with:
28 * gcc -o ./uhid_test -Wall -I./include ./samples/uhid/uhid-example.c
29 * And ignore the warning about kernel headers. However, it is recommended to
30 * use the installed uhid.h if available.
31 */
32
33#include <errno.h>
34#include <fcntl.h>
35#include <poll.h>
36#include <stdbool.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <termios.h>
41#include <unistd.h>
42#include <linux/uhid.h>
43
44/* HID Report Desciptor
45 * We emulate a basic 3 button mouse with wheel. This is the report-descriptor
46 * as the kernel will parse it:
47 *
48 * INPUT[INPUT]
49 * Field(0)
50 * Physical(GenericDesktop.Pointer)
51 * Application(GenericDesktop.Mouse)
52 * Usage(3)
53 * Button.0001
54 * Button.0002
55 * Button.0003
56 * Logical Minimum(0)
57 * Logical Maximum(1)
58 * Report Size(1)
59 * Report Count(3)
60 * Report Offset(0)
61 * Flags( Variable Absolute )
62 * Field(1)
63 * Physical(GenericDesktop.Pointer)
64 * Application(GenericDesktop.Mouse)
65 * Usage(3)
66 * GenericDesktop.X
67 * GenericDesktop.Y
68 * GenericDesktop.Wheel
69 * Logical Minimum(-128)
70 * Logical Maximum(127)
71 * Report Size(8)
72 * Report Count(3)
73 * Report Offset(8)
74 * Flags( Variable Relative )
75 *
76 * This is the mapping that we expect:
77 * Button.0001 ---> Key.LeftBtn
78 * Button.0002 ---> Key.RightBtn
79 * Button.0003 ---> Key.MiddleBtn
80 * GenericDesktop.X ---> Relative.X
81 * GenericDesktop.Y ---> Relative.Y
82 * GenericDesktop.Wheel ---> Relative.Wheel
83 *
84 * This information can be verified by reading /sys/kernel/debug/hid/<dev>/rdesc
85 * This file should print the same information as showed above.
86 */
87
88static unsigned char rdesc[] = {
89 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01,
90 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
91 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
92 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
93 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x38,
94 0x15, 0x80, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x03,
95 0x81, 0x06, 0xc0, 0xc0,
96};
97
98static int uhid_write(int fd, const struct uhid_event *ev)
99{
100 ssize_t ret;
101
102 ret = write(fd, ev, sizeof(*ev));
103 if (ret < 0) {
104 fprintf(stderr, "Cannot write to uhid: %m\n");
105 return -errno;
106 } else if (ret != sizeof(*ev)) {
107 fprintf(stderr, "Wrong size written to uhid: %ld != %lu\n",
108 ret, sizeof(ev));
109 return -EFAULT;
110 } else {
111 return 0;
112 }
113}
114
115static int create(int fd)
116{
117 struct uhid_event ev;
118
119 memset(&ev, 0, sizeof(ev));
120 ev.type = UHID_CREATE;
121 strcpy((char*)ev.u.create.name, "test-uhid-device");
122 ev.u.create.rd_data = rdesc;
123 ev.u.create.rd_size = sizeof(rdesc);
124 ev.u.create.bus = BUS_USB;
125 ev.u.create.vendor = 0x15d9;
126 ev.u.create.product = 0x0a37;
127 ev.u.create.version = 0;
128 ev.u.create.country = 0;
129
130 return uhid_write(fd, &ev);
131}
132
133static void destroy(int fd)
134{
135 struct uhid_event ev;
136
137 memset(&ev, 0, sizeof(ev));
138 ev.type = UHID_DESTROY;
139
140 uhid_write(fd, &ev);
141}
142
143static int event(int fd)
144{
145 struct uhid_event ev;
146 ssize_t ret;
147
148 memset(&ev, 0, sizeof(ev));
149 ret = read(fd, &ev, sizeof(ev));
150 if (ret == 0) {
151 fprintf(stderr, "Read HUP on uhid-cdev\n");
152 return -EFAULT;
153 } else if (ret < 0) {
154 fprintf(stderr, "Cannot read uhid-cdev: %m\n");
155 return -errno;
156 } else if (ret != sizeof(ev)) {
157 fprintf(stderr, "Invalid size read from uhid-dev: %ld != %lu\n",
158 ret, sizeof(ev));
159 return -EFAULT;
160 }
161
162 switch (ev.type) {
163 case UHID_START:
164 fprintf(stderr, "UHID_START from uhid-dev\n");
165 break;
166 case UHID_STOP:
167 fprintf(stderr, "UHID_STOP from uhid-dev\n");
168 break;
169 case UHID_OPEN:
170 fprintf(stderr, "UHID_OPEN from uhid-dev\n");
171 break;
172 case UHID_CLOSE:
173 fprintf(stderr, "UHID_CLOSE from uhid-dev\n");
174 break;
175 case UHID_OUTPUT:
176 fprintf(stderr, "UHID_OUTPUT from uhid-dev\n");
177 break;
178 case UHID_OUTPUT_EV:
179 fprintf(stderr, "UHID_OUTPUT_EV from uhid-dev\n");
180 break;
181 default:
182 fprintf(stderr, "Invalid event from uhid-dev: %u\n", ev.type);
183 }
184
185 return 0;
186}
187
188static bool btn1_down;
189static bool btn2_down;
190static bool btn3_down;
191static signed char abs_hor;
192static signed char abs_ver;
193static signed char wheel;
194
195static int send_event(i