aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-06-12 16:56:15 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-06-23 16:20:42 +0100
commitf1323504a91733f7c19754978c9c3655d92f4a42 (patch)
treecae4cf15ca5696081faeb412d7e9d9a16d414a89
parent7afbec528de3e1253e9f36b095b1e885eb1f8203 (diff)
downloadqemu-arm-f1323504a91733f7c19754978c9c3655d92f4a42.tar.gz
hw/input/goldfish_events.c: Implement goldfish events device
Implement the goldfish 'events' device which provides a variety of input events including simulated touchscreen and hard buttons. This is a forward port and revamp of the goldfish/events_device from the classic Android emulator. Some features from the classic emulator are not supported: * multitouch * full keyboard Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/input/Makefile.objs1
-rw-r--r--hw/input/goldfish_events.c757
-rw-r--r--include/hw/input/linux_keycodes.h510
3 files changed, 1268 insertions, 0 deletions
diff --git a/hw/input/Makefile.objs b/hw/input/Makefile.objs
index e8c80b9de2..c188a74b04 100644
--- a/hw/input/Makefile.objs
+++ b/hw/input/Makefile.objs
@@ -11,3 +11,4 @@ common-obj-$(CONFIG_VMMOUSE) += vmmouse.o
obj-$(CONFIG_MILKYMIST) += milkymist-softusb.o
obj-$(CONFIG_PXA2XX) += pxa2xx_keypad.o
obj-$(CONFIG_TSC210X) += tsc210x.o
+obj-$(CONFIG_GOLDFISH) += goldfish_events.o
diff --git a/hw/input/goldfish_events.c b/hw/input/goldfish_events.c
new file mode 100644
index 0000000000..8a6f5aa7ff
--- /dev/null
+++ b/hw/input/goldfish_events.c
@@ -0,0 +1,757 @@
+/*
+ * Goldfish 'events' device model
+ *
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ * Copyright (c) 2014 Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "hw/sysbus.h"
+#include "ui/input.h"
+#include "ui/console.h"
+#include "hw/input/linux_keycodes.h"
+
+/* Multitouch specific code is defined out via EVDEV_MULTITOUCH currently,
+ * because upstream has no multitouch related APIs.
+ */
+/* #define EVDEV_MULTITOUCH */
+
+#define MAX_EVENTS (256 * 4)
+
+/* Event types (as per Linux input event layer) */
+#define EV_SYN 0x00
+#define EV_KEY 0x01
+#define EV_REL 0x02
+#define EV_ABS 0x03
+#define EV_MSC 0x04
+#define EV_SW 0x05
+#define EV_LED 0x11
+#define EV_SND 0x12
+#define EV_REP 0x14
+#define EV_FF 0x15
+#define EV_PWR 0x16
+#define EV_FF_STATUS 0x17
+#define EV_MAX 0x1f
+
+/* Absolute axes */
+#define ABS_X 0x00
+#define ABS_Y 0x01
+#define ABS_Z 0x02
+#define ABS_MT_SLOT 0x2f /* MT slot being modified */
+#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
+#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
+#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
+#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
+#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
+#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
+#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
+#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
+#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
+#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
+#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
+#define ABS_MT_DISTANCE 0x3b /* Contact hover distance */
+#define ABS_MAX 0x3f
+
+/* Relative axes */
+#define REL_X 0x00
+#define REL_Y 0x01
+
+#define BTN_TOUCH 0x14a
+#define BTN_MOUSE 0x110
+
+
+enum {
+ REG_READ = 0x00,
+ REG_SET_PAGE = 0x00,
+ REG_LEN = 0x04,
+ REG_DATA = 0x08,
+
+ PAGE_NAME = 0x00000,
+ PAGE_EVBITS = 0x10000,
+ PAGE_ABSDATA = 0x20000 | EV_ABS,
+};
+
+/* These corresponds to the state of the driver.
+ * Unfortunately, we have to buffer events coming
+ * from the UI, since the kernel driver is not
+ * capable of receiving them until XXXXXX
+ */
+enum {
+ STATE_INIT = 0, /* The device is initialized */
+ STATE_BUFFERED, /* Events have been buffered, but no IRQ raised yet */
+ STATE_LIVE /* Events can be sent directly to the kernel */
+};
+
+/* NOTE: The ev_bits arrays are used to indicate to the kernel
+ * which events can be sent by the emulated hardware.
+ */
+
+#define TYPE_GOLDFISHEVDEV "goldfish-events"
+#define GOLDFISHEVDEV(obj) \
+ OBJECT_CHECK(GoldfishEvDevState, (obj), TYPE_GOLDFISHEVDEV)
+
+typedef struct GoldfishEvDevState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ /* Device properties (TODO: actually make these props) */
+ bool have_dpad;
+ bool have_trackball;
+ bool have_camera;
+ bool have_keyboard;
+ bool have_keyboard_lid;
+ bool have_touch;
+ bool have_multitouch;
+
+ /* Actual device state */
+ int32_t page;
+ uint32_t events[MAX_EVENTS];
+ uint32_t first;
+ uint32_t last;
+ uint32_t state;
+
+ uint32_t modifier_state;
+
+ /* All data below here is set up at realize and not modified thereafter */
+
+ const char *name;
+
+ struct {
+ size_t len;
+ uint8_t *bits;
+ } ev_bits[EV_MAX + 1];
+
+ int32_t *abs_info;
+ size_t abs_info_count;
+} GoldfishEvDevState;
+
+/* Bitfield meanings for modifier_state. */
+#define MODSTATE_SHIFT (1 << 0)
+#define MODSTATE_CTRL (1 << 1)
+#define MODSTATE_ALT (1 << 2)
+#define MODSTATE_MASK (MODSTATE_SHIFT | MODSTATE_CTRL | MODSTATE_ALT)
+
+/* An entry in the array of ABS_XXX values */
+typedef struct ABSEntry {
+ /* Minimum ABS_XXX value. */
+ uint32_t min;
+ /* Maximum ABS_XXX value. */
+ uint32_t max;
+ /* 'fuzz;, and 'flat' ABS_XXX values are always zero here. */
+ uint32_t fuzz;
+ uint32_t flat;
+} ABSEntry;
+
+static const VMStateDescription vmstate_gf_evdev = {
+ .name = "goldfish-events",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(page, GoldfishEvDevState),
+ VMSTATE_UINT32_ARRAY(events, GoldfishEvDevState, MAX_EVENTS),
+ VMSTATE_UINT32(first, GoldfishEvDevState),
+ VMSTATE_UINT32(last, GoldfishEvDevState),
+ VMSTATE_UINT32(state, GoldfishEvDevState),
+ VMSTATE_UINT32(modifier_state, GoldfishEvDevState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void enqueue_event(GoldfishEvDevState *s,
+ unsigned int type, unsigned int code, int value)
+{
+ int enqueued = s->last - s->first;
+
+ if (enqueued < 0) {
+ enqueued += MAX_EVENTS;
+ }
+
+ if (enqueued + 3 > MAX_EVENTS) {
+ fprintf(stderr, "##KBD: Full queue, lose event\n");
+ return;
+ }
+
+ if (s->first == s->last) {
+ if (s->state == STATE_LIVE) {
+ qemu_irq_raise(s->irq);
+ } else {
+ s->state = STATE_BUFFERED;
+ }
+ }
+
+ s->events[s->last] = type;
+ s->last = (s->last + 1) & (MAX_EVENTS-1);
+ s->events[s->last] = code;
+ s->last = (s->last + 1) & (MAX_EVENTS-1);
+ s->events[s->last] = value;
+ s->last = (s->last + 1) & (MAX_EVENTS-1);
+}
+
+static unsigned dequeue_event(GoldfishEvDevState *s)
+{
+ unsigned n;
+
+ if (s->first == s->last) {
+ return 0;
+ }
+
+ n = s->events[s->first];
+
+ s->first = (s->first + 1) & (MAX_EVENTS - 1);
+
+ if (s->first == s->last) {
+ qemu_irq_lower(s->irq);
+ }
+#ifdef TARGET_I386
+ /*
+ * Adding the logic to handle edge-triggered interrupts for x86
+ * because the exisiting goldfish events device basically provides
+ * level-trigger interrupts only.
+ *
+ * Logic: When an event (including the type/code/value) is fetched
+ * by the driver, if there is still another event in the event
+ * queue, the goldfish event device will re-assert the IRQ so that
+ * the driver can be notified to fetch the event again.
+ */
+ else if (((s->first + 2) & (MAX_EVENTS - 1)) < s->last ||
+ (s->first & (MAX_EVENTS - 1)) > s->last) {
+ /* if there still is an event */
+ qemu_irq_lower(s->irq);
+ qemu_irq_raise(s->irq);
+ }
+#endif
+ return n;
+}
+
+static int get_page_len(GoldfishEvDevState *s)
+{
+ int page = s->page;
+ if (page == PAGE_NAME) {
+ const char *name = s->name;
+ return strlen(name);
+ }
+ if (page >= PAGE_EVBITS && page <= PAGE_EVBITS + EV_MAX) {
+ return s->ev_bits[page - PAGE_EVBITS].len;
+ }
+ if (page == PAGE_ABSDATA) {
+ return s->abs_info_count * sizeof(s->abs_info[0]);
+ }
+ return 0;
+}
+
+static int get_page_data(GoldfishEvDevState *s, int offset)
+{
+ int page_len = get_page_len(s);
+ int page = s->page;
+ if (offset > page_len) {
+ return 0;
+ }
+ if (page == PAGE_NAME) {
+ const char *name = s->name;
+ return name[offset];
+ }
+ if (page >= PAGE_EVBITS && page <= PAGE_EVBITS + EV_MAX) {
+ return s->ev_bits[page - PAGE_EVBITS].bits[offset];
+ }
+ if (page == PAGE_ABSDATA) {
+ return s->abs_info[offset / sizeof(s->abs_info[0])];
+ }
+ return 0;
+}
+
+static uint64_t events_read(void *opaque, hwaddr offset, unsigned size)
+{
+ GoldfishEvDevState *s = (GoldfishEvDevState *)opaque;
+
+ /* This gross hack below is used to ensure that we
+ * only raise the IRQ when the kernel driver is
+ * properly ready! If done before this, the driver
+ * becomes confused and ignores all input events
+ * as soon as one was buffered!
+ */
+ if (offset == REG_LEN && s->page == PAGE_ABSDATA) {
+ if (s->state == STATE_BUFFERED) {
+ qemu_irq_raise(s->irq);
+ }
+ s->state = STATE_LIVE;
+ }
+
+ switch (offset) {
+ case REG_READ:
+ return dequeue_event(s);
+ case REG_LEN:
+ return get_page_len(s);
+ default:
+ if (offset >= REG_DATA) {
+ return get_page_data(s, offset - REG_DATA);
+ }
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "goldfish events device read: bad offset %x\n",
+ (int)offset);
+ return 0;
+ }
+}
+
+static void events_write(void *opaque, hwaddr offset,
+ uint64_t val, unsigned size)
+{
+ GoldfishEvDevState *s = (GoldfishEvDevState *)opaque;
+ switch (offset) {
+ case REG_SET_PAGE:
+ s->page = val;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "goldfish events device write: bad offset %x\n",
+ (int)offset);
+ break;
+ }
+}
+
+static const MemoryRegionOps gf_evdev_ops = {
+ .read = events_read,
+ .write = events_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void gf_evdev_put_mouse(void *opaque,
+ int dx, int dy, int dz, int buttons_state)
+{
+ GoldfishEvDevState *s = (GoldfishEvDevState *)opaque;
+
+ /* Note that unlike the "classic" Android emulator, we don't
+ * have the "dz == 0 for touchscreen, == 1 for trackball"
+ * distinction.
+ */
+#ifdef EVDEV_MULTITOUCH
+ if (s->have_multitouch) {
+ /* Convert mouse event into multi-touch event */
+ multitouch_update_pointer(MTES_MOUSE, 0, dx, dy,
+ (buttons_state & 1) ? 0x81 : 0);
+ return;
+ }
+#endif
+ if (s->have_touch) {
+ enqueue_event(s, EV_ABS, ABS_X, dx);
+ enqueue_event(s, EV_ABS, ABS_Y, dy);
+ enqueue_event(s, EV_ABS, ABS_Z, dz);
+ enqueue_event(s, EV_KEY, BTN_TOUCH, buttons_state & 1);
+ enqueue_event(s, EV_SYN, 0, 0);
+ return;
+ }
+ if (s->have_trackball) {
+ enqueue_event(s, EV_REL, REL_X, dx);
+ enqueue_event(s, EV_REL, REL_Y, dy);
+ enqueue_event(s, EV_SYN, 0, 0);
+ return;
+ }
+}
+
+/* set bits [bitl..bith] in the ev_bits[type] array
+ */
+static void
+events_set_bits(GoldfishEvDevState *s, int type, int bitl, int bith)
+{
+ uint8_t *bits;
+ uint8_t maskl, maskh;
+ int il, ih;
+ il = bitl / 8;
+ ih = bith / 8;
+ if (ih >= s->ev_bits[type].len) {
+ bits = g_malloc0(ih + 1);
+ if (bits == NULL) {
+ return;
+ }
+ memcpy(bits, s->ev_bits[type].bits, s->ev_bits[type].len);
+ g_free(s->ev_bits[type].bits);
+ s->ev_bits[type].bits = bits;
+ s->ev_bits[type].len = ih + 1;
+ } else {
+ bits = s->ev_bits[type].bits;
+ }
+ maskl = 0xffU << (bitl & 7);
+ maskh = 0xffU >> (7 - (bith & 7));
+ if (il >= ih) {
+ maskh &= maskl;
+ } else {
+ bits[il] |= maskl;
+ while (++il < ih) {
+ bits[il] = 0xff;
+ }
+ }
+ bits[ih] |= maskh;
+}
+
+static void
+events_set_bit(GoldfishEvDevState *s, int type, int bit)
+{
+ events_set_bits(s, type, bit, bit);
+}
+
+static void
+events_clr_bit(GoldfishEvDevState *s, int type, int bit)
+{
+ int ii = bit / 8;
+ if (ii < s->ev_bits[type].len) {
+ uint8_t *bits = s->ev_bits[type].bits;
+ uint8_t mask = 0x01U << (bit & 7);
+ bits[ii] &= ~mask;
+ }
+}
+
+/* Keycode mappings to match the classic Android emulator as documented in
+ * http://developer.android.com/tools/help/emulator.html
+ */
+static const uint16_t hardbutton_map[Q_KEY_CODE_MAX] = {
+ [Q_KEY_CODE_HOME] = LINUX_KEY_HOME,
+ [Q_KEY_CODE_F2] = LINUX_KEY_SOFT1, /* Android menu key */
+ [Q_KEY_CODE_PGUP] = LINUX_KEY_SOFT1,
+ [Q_KEY_CODE_PGDN] = LINUX_KEY_SOFT2,
+ [Q_KEY_CODE_ESC] = LINUX_KEY_BACK,
+ [Q_KEY_CODE_F3] = LINUX_KEY_SEND, /* dial */
+ [Q_KEY_CODE_F4] = LINUX_KEY_END, /* end call */
+ [Q_KEY_CODE_F5] = LINUX_KEY_SEARCH,
+ [Q_KEY_CODE_F7] = LINUX_KEY_POWER,
+ [Q_KEY_CODE_KP_ADD] = LINUX_KEY_VOLUMEUP,
+ [Q_KEY_CODE_KP_SUBTRACT] = LINUX_KEY_VOLUMEDOWN,
+};
+
+static const uint16_t hardbutton_shift_map[Q_KEY_CODE_MAX] = {
+ [Q_KEY_CODE_F2] = LINUX_KEY_SOFT2,
+};
+
+static const uint16_t hardbutton_control_map[Q_KEY_CODE_MAX] = {
+ [Q_KEY_CODE_F5] = LINUX_KEY_VOLUMEUP,
+ [Q_KEY_CODE_F6] = LINUX_KEY_VOLUMEDOWN,
+ /* ctrl-kp5, ctrl-f3 -> LINUX_KEY_CAMERA (if have_camera) */
+};
+
+static const int dpad_map[Q_KEY_CODE_MAX] = {
+ [Q_KEY_CODE_KP_4] = LINUX_KEY_LEFT,
+ [Q_KEY_CODE_KP_6] = LINUX_KEY_RIGHT,
+ [Q_KEY_CODE_KP_8] = LINUX_KEY_UP,
+ [Q_KEY_CODE_KP_2] = LINUX_KEY_DOWN,
+ [Q_KEY_CODE_KP_5] = LINUX_KEY_CENTER,
+};
+
+static void gf_evdev_handle_keyevent(DeviceState *dev, QemuConsole *src,
+ InputEvent *evt)
+{
+ /* Handle a key event. Minimal implementation which just handles
+ * the required hardware buttons and the dpad.
+ * This should be extended to also honour have_keyboard, and
+ * possibly also the control keys which affect the emulator itself.
+ */
+
+ GoldfishEvDevState *s = GOLDFISHEVDEV(dev);
+ int qcode;
+ int lkey = 0;
+ int mod;
+
+ assert(evt->kind == INPUT_EVENT_KIND_KEY);
+
+ qcode = qemu_input_key_value_to_qcode(evt->key->key);
+
+ /* Keep our modifier state up to date */
+ switch (qcode) {
+ case Q_KEY_CODE_SHIFT:
+ case Q_KEY_CODE_SHIFT_R:
+ mod = MODSTATE_SHIFT;
+ break;
+ case Q_KEY_CODE_ALT:
+ case Q_KEY_CODE_ALT_R:
+ mod = MODSTATE_ALT;
+ break;
+ case Q_KEY_CODE_CTRL:
+ case Q_KEY_CODE_CTRL_R:
+ mod = MODSTATE_CTRL;
+ break;
+ default:
+ mod = 0;
+ break;
+ }
+
+ if (mod) {
+ if (evt->key->down) {
+ s->modifier_state |= mod;
+ } else {
+ s->modifier_state &= ~mod;
+ }
+ }
+
+ if (s->modifier_state & MODSTATE_ALT) {
+ /* No alt-keys defined currently */
+ } else if (s->modifier_state & MODSTATE_CTRL) {
+ lkey = hardbutton_control_map[qcode];
+ } else if (s->modifier_state & MODSTATE_SHIFT) {
+ lkey = hardbutton_shift_map[qcode];
+ } else {
+ lkey = hardbutton_map[qcode];
+ }
+
+ if (!lkey && s->have_dpad && s->modifier_state == 0) {
+ lkey = dpad_map[qcode];
+ }
+
+ if (lkey) {
+ enqueue_event(s, EV_KEY, lkey, evt->key->down);
+ }
+}
+
+static QemuInputHandler gf_evdev_key_input_handler = {
+ .name = "goldfish event device key handler",
+ .mask = INPUT_EVENT_MASK_KEY,
+ .event = gf_evdev_handle_keyevent,
+};
+
+static void gf_evdev_init(Object *obj)
+{
+ GoldfishEvDevState *s = GOLDFISHEVDEV(obj);
+ DeviceState *dev = DEVICE(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+ memory_region_init_io(&s->iomem, obj, &gf_evdev_ops, s,
+ "goldfish-events", 0x1000);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+
+ qemu_input_handler_register(dev, &gf_evdev_key_input_handler);
+ qemu_add_mouse_event_handler(gf_evdev_put_mouse, s, 1, "goldfish-events");
+}
+
+static void gf_evdev_realize(DeviceState *dev, Error **errp)
+{
+ GoldfishEvDevState *s = GOLDFISHEVDEV(dev);
+
+ /* now set the events capability bits depending on hardware configuration */
+ /* apparently, the EV_SYN array is used to indicate which other
+ * event classes to consider.
+ */
+
+ /* XXX PMM properties ? */
+ s->name = "qwerty2";
+
+ if (s->have_multitouch) {
+ s->have_touch = true;
+ }
+
+ /* configure EV_KEY array
+ *
+ * All Android devices must have the following keys:
+ * KEY_HOME, KEY_BACK, KEY_SEND (Call), KEY_END (EndCall),
+ * KEY_SOFT1 (Menu), VOLUME_UP, VOLUME_DOWN
+ *
+ * Note that previous models also had a KEY_SOFT2,
+ * and a KEY_POWER which we still support here.
+ *
+ * Newer models have a KEY_SEARCH key, which we always
+ * enable here.
+ *
+ * A Dpad will send: KEY_DOWN / UP / LEFT / RIGHT / CENTER
+ *
+ * The KEY_CAMERA button isn't very useful if there is no camera.
+ *
+ * BTN_MOUSE is sent when the trackball is pressed
+ * BTN_TOUCH is sent when the touchscreen is pressed
+ */
+ events_set_bit(s, EV_SYN, EV_KEY);
+
+ events_set_bit(s, EV_KEY, LINUX_KEY_HOME);
+ events_set_bit(s, EV_KEY, LINUX_KEY_BACK);
+ events_set_bit(s, EV_KEY, LINUX_KEY_SEND);
+ events_set_bit(s, EV_KEY, LINUX_KEY_END);
+ events_set_bit(s, EV_KEY, LINUX_KEY_SOFT1);
+ events_set_bit(s, EV_KEY, LINUX_KEY_VOLUMEUP);
+ events_set_bit(s, EV_KEY, LINUX_KEY_VOLUMEDOWN);
+ events_set_bit(s, EV_KEY, LINUX_KEY_SOFT2);
+ events_set_bit(s, EV_KEY, LINUX_KEY_POWER);
+ events_set_bit(s, EV_KEY, LINUX_KEY_SEARCH);
+
+ if (s->have_dpad) {
+ events_set_bit(s, EV_KEY, LINUX_KEY_DOWN);
+ events_set_bit(s, EV_KEY, LINUX_KEY_UP);
+ events_set_bit(s, EV_KEY, LINUX_KEY_LEFT);
+ events_set_bit(s, EV_KEY, LINUX_KEY_RIGHT);
+ events_set_bit(s, EV_KEY, LINUX_KEY_CENTER);
+ }
+
+ if (s->have_trackball) {
+ events_set_bit(s, EV_KEY, BTN_MOUSE);
+ }
+ if (s->have_touch) {
+ events_set_bit(s, EV_KEY, BTN_TOUCH);
+ }
+
+ if (s->have_camera) {
+ /* Camera emulation is enabled. */
+ events_set_bit(s, EV_KEY, LINUX_KEY_CAMERA);
+ }
+
+ if (s->have_keyboard) {
+ /* since we want to implement Unicode reverse-mapping
+ * allow any kind of key, even those not available on
+ * the skin.
+ *
+ * the previous code did set the [1..0x1ff] range, but
+ * we don't want to enable certain bits in the middle
+ * of the range that are registered for mouse/trackball/joystick
+ * events.
+ *
+ * see "linux_keycodes.h" for the list of events codes.
+ */
+ events_set_bits(s, EV_KEY, 1, 0xff);
+ events_set_bits(s, EV_KEY, 0x160, 0x1ff);
+
+ /* If there is a keyboard, but no DPad, we need to clear the
+ * corresponding bits. Doing this is simpler than trying to exclude
+ * the DPad values from the ranges above.
+ */
+ if (!s->have_dpad) {
+ events_clr_bit(s, EV_KEY, LINUX_KEY_DOWN);
+ events_clr_bit(s, EV_KEY, LINUX_KEY_UP);
+ events_clr_bit(s, EV_KEY, LINUX_KEY_LEFT);
+ events_clr_bit(s, EV_KEY, LINUX_KEY_RIGHT);
+ events_clr_bit(s, EV_KEY, LINUX_KEY_CENTER);
+ }
+ }
+
+ /* configure EV_REL array
+ *
+ * EV_REL events are sent when the trackball is moved
+ */
+ if (s->have_trackball) {
+ events_set_bit(s, EV_SYN, EV_REL);
+ events_set_bits(s, EV_REL, REL_X, REL_Y);
+ }
+
+ /* configure EV_ABS array.
+ *
+ * EV_ABS events are sent when the touchscreen is pressed
+ */
+ if (s->have_touch) {
+ ABSEntry *abs_values;
+
+ events_set_bit(s, EV_SYN, EV_ABS);
+ events_set_bits(s, EV_ABS, ABS_X, ABS_Z);
+ /* Allocate the absinfo to report the min/max bounds for each
+ * absolute dimension. The array must contain 3, or ABS_MAX tuples
+ * of (min,max,fuzz,flat) 32-bit values.
+ *
+ * min and max are the bounds
+ * fuzz corresponds to the device's fuziness, we set it to 0
+ * flat corresponds to the flat position for JOEYDEV devices,
+ * we also set it to 0.
+ *
+ * There is no need to save/restore this array in a snapshot
+ * since the values only depend on the hardware configuration.
+ */
+ s->abs_info_count = s->have_multitouch ? ABS_MAX * 4 : 3 * 4;
+ s->abs_info = g_new0(int32_t, s->abs_info_count);
+ abs_values = (ABSEntry *)s->abs_info;
+
+ /* QEMU provides absolute coordinates in the [0,0x7fff] range
+ * regardless of the display resolution.
+ */
+ abs_values[ABS_X].max = 0x7fff;
+ abs_values[ABS_Y].max = 0x7fff;
+ abs_values[ABS_Z].max = 1;
+
+#ifdef EVDEV_MULTITOUCH
+ if (s->have_multitouch) {
+ /*
+ * Setup multitouch.
+ */
+ events_set_bit(s, EV_ABS, ABS_MT_SLOT);
+ events_set_bit(s, EV_ABS, ABS_MT_POSITION_X);
+ events_set_bit(s, EV_ABS, ABS_MT_POSITION_Y);
+ events_set_bit(s, EV_ABS, ABS_MT_TRACKING_ID);
+ events_set_bit(s, EV_ABS, ABS_MT_TOUCH_MAJOR);
+ events_set_bit(s, EV_ABS, ABS_MT_PRESSURE);
+
+ abs_values[ABS_MT_SLOT].max = multitouch_get_max_slot();
+ abs_values[ABS_MT_TRACKING_ID].max
+ = abs_values[ABS_MT_SLOT].max + 1;
+ abs_values[ABS_MT_POSITION_X].max = abs_values[ABS_X].max;
+ abs_values[ABS_MT_POSITION_Y].max = abs_values[ABS_Y].max;
+ /* TODO : make next 2 less random */
+ abs_values[ABS_MT_TOUCH_MAJOR].max = 0x7fffffff;
+ abs_values[ABS_MT_PRESSURE].max = 0x100;
+ }
+#endif
+ }
+
+ /* configure EV_SW array
+ *
+ * EV_SW events are sent to indicate that the keyboard lid
+ * was closed or opened (done when we switch layouts through
+ * KP-7 or KP-9).
+ *
+ * We only support this when hw.keyboard.lid is true.
+ */
+ if (s->have_keyboard && s->have_keyboard_lid) {
+ events_set_bit(s, EV_SYN, EV_SW);
+ events_set_bit(s, EV_SW, 0);
+ }
+}
+
+static void gf_evdev_reset(DeviceState *dev)
+{
+ GoldfishEvDevState *s = GOLDFISHEVDEV(dev);
+
+ s->state = STATE_INIT;
+ s->first = 0;
+ s->last = 0;
+ s->state = 0;
+}
+
+static Property gf_evdev_props[] = {
+ DEFINE_PROP_BOOL("have-dpad", GoldfishEvDevState, have_dpad, false),
+ DEFINE_PROP_BOOL("have-trackball", GoldfishEvDevState,
+ have_trackball, false),
+ DEFINE_PROP_BOOL("have-camera", GoldfishEvDevState, have_camera, false),
+ DEFINE_PROP_BOOL("have-keyboard", GoldfishEvDevState, have_keyboard, false),
+ DEFINE_PROP_BOOL("have-lidswitch", GoldfishEvDevState,
+ have_keyboard_lid, false),
+ DEFINE_PROP_BOOL("have-touch", GoldfishEvDevState,
+ have_touch, true),
+ DEFINE_PROP_BOOL("have-multitouch", GoldfishEvDevState,
+ have_multitouch, false),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void gf_evdev_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = gf_evdev_realize;
+ dc->reset = gf_evdev_reset;
+ dc->props = gf_evdev_props;
+ dc->vmsd = &vmstate_gf_evdev;
+}
+
+static const TypeInfo gf_evdev_info = {
+ .name = TYPE_GOLDFISHEVDEV,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(GoldfishEvDevState),
+ .instance_init = gf_evdev_init,
+ .class_init = gf_evdev_class_init,
+};
+
+static void gf_evdev_register_types(void)
+{
+ type_register_static(&gf_evdev_info);
+}
+
+type_init(gf_evdev_register_types)
diff --git a/include/hw/input/linux_keycodes.h b/include/hw/input/linux_keycodes.h
new file mode 100644
index 0000000000..d0bbcc6e4b
--- /dev/null
+++ b/include/hw/input/linux_keycodes.h
@@ -0,0 +1,510 @@
+#ifndef HW_INPUT_LINUX_KEYCODES_H
+#define HW_INPUT_LINUX_KEYCODES_H
+
+/*
+ * Copyright (c) 1999-2002 Vojtech Pavlik
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * Adjusted for portable use in QEMU by prepending LINUX_ to all names.
+ */
+
+/*
+ * Keys and buttons
+ */
+
+#define LINUX_KEY_RESERVED 0
+#define LINUX_KEY_ESC 1
+#define LINUX_KEY_1 2
+#define LINUX_KEY_2 3
+#define LINUX_KEY_3 4
+#define LINUX_KEY_4 5
+#define LINUX_KEY_5 6
+#define LINUX_KEY_6 7
+#define LINUX_KEY_7 8
+#define LINUX_KEY_8 9
+#define LINUX_KEY_9 10
+#define LINUX_KEY_0 11
+#define LINUX_KEY_MINUS 12
+#define LINUX_KEY_EQUAL 13
+#define LINUX_KEY_BACKSPACE 14
+#define LINUX_KEY_TAB 15
+#define LINUX_KEY_Q 16
+#define LINUX_KEY_W 17
+#define LINUX_KEY_E 18
+#define LINUX_KEY_R 19
+#define LINUX_KEY_T 20
+#define LINUX_KEY_Y 21
+#define LINUX_KEY_U 22
+#define LINUX_KEY_I 23
+#define LINUX_KEY_O 24
+#define LINUX_KEY_P 25
+#define LINUX_KEY_LEFTBRACE 26
+#define LINUX_KEY_RIGHTBRACE 27
+#define LINUX_KEY_ENTER 28
+#define LINUX_KEY_LEFTCTRL 29
+#define LINUX_KEY_A 30
+#define LINUX_KEY_S 31
+#define LINUX_KEY_D 32
+#define LINUX_KEY_F 33
+#define LINUX_KEY_G 34
+#define LINUX_KEY_H 35
+#define LINUX_KEY_J 36
+#define LINUX_KEY_K 37
+#define LINUX_KEY_L 38
+#define LINUX_KEY_SEMICOLON 39
+#define LINUX_KEY_APOSTROPHE 40
+#define LINUX_KEY_GRAVE 41
+#define LINUX_KEY_LEFTSHIFT 42
+#define LINUX_KEY_BACKSLASH 43
+#define LINUX_KEY_Z 44
+#define LINUX_KEY_X 45
+#define LINUX_KEY_C 46
+#define LINUX_KEY_V 47
+#define LINUX_KEY_B 48
+#define LINUX_KEY_N 49
+#define LINUX_KEY_M 50
+#define LINUX_KEY_COMMA 51
+#define LINUX_KEY_DOT 52
+#define LINUX_KEY_SLASH 53
+#define LINUX_KEY_RIGHTSHIFT 54
+#define LINUX_KEY_KPASTERISK 55
+#define LINUX_KEY_LEFTALT 56
+#define LINUX_KEY_SPACE 57
+#define LINUX_KEY_CAPSLOCK 58
+#define LINUX_KEY_F1 59
+#define LINUX_KEY_F2 60
+#define LINUX_KEY_F3 61
+#define LINUX_KEY_F4 62
+#define LINUX_KEY_F5 63
+#define LINUX_KEY_F6 64
+#define LINUX_KEY_F7 65
+#define LINUX_KEY_F8 66
+#define LINUX_KEY_F9 67
+#define LINUX_KEY_F10 68
+#define LINUX_KEY_NUMLOCK 69
+#define LINUX_KEY_SCROLLLOCK 70
+#define LINUX_KEY_KP7 71
+#define LINUX_KEY_KP8 72
+#define LINUX_KEY_KP9 73
+#define LINUX_KEY_KPMINUS 74
+#define LINUX_KEY_KP4 75
+#define LINUX_KEY_KP5 76
+#define LINUX_KEY_KP6 77
+#define LINUX_KEY_KPPLUS 78
+#define LINUX_KEY_KP1 79
+#define LINUX_KEY_KP2 80
+#define LINUX_KEY_KP3 81
+#define LINUX_KEY_KP0 82
+#define LINUX_KEY_KPDOT 83
+
+#define LINUX_KEY_ZENKAKUHANKAKU 85
+#define LINUX_KEY_102ND 86
+#define LINUX_KEY_F11 87
+#define LINUX_KEY_F12 88
+#define LINUX_KEY_RO 89
+#define LINUX_KEY_KATAKANA 90
+#define LINUX_KEY_HIRAGANA 91
+#define LINUX_KEY_HENKAN 92
+#define LINUX_KEY_KATAKANAHIRAGANA 93
+#define LINUX_KEY_MUHENKAN 94
+#define LINUX_KEY_KPJPCOMMA 95
+#define LINUX_KEY_KPENTER 96
+#define LINUX_KEY_RIGHTCTRL 97
+#define LINUX_KEY_KPSLASH 98
+#define LINUX_KEY_SYSRQ 99
+#define LINUX_KEY_RIGHTALT 100
+#define LINUX_KEY_LINEFEED 101
+#define LINUX_KEY_HOME 102
+#define LINUX_KEY_UP 103
+#define LINUX_KEY_PAGEUP 104
+#define LINUX_KEY_LEFT 105
+#define LINUX_KEY_RIGHT 106
+#define LINUX_KEY_END 107
+#define LINUX_KEY_DOWN 108
+#define LINUX_KEY_PAGEDOWN 109
+#define LINUX_KEY_INSERT 110
+#define LINUX_KEY_DELETE 111
+#define LINUX_KEY_MACRO 112
+#define LINUX_KEY_MUTE 113
+#define LINUX_KEY_VOLUMEDOWN 114
+#define LINUX_KEY_VOLUMEUP 115
+#define LINUX_KEY_POWER 116
+#define LINUX_KEY_KPEQUAL 117
+#define LINUX_KEY_KPPLUSMINUS 118
+#define LINUX_KEY_PAUSE 119
+
+#define LINUX_KEY_KPCOMMA 121
+#define LINUX_KEY_HANGEUL 122
+#define LINUX_KEY_HANGUEL KEY_HANGEUL
+#define LINUX_KEY_HANJA 123
+#define LINUX_KEY_YEN 124
+#define LINUX_KEY_LEFTMETA 125
+#define LINUX_KEY_RIGHTMETA 126
+#define LINUX_KEY_COMPOSE 127
+
+#define LINUX_KEY_STOP 128
+#define LINUX_KEY_AGAIN 129
+#define LINUX_KEY_PROPS 130
+#define LINUX_KEY_UNDO 131
+#define LINUX_KEY_FRONT 132
+#define LINUX_KEY_COPY 133
+#define LINUX_KEY_OPEN 134
+#define LINUX_KEY_PASTE 135
+#define LINUX_KEY_FIND 136
+#define LINUX_KEY_CUT 137
+#define LINUX_KEY_HELP 138
+#define LINUX_KEY_MENU 139
+#define LINUX_KEY_CALC 140
+#define LINUX_KEY_SETUP 141
+#define LINUX_KEY_SLEEP 142
+#define LINUX_KEY_WAKEUP 143
+#define LINUX_KEY_FILE 144
+#define LINUX_KEY_SENDFILE 145
+#define LINUX_KEY_DELETEFILE 146
+#define LINUX_KEY_XFER 147
+#define LINUX_KEY_PROG1 148
+#define LINUX_KEY_PROG2 149
+#define LINUX_KEY_WWW 150
+#define LINUX_KEY_MSDOS 151
+#define LINUX_KEY_COFFEE 152
+#define LINUX_KEY_DIRECTION 153
+#define LINUX_KEY_CYCLEWINDOWS 154
+#define LINUX_KEY_MAIL 155
+#define LINUX_KEY_BOOKMARKS 156
+#define LINUX_KEY_COMPUTER 157
+#define LINUX_KEY_BACK 158
+#define LINUX_KEY_FORWARD 159
+#define LINUX_KEY_CLOSECD 160
+#define LINUX_KEY_EJECTCD 161
+#define LINUX_KEY_EJECTCLOSECD 162
+#define LINUX_KEY_NEXTSONG 163
+#define LINUX_KEY_PLAYPAUSE 164
+#define LINUX_KEY_PREVIOUSSONG 165
+#define LINUX_KEY_STOPCD 166
+#define LINUX_KEY_RECORD 167
+#define LINUX_KEY_REWIND 168
+#define LINUX_KEY_PHONE 169
+#define LINUX_KEY_ISO 170
+#define LINUX_KEY_CONFIG 171
+#define LINUX_KEY_HOMEPAGE 172
+#define LINUX_KEY_REFRESH 173
+#define LINUX_KEY_EXIT 174
+#define LINUX_KEY_MOVE 175
+#define LINUX_KEY_EDIT 176
+#define LINUX_KEY_SCROLLUP 177
+#define LINUX_KEY_SCROLLDOWN 178
+#define LINUX_KEY_KPLEFTPAREN 179
+#define LINUX_KEY_KPRIGHTPAREN 180
+#define LINUX_KEY_NEW 181
+#define LINUX_KEY_REDO 182
+
+#define LINUX_KEY_F13 183
+#define LINUX_KEY_F14 184
+#define LINUX_KEY_F15 185
+#define LINUX_KEY_F16 186
+#define LINUX_KEY_F17 187
+#define LINUX_KEY_F18 188
+#define LINUX_KEY_F19 189
+#define LINUX_KEY_F20 190
+#define LINUX_KEY_F21 191
+#define LINUX_KEY_F22 192
+#define LINUX_KEY_F23 193
+#define LINUX_KEY_F24 194
+
+#define LINUX_KEY_PLAYCD 200
+#define LINUX_KEY_PAUSECD 201
+#define LINUX_KEY_PROG3 202
+#define LINUX_KEY_PROG4 203
+#define LINUX_KEY_SUSPEND 205
+#define LINUX_KEY_CLOSE 206
+#define LINUX_KEY_PLAY 207
+#define LINUX_KEY_FASTFORWARD 208
+#define LINUX_KEY_BASSBOOST 209
+#define LINUX_KEY_PRINT 210
+#define LINUX_KEY_HP 211
+#define LINUX_KEY_CAMERA 212
+#define LINUX_KEY_SOUND 213
+#define LINUX_KEY_QUESTION 214
+#define LINUX_KEY_EMAIL 215
+#define LINUX_KEY_CHAT 216
+#define LINUX_KEY_SEARCH 217
+#define LINUX_KEY_CONNECT 218
+#define LINUX_KEY_FINANCE 219
+#define LINUX_KEY_SPORT 220
+#define LINUX_KEY_SHOP 221
+#define LINUX_KEY_ALTERASE 222
+#define LINUX_KEY_CANCEL 223
+#define LINUX_KEY_BRIGHTNESSDOWN 224
+#define LINUX_KEY_BRIGHTNESSUP 225
+#define LINUX_KEY_MEDIA 226
+
+
+/*Zeus: these keys are defined for OMAP730 Perseus2*/
+#define LINUX_KEY_STAR 227
+#define LINUX_KEY_SHARP 228
+#define LINUX_KEY_SOFT1 229
+#define LINUX_KEY_SOFT2 230
+#define LINUX_KEY_SEND 231
+#define LINUX_KEY_CENTER 232
+#define LINUX_KEY_HEADSETHOOK 233
+#define LINUX_KEY_0_5 234
+#define LINUX_KEY_2_5 235
+
+#define LINUX_KEY_SWITCHVIDEOMODE 236
+#define LINUX_KEY_KBDILLUMTOGGLE 237
+#define LINUX_KEY_KBDILLUMDOWN 238
+#define LINUX_KEY_KBDILLUMUP 239
+
+#define LINUX_KEY_SEND 231
+#define LINUX_KEY_REPLY 232
+#define LINUX_KEY_FORWARDMAIL 233
+#define LINUX_KEY_SAVE 234
+#define LINUX_KEY_DOCUMENTS 235
+
+#define LINUX_KEY_BATTERY 236
+
+#define LINUX_KEY_UNKNOWN 240
+
+#define LINUX_KEY_NUM 241
+#define LINUX_KEY_FOCUS 242
+#define LINUX_KEY_PLUS 243
+#define LINUX_KEY_NOTIFICATION 244
+
+#define LINUX_BTN_MISC 0x100
+#define LINUX_BTN_0 0x100
+#define LINUX_BTN_1 0x101
+#define LINUX_BTN_2 0x102
+#define LINUX_BTN_3 0x103
+#define LINUX_BTN_4 0x104
+#define LINUX_BTN_5 0x105
+#define LINUX_BTN_6 0x106
+#define LINUX_BTN_7 0x107
+#define LINUX_BTN_8 0x108
+#define LINUX_BTN_9 0x109
+
+#define LINUX_BTN_MOUSE 0x110
+#define LINUX_BTN_LEFT 0x110
+#define LINUX_BTN_RIGHT 0x111
+#define LINUX_BTN_MIDDLE 0x112
+#define LINUX_BTN_SIDE 0x113
+#define LINUX_BTN_EXTRA 0x114
+#define LINUX_BTN_FORWARD 0x115
+#define LINUX_BTN_BACK 0x116
+#define LINUX_BTN_TASK 0x117
+
+#define LINUX_BTN_JOYSTICK 0x120
+#define LINUX_BTN_TRIGGER 0x120
+#define LINUX_BTN_THUMB 0x121
+#define LINUX_BTN_THUMB2 0x122
+#define LINUX_BTN_TOP 0x123
+#define LINUX_BTN_TOP2 0x124
+#define LINUX_BTN_PINKIE 0x125
+#define LINUX_BTN_BASE 0x126
+#define LINUX_BTN_BASE2 0x127
+#define LINUX_BTN_BASE3 0x128
+#define LINUX_BTN_BASE4 0x129
+#define LINUX_BTN_BASE5 0x12a
+#define LINUX_BTN_BASE6 0x12b
+#define LINUX_BTN_DEAD 0x12f
+
+#define LINUX_BTN_GAMEPAD 0x130
+#define LINUX_BTN_A 0x130
+#define LINUX_BTN_B 0x131
+#define LINUX_BTN_C 0x132
+#define LINUX_BTN_X 0x133
+#define LINUX_BTN_Y 0x134
+#define LINUX_BTN_Z 0x135
+#define LINUX_BTN_TL 0x136
+#define LINUX_BTN_TR 0x137
+#define LINUX_BTN_TL2 0x138
+#define LINUX_BTN_TR2 0x139
+#define LINUX_BTN_SELECT 0x13a
+#define LINUX_BTN_START 0x13b
+#define LINUX_BTN_MODE 0x13c
+#define LINUX_BTN_THUMBL 0x13d
+#define LINUX_BTN_THUMBR 0x13e
+
+#define LINUX_BTN_DIGI 0x140
+#define LINUX_BTN_TOOL_PEN 0x140
+#define LINUX_BTN_TOOL_RUBBER 0x141
+#define LINUX_BTN_TOOL_BRUSH 0x142
+#define LINUX_BTN_TOOL_PENCIL 0x143
+#define LINUX_BTN_TOOL_AIRBRUSH 0x144
+#define LINUX_BTN_TOOL_FINGER 0x145
+#define LINUX_BTN_TOOL_MOUSE 0x146
+#define LINUX_BTN_TOOL_LENS 0x147
+#define LINUX_BTN_TOUCH 0x14a
+#define LINUX_BTN_STYLUS 0x14b
+#define LINUX_BTN_STYLUS2 0x14c
+#define LINUX_BTN_TOOL_DOUBLETAP 0x14d
+#define LINUX_BTN_TOOL_TRIPLETAP 0x14e
+
+#define LINUX_BTN_WHEEL 0x150
+#define LINUX_BTN_GEAR_DOWN 0x150
+#define LINUX_BTN_GEAR_UP 0x151
+
+#define LINUX_KEY_OK 0x160
+#define LINUX_KEY_SELECT 0x161
+#define LINUX_KEY_GOTO 0x162
+#define LINUX_KEY_CLEAR 0x163
+#define LINUX_KEY_POWER2 0x164
+#define LINUX_KEY_OPTION 0x165
+#define LINUX_KEY_INFO 0x166
+#define LINUX_KEY_TIME 0x167
+#define LINUX_KEY_VENDOR 0x168
+#define LINUX_KEY_ARCHIVE 0x169
+#define LINUX_KEY_PROGRAM 0x16a
+#define LINUX_KEY_CHANNEL 0x16b
+#define LINUX_KEY_FAVORITES 0x16c
+#define LINUX_KEY_EPG 0x16d
+#define LINUX_KEY_PVR 0x16e
+#define LINUX_KEY_MHP 0x16f
+#define LINUX_KEY_LANGUAGE 0x170
+#define LINUX_KEY_TITLE 0x171
+#define LINUX_KEY_SUBTITLE 0x172
+#define LINUX_KEY_ANGLE 0x173
+#define LINUX_KEY_ZOOM 0x174
+#define LINUX_KEY_MODE 0x175
+#define LINUX_KEY_KEYBOARD 0x176
+#define LINUX_KEY_SCREEN 0x177
+#define LINUX_KEY_PC 0x178
+#define LINUX_KEY_TV 0x179
+#define LINUX_KEY_TV2 0x17a
+#define LINUX_KEY_VCR 0x17b
+#define LINUX_KEY_VCR2 0x17c
+#define LINUX_KEY_SAT 0x17d
+#define LINUX_KEY_SAT2 0x17e
+#define LINUX_KEY_CD 0x17f
+#define LINUX_KEY_TAPE 0x180
+#define LINUX_KEY_RADIO 0x181
+#define LINUX_KEY_TUNER 0x182
+#define LINUX_KEY_PLAYER 0x183
+#define LINUX_KEY_TEXT 0x184
+#define LINUX_KEY_DVD 0x185
+#define LINUX_KEY_AUX 0x186
+#define LINUX_KEY_MP3 0x187
+#define LINUX_KEY_AUDIO 0x188
+#define LINUX_KEY_VIDEO 0x189
+#define LINUX_KEY_DIRECTORY 0x18a
+#define LINUX_KEY_LIST 0x18b
+#define LINUX_KEY_MEMO 0x18c
+#define LINUX_KEY_CALENDAR 0x18d
+#define LINUX_KEY_RED 0x18e
+#define LINUX_KEY_GREEN 0x18f
+#define LINUX_KEY_YELLOW 0x190
+#define LINUX_KEY_BLUE 0x191
+#define LINUX_KEY_CHANNELUP 0x192
+#define LINUX_KEY_CHANNELDOWN 0x193
+#define LINUX_KEY_FIRST 0x194
+#define LINUX_KEY_LAST 0x195
+#define LINUX_KEY_AB 0x196
+#define LINUX_KEY_NEXT 0x197
+#define LINUX_KEY_RESTART 0x198
+#define LINUX_KEY_SLOW 0x199
+#define LINUX_KEY_SHUFFLE 0x19a
+#define LINUX_KEY_BREAK 0x19b
+#define LINUX_KEY_PREVIOUS 0x19c
+#define LINUX_KEY_DIGITS 0x19d
+#define LINUX_KEY_TEEN 0x19e
+#define LINUX_KEY_TWEN 0x19f
+
+#define LINUX_KEY_DEL_EOL 0x1c0
+#define LINUX_KEY_DEL_EOS 0x1c1
+#define LINUX_KEY_INS_LINE 0x1c2
+#define LINUX_KEY_DEL_LINE 0x1c3
+
+#define LINUX_KEY_FN 0x1d0
+#define LINUX_KEY_FN_ESC 0x1d1
+#define LINUX_KEY_FN_F1 0x1d2
+#define LINUX_KEY_FN_F2 0x1d3
+#define LINUX_KEY_FN_F3 0x1d4
+#define LINUX_KEY_FN_F4 0x1d5
+#define LINUX_KEY_FN_F5 0x1d6
+#define LINUX_KEY_FN_F6 0x1d7
+#define LINUX_KEY_FN_F7 0x1d8
+#define LINUX_KEY_FN_F8 0x1d9
+#define LINUX_KEY_FN_F9 0x1da
+#define LINUX_KEY_FN_F10 0x1db
+#define LINUX_KEY_FN_F11 0x1dc
+#define LINUX_KEY_FN_F12 0x1dd
+#define LINUX_KEY_FN_1 0x1de
+#define LINUX_KEY_FN_2 0x1df
+#define LINUX_KEY_FN_D 0x1e0
+#define LINUX_KEY_FN_E 0x1e1
+#define LINUX_KEY_FN_F 0x1e2
+#define LINUX_KEY_FN_S 0x1e3
+#define LINUX_KEY_FN_B 0x1e4
+
+#define LINUX_KEY_BRL_DOT1 0x1f1
+#define LINUX_KEY_BRL_DOT2 0x1f2
+#define LINUX_KEY_BRL_DOT3 0x1f3
+#define LINUX_KEY_BRL_DOT4 0x1f4
+#define LINUX_KEY_BRL_DOT5 0x1f5
+#define LINUX_KEY_BRL_DOT6 0x1f6
+#define LINUX_KEY_BRL_DOT7 0x1f7
+#define LINUX_KEY_BRL_DOT8 0x1f8
+
+/* We avoid low common keys in module aliases so they don't get huge. */
+#define LINUX_KEY_MIN_INTERESTING KEY_MUTE
+#define LINUX_KEY_MAX 0x1ff
+
+#ifndef ABS_MT_SLOT
+#define LINUX_ABS_MT_SLOT 0x2f /* MT slot being modified */
+#endif
+#ifndef ABS_MT_TOUCH_MAJOR
+#define LINUX_ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
+#endif
+#ifndef ABS_MT_TOUCH_MINOR
+#define LINUX_ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
+#endif
+#ifndef ABS_MT_WIDTH_MAJOR
+#define LINUX_ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
+#endif
+#ifndef ABS_MT_WIDTH_MINOR
+#define LINUX_ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
+#endif
+#ifndef ABS_MT_ORIENTATION
+#define LINUX_ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
+#endif
+#ifndef ABS_MT_POSITION_X
+#define LINUX_ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
+#endif
+#ifndef ABS_MT_POSITION_Y
+#define LINUX_ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
+#endif
+#ifndef ABS_MT_TOOL_TYPE
+#define LINUX_ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
+#endif
+#ifndef ABS_MT_BLOB_ID
+#define LINUX_ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
+#endif
+#ifndef ABS_MT_TRACKING_ID
+#define LINUX_ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
+#endif
+#ifndef ABS_MT_PRESSURE
+#define LINUX_ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
+#endif
+#ifndef ABS_MT_DISTANCE
+#define LINUX_ABS_MT_DISTANCE 0x3b /* Contact hover distance */
+#endif
+#ifndef ABS_MAX
+#define LINUX_ABS_MAX 0x3f
+#endif
+
+#ifndef SYN_REPORT
+#define LINUX_SYN_REPORT 0
+#endif
+#ifndef SYN_CONFIG
+#define LINUX_SYN_CONFIG 1
+#endif
+#ifndef SYN_MT_REPORT
+#define LINUX_SYN_MT_REPORT 2
+#endif
+#ifndef SYN_DROPPED
+#define LINUX_SYN_DROPPED 3
+#endif
+
+#endif