diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 09:30:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 09:30:36 -0700 |
commit | 22e04f6b4b04a8afe9af9239224591d06ba3b24d (patch) | |
tree | 9bb72350400153ab232e227a378f94e95ad27569 /samples | |
parent | ec0ad730802173ec17e942f4b652a1819b1025b2 (diff) | |
parent | 4e5a494e4b4ba7e6aa1a8a285e98e3665fcb396e (diff) | |
download | blackbird-op-linux-22e04f6b4b04a8afe9af9239224591d06ba3b24d.tar.gz blackbird-op-linux-22e04f6b4b04a8afe9af9239224591d06ba3b24d.zip |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina:
"Highlights:
- conversion of HID subsystem to use devm-based resource management,
from Benjamin Tissoires
- i2c-hid support for DT bindings, from Benjamin Tissoires
- much improved support for Win8-multitouch devices, from Benjamin
Tissoires
- cleanup of core code using common hidinput_input_event(), from
David Herrmann
- fix for bug in implement() access to the bit stream (causing oops)
that has been present in the code for ages, but devices that are
able to trigger it have started to appear only now, from Jiri
Kosina
- fixes for CVE-2013-2899, CVE-2013-2898, CVE-2013-2896,
CVE-2013-2892, CVE-2013-2888 (all triggerable only by specially
crafted malicious HW devices plugged into the system), from Kees
Cook
- hidraw oops fix, from Manoj Chourasia
- various smaller fixes here and there, support for a bunch of new
devices by various contributors"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (53 commits)
HID: MAINTAINERS: add roccat drivers
HID: hid-sensor-hub: change kmalloc + memcpy by kmemdup
HID: hid-sensor-hub: move to devm_kzalloc
HID: hid-sensor-hub: fix indentation accross the code
HID: move HID_REPORT_TYPES closer to the report-definitions
HID: check for NULL field when setting values
HID: picolcd_core: validate output report details
HID: sensor-hub: validate feature report details
HID: ntrig: validate feature report details
HID: pantherlord: validate output report details
HID: hid-wiimote: print small buffers via %*phC
HID: uhid: improve uhid example client
HID: Correct the USB IDs for the new Macbook Air 6
HID: wiimote: add support for Guitar-Hero guitars
HID: wiimote: add support for Guitar-Hero drums
Input: introduce BTN/ABS bits for drums and guitars
HID: battery: don't do DMA from stack
HID: roccat: add support for KonePureOptical v2
HID: picolcd: Prevent NULL pointer dereference on _remove()
HID: usbhid: quirk for N-Trig DuoSense Touch Screen
...
Diffstat (limited to 'samples')
-rw-r--r-- | samples/hidraw/.gitignore | 1 | ||||
-rw-r--r-- | samples/uhid/uhid-example.c | 123 |
2 files changed, 104 insertions, 20 deletions
diff --git a/samples/hidraw/.gitignore b/samples/hidraw/.gitignore new file mode 100644 index 000000000000..05e51a685242 --- /dev/null +++ b/samples/hidraw/.gitignore @@ -0,0 +1 @@ +hid-example 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 @@ /* * UHID Example * - * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com> + * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com> * * The code may be used by anyone for any purpose, * and can serve as a starting point for developing * applications using uhid. */ -/* UHID Example +/* + * UHID Example * This example emulates a basic 3 buttons mouse with wheel over UHID. Run this * program as root and then use the following keys to control the mouse: * q: Quit the application @@ -22,6 +23,11 @@ * r: Move wheel up * f: Move wheel down * + * Additionally to 3 button mouse, 3 keyboard LEDs are also supported (LED_NUML, + * LED_CAPSL and LED_SCROLLL). The device doesn't generate any related keyboard + * events, though. You need to manually write the EV_LED/LED_XY/1 activation + * input event to the evdev device to see it being sent to this device. + * * If uhid is not available as /dev/uhid, then you can pass a different path as * first argument. * If <linux/uhid.h> is not installed in /usr, then compile this with: @@ -41,11 +47,12 @@ #include <unistd.h> #include <linux/uhid.h> -/* HID Report Desciptor - * We emulate a basic 3 button mouse with wheel. This is the report-descriptor - * as the kernel will parse it: +/* + * HID Report Desciptor + * We emulate a basic 3 button mouse with wheel and 3 keyboard LEDs. This is + * the report-descriptor as the kernel will parse it: * - * INPUT[INPUT] + * INPUT(1)[INPUT] * Field(0) * Physical(GenericDesktop.Pointer) * Application(GenericDesktop.Mouse) @@ -72,6 +79,19 @@ * Report Count(3) * Report Offset(8) * Flags( Variable Relative ) + * OUTPUT(2)[OUTPUT] + * Field(0) + * Application(GenericDesktop.Keyboard) + * Usage(3) + * LED.NumLock + * LED.CapsLock + * LED.ScrollLock + * Logical Minimum(0) + * Logical Maximum(1) + * Report Size(1) + * Report Count(3) + * Report Offset(0) + * Flags( Variable Absolute ) * * This is the mapping that we expect: * Button.0001 ---> Key.LeftBtn @@ -80,19 +100,59 @@ * GenericDesktop.X ---> Relative.X * GenericDesktop.Y ---> Relative.Y * GenericDesktop.Wheel ---> Relative.Wheel + * LED.NumLock ---> LED.NumLock + * LED.CapsLock ---> LED.CapsLock + * LED.ScrollLock ---> LED.ScrollLock * * This information can be verified by reading /sys/kernel/debug/hid/<dev>/rdesc * This file should print the same information as showed above. */ static unsigned char rdesc[] = { - 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01, - 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, - 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, - 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, - 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x38, - 0x15, 0x80, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x03, - 0x81, 0x06, 0xc0, 0xc0, + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x09, 0x01, /* USAGE (Pointer) */ + 0xa1, 0x00, /* COLLECTION (Physical) */ + 0x85, 0x01, /* REPORT_ID (1) */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x03, /* USAGE_MAXIMUM (Button 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x81, 0x01, /* INPUT (Cnst,Var,Abs) */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x09, 0x38, /* USAGE (WHEEL) */ + 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ + 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ + 0xc0, /* END_COLLECTION */ + 0xc0, /* END_COLLECTION */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, 0x02, /* REPORT_ID (2) */ + 0x05, 0x08, /* USAGE_PAGE (Led) */ + 0x19, 0x01, /* USAGE_MINIMUM (1) */ + 0x29, 0x03, /* USAGE_MAXIMUM (3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* Output (Data,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x91, 0x01, /* Output (Cnst,Var,Abs) */ + 0xc0, /* END_COLLECTION */ }; static int uhid_write(int fd, const struct uhid_event *ev) @@ -140,6 +200,27 @@ static void destroy(int fd) uhid_write(fd, &ev); } +/* This parses raw output reports sent by the kernel to the device. A normal + * uhid program shouldn't do this but instead just forward the raw report. + * However, for ducomentational purposes, we try to detect LED events here and + * print debug messages for it. */ +static void handle_output(struct uhid_event *ev) +{ + /* LED messages are adverised via OUTPUT reports; ignore the rest */ + if (ev->u.output.rtype != UHID_OUTPUT_REPORT) + return; + /* LED reports have length 2 bytes */ + if (ev->u.output.size != 2) + return; + /* first byte is report-id which is 0x02 for LEDs in our rdesc */ + if (ev->u.output.data[0] != 0x2) + return; + + /* print flags payload */ + fprintf(stderr, "LED output report received with flags %x\n", + ev->u.output.data[1]); +} + static int event(int fd) { struct uhid_event ev; @@ -174,6 +255,7 @@ static int event(int fd) break; case UHID_OUTPUT: fprintf(stderr, "UHID_OUTPUT from uhid-dev\n"); + handle_output(&ev); break; case UHID_OUTPUT_EV: fprintf(stderr, "UHID_OUTPUT_EV from uhid-dev\n"); @@ -198,18 +280,19 @@ static int send_event(int fd) memset(&ev, 0, sizeof(ev)); ev.type = UHID_INPUT; - ev.u.input.size = 4; + ev.u.input.size = 5; + ev.u.input.data[0] = 0x1; if (btn1_down) - ev.u.input.data[0] |= 0x1; + ev.u.input.data[1] |= 0x1; if (btn2_down) - ev.u.input.data[0] |= 0x2; + ev.u.input.data[1] |= 0x2; if (btn3_down) - ev.u.input.data[0] |= 0x4; + ev.u.input.data[1] |= 0x4; - ev.u.input.data[1] = abs_hor; - ev.u.input.data[2] = abs_ver; - ev.u.input.data[3] = wheel; + ev.u.input.data[2] = abs_hor; + ev.u.input.data[3] = abs_ver; + ev.u.input.data[4] = wheel; return uhid_write(fd, &ev); } |