aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--samples/uhid/uhid-example.c123
1 files changed, 103 insertions, 20 deletions
diff --git a/samples/uhid/uhid-example.c b/samples/uhid/uhid-example.c
index 03ce3c059a5e..7d58a4b8d324 100644
--- a/samples/uhid/uhid-example.c
+++ b/samples/uhid/uhid-example.c
@@ -1,14 +1,15 @@
1/* 1/*
2 * UHID Example 2 * UHID Example
3 * 3 *
4 * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com> 4 * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
5 * 5 *
6 * The code may be used by anyone for any purpose, 6 * The code may be used by anyone for any purpose,
7 * and can serve as a starting point for developing 7 * and can serve as a starting point for developing
8 * applications using uhid. 8 * applications using uhid.
9 */ 9 */
10 10
11/* UHID Example 11/*
12 * UHID Example
12 * This example emulates a basic 3 buttons mouse with wheel over UHID. Run this 13 * 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 * program as root and then use the following keys to control the mouse:
14 * q: Quit the application 15 * q: Quit the application
@@ -22,6 +23,11 @@
22 * r: Move wheel up 23 * r: Move wheel up
23 * f: Move wheel down 24 * f: Move wheel down
24 * 25 *
26 * Additionally to 3 button mouse, 3 keyboard LEDs are also supported (LED_NUML,
27 * LED_CAPSL and LED_SCROLLL). The device doesn't generate any related keyboard
28 * events, though. You need to manually write the EV_LED/LED_XY/1 activation
29 * input event to the evdev device to see it being sent to this device.
30 *
25 * If uhid is not available as /dev/uhid, then you can pass a different path as 31 * If uhid is not available as /dev/uhid, then you can pass a different path as
26 * first argument. 32 * first argument.
27 * If <linux/uhid.h> is not installed in /usr, then compile this with: 33 * If <linux/uhid.h> is not installed in /usr, then compile this with:
@@ -41,11 +47,12 @@
41#include <unistd.h> 47#include <unistd.h>
42#include <linux/uhid.h> 48#include <linux/uhid.h>
43 49
44/* HID Report Desciptor 50/*
45 * We emulate a basic 3 button mouse with wheel. This is the report-descriptor 51 * HID Report Desciptor
46 * as the kernel will parse it: 52 * We emulate a basic 3 button mouse with wheel and 3 keyboard LEDs. This is
53 * the report-descriptor as the kernel will parse it:
47 * 54 *
48 * INPUT[INPUT] 55 * INPUT(1)[INPUT]
49 * Field(0) 56 * Field(0)
50 * Physical(GenericDesktop.Pointer) 57 * Physical(GenericDesktop.Pointer)
51 * Application(GenericDesktop.Mouse) 58 * Application(GenericDesktop.Mouse)
@@ -72,6 +79,19 @@
72 * Report Count(3) 79 * Report Count(3)
73 * Report Offset(8) 80 * Report Offset(8)
74 * Flags( Variable Relative ) 81 * Flags( Variable Relative )
82 * OUTPUT(2)[OUTPUT]
83 * Field(0)
84 * Application(GenericDesktop.Keyboard)
85 * Usage(3)
86 * LED.NumLock
87 * LED.CapsLock
88 * LED.ScrollLock
89 * Logical Minimum(0)
90 * Logical Maximum(1)
91 * Report Size(1)
92 * Report Count(3)
93 * Report Offset(0)
94 * Flags( Variable Absolute )
75 * 95 *
76 * This is the mapping that we expect: 96 * This is the mapping that we expect:
77 * Button.0001 ---> Key.LeftBtn 97 * Button.0001 ---> Key.LeftBtn
@@ -80,19 +100,59 @@
80 * GenericDesktop.X ---> Relative.X 100 * GenericDesktop.X ---> Relative.X
81 * GenericDesktop.Y ---> Relative.Y 101 * GenericDesktop.Y ---> Relative.Y
82 * GenericDesktop.Wheel ---> Relative.Wheel 102 * GenericDesktop.Wheel ---> Relative.Wheel
103 * LED.NumLock ---> LED.NumLock
104 * LED.CapsLock ---> LED.CapsLock
105 * LED.ScrollLock ---> LED.ScrollLock
83 * 106 *
84 * This information can be verified by reading /sys/kernel/debug/hid/<dev>/rdesc 107 * This information can be verified by reading /sys/kernel/debug/hid/<dev>/rdesc
85 * This file should print the same information as showed above. 108 * This file should print the same information as showed above.
86 */ 109 */
87 110
88static unsigned char rdesc[] = { 111static unsigned char rdesc[] = {
89 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01, 112 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
90 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, 113 0x09, 0x02, /* USAGE (Mouse) */
91 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 114 0xa1, 0x01, /* COLLECTION (Application) */
92 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, 115 0x09, 0x01, /* USAGE (Pointer) */
93 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x38, 116 0xa1, 0x00, /* COLLECTION (Physical) */
94 0x15, 0x80, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x03, 117 0x85, 0x01, /* REPORT_ID (1) */
95 0x81, 0x06, 0xc0, 0xc0, 118 0x05, 0x09, /* USAGE_PAGE (Button) */
119 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */
120 0x29, 0x03, /* USAGE_MAXIMUM (Button 3) */
121 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
122 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
123 0x95, 0x03, /* REPORT_COUNT (3) */
124 0x75, 0x01, /* REPORT_SIZE (1) */
125 0x81, 0x02, /* INPUT (Data,Var,Abs) */
126 0x95, 0x01, /* REPORT_COUNT (1) */
127 0x75, 0x05, /* REPORT_SIZE (5) */
128 0x81, 0x01, /* INPUT (Cnst,Var,Abs) */
129 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
130 0x09, 0x30, /* USAGE (X) */
131 0x09, 0x31, /* USAGE (Y) */
132 0x09, 0x38, /* USAGE (WHEEL) */
133 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */
134 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */
135 0x75, 0x08, /* REPORT_SIZE (8) */
136 0x95, 0x03, /* REPORT_COUNT (3) */
137 0x81, 0x06, /* INPUT (Data,Var,Rel) */
138 0xc0, /* END_COLLECTION */
139 0xc0, /* END_COLLECTION */
140 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
141 0x09, 0x06, /* USAGE (Keyboard) */
142 0xa1, 0x01, /* COLLECTION (Application) */
143 0x85, 0x02, /* REPORT_ID (2) */
144 0x05, 0x08, /* USAGE_PAGE (Led) */
145 0x19, 0x01, /* USAGE_MINIMUM (1) */
146 0x29, 0x03, /* USAGE_MAXIMUM (3) */
147 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
148 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
149 0x95, 0x03, /* REPORT_COUNT (3) */
150 0x75, 0x01, /* REPORT_SIZE (1) */
151 0x91, 0x02, /* Output (Data,Var,Abs) */
152 0x95, 0x01, /* REPORT_COUNT (1) */
153 0x75, 0x05, /* REPORT_SIZE (5) */
154 0x91, 0x01, /* Output (Cnst,Var,Abs) */
155 0xc0, /* END_COLLECTION */
96}; 156};
97 157
98static int uhid_write(int fd, const struct uhid_event *ev) 158static int uhid_write(int fd, const struct uhid_event *ev)
@@ -140,6 +200,27 @@ static void destroy(int fd)
140 uhid_write(fd, &ev); 200 uhid_write(fd, &ev);
141} 201}
142 202
203/* This parses raw output reports sent by the kernel to the device. A normal
204 * uhid program shouldn't do this but instead just forward the raw report.
205 * However, for ducomentational purposes, we try to detect LED events here and
206 * print debug messages for it. */
207static void handle_output(struct uhid_event *ev)
208{
209 /* LED messages are adverised via OUTPUT reports; ignore the rest */
210 if (ev->u.output.rtype != UHID_OUTPUT_REPORT)
211 return;
212 /* LED reports have length 2 bytes */
213 if (ev->u.output.size != 2)
214 return;
215 /* first byte is report-id which is 0x02 for LEDs in our rdesc */
216 if (ev->u.output.data[0] != 0x2)
217 return;
218
219 /* print flags payload */
220 fprintf(stderr, "LED output report received with flags %x\n",
221 ev->u.output.data[1]);
222}
223
143static int event(int fd) 224static int event(int fd)
144{ 225{
145 struct uhid_event ev; 226 struct uhid_event ev;
@@ -174,6 +255,7 @@ static int event(int fd)
174 break; 255 break;
175 case UHID_OUTPUT: 256 case UHID_OUTPUT:
176 fprintf(stderr, "UHID_OUTPUT from uhid-dev\n"); 257 fprintf(stderr, "UHID_OUTPUT from uhid-dev\n");
258 handle_output(&ev);
177 break; 259 break;
178 case UHID_OUTPUT_EV: 260 case UHID_OUTPUT_EV:
179 fprintf(stderr, "UHID_OUTPUT_EV from uhid-dev\n"); 261 fprintf(stderr, "UHID_OUTPUT_EV from uhid-dev\n");
@@ -198,18 +280,19 @@ static int send_event(int fd)
198 280
199 memset(&ev, 0, sizeof(ev)); 281 memset(&ev, 0, sizeof(ev));
200 ev.type = UHID_INPUT; 282 ev.type = UHID_INPUT;
201 ev.u.input.size = 4; 283 ev.u.input.size = 5;
202 284
285 ev.u.input.data[0] = 0x1;
203 if (btn1_down) 286 if (btn1_down)
204 ev.u.input.data[0] |= 0x1; 287 ev.u.input.data[1] |= 0x1;
205 if (btn2_down) 288 if (btn2_down)
206 ev.u.input.data[0] |= 0x2; 289 ev.u.input.data[1] |= 0x2;
207 if (btn3_down) 290 if (btn3_down)
208 ev.u.input.data[0] |= 0x4; 291 ev.u.input.data[1] |= 0x4;
209 292
210 ev.u.input.data[1] = abs_hor; 293 ev.u.input.data[2] = abs_hor;
211 ev.u.input.data[2] = abs_ver; 294 ev.u.input.data[3] = abs_ver;
212 ev.u.input.data[3] = wheel; 295 ev.u.input.data[4] = wheel;
213 296
214 return uhid_write(fd, &ev); 297 return uhid_write(fd, &ev);
215} 298}