2014-04-01 12:06:29 +04:00
|
|
|
/*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
|
|
|
* (at your option) any later version. See the COPYING file in the
|
|
|
|
* top-level directory.
|
|
|
|
*/
|
|
|
|
|
2016-01-26 21:17:07 +03:00
|
|
|
#include "qemu/osdep.h"
|
2014-04-01 12:06:29 +04:00
|
|
|
#include "qemu/iov.h"
|
|
|
|
|
|
|
|
#include "hw/qdev.h"
|
|
|
|
#include "hw/virtio/virtio.h"
|
|
|
|
#include "hw/virtio/virtio-input.h"
|
|
|
|
|
|
|
|
#undef CONFIG_CURSES
|
|
|
|
#include "ui/console.h"
|
|
|
|
|
|
|
|
#include "standard-headers/linux/input.h"
|
|
|
|
|
|
|
|
#define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard"
|
|
|
|
#define VIRTIO_ID_NAME_MOUSE "QEMU Virtio Mouse"
|
|
|
|
#define VIRTIO_ID_NAME_TABLET "QEMU Virtio Tablet"
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
|
|
|
qapi: Don't let implicit enum MAX member collide
Now that we guarantee the user doesn't have any enum values
beginning with a single underscore, we can use that for our
own purposes. Renaming ENUM_MAX to ENUM__MAX makes it obvious
that the sentinel is generated.
This patch was mostly generated by applying a temporary patch:
|diff --git a/scripts/qapi.py b/scripts/qapi.py
|index e6d014b..b862ec9 100644
|--- a/scripts/qapi.py
|+++ b/scripts/qapi.py
|@@ -1570,6 +1570,7 @@ const char *const %(c_name)s_lookup[] = {
| max_index = c_enum_const(name, 'MAX', prefix)
| ret += mcgen('''
| [%(max_index)s] = NULL,
|+// %(max_index)s
| };
| ''',
| max_index=max_index)
then running:
$ cat qapi-{types,event}.c tests/test-qapi-types.c |
sed -n 's,^// \(.*\)MAX,s|\1MAX|\1_MAX|g,p' > list
$ git grep -l _MAX | xargs sed -i -f list
The only things not generated are the changes in scripts/qapi.py.
Rejecting enum members named 'MAX' is now useless, and will be dropped
in the next patch.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-23-git-send-email-eblake@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[Rebased to current master, commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 11:52:57 +03:00
|
|
|
static const unsigned int keymap_qcode[Q_KEY_CODE__MAX] = {
|
2014-04-01 12:06:29 +04:00
|
|
|
[Q_KEY_CODE_ESC] = KEY_ESC,
|
|
|
|
[Q_KEY_CODE_1] = KEY_1,
|
|
|
|
[Q_KEY_CODE_2] = KEY_2,
|
|
|
|
[Q_KEY_CODE_3] = KEY_3,
|
|
|
|
[Q_KEY_CODE_4] = KEY_4,
|
|
|
|
[Q_KEY_CODE_5] = KEY_5,
|
|
|
|
[Q_KEY_CODE_6] = KEY_6,
|
|
|
|
[Q_KEY_CODE_7] = KEY_7,
|
|
|
|
[Q_KEY_CODE_8] = KEY_8,
|
|
|
|
[Q_KEY_CODE_9] = KEY_9,
|
|
|
|
[Q_KEY_CODE_0] = KEY_0,
|
|
|
|
[Q_KEY_CODE_MINUS] = KEY_MINUS,
|
|
|
|
[Q_KEY_CODE_EQUAL] = KEY_EQUAL,
|
|
|
|
[Q_KEY_CODE_BACKSPACE] = KEY_BACKSPACE,
|
|
|
|
|
|
|
|
[Q_KEY_CODE_TAB] = KEY_TAB,
|
|
|
|
[Q_KEY_CODE_Q] = KEY_Q,
|
|
|
|
[Q_KEY_CODE_W] = KEY_W,
|
|
|
|
[Q_KEY_CODE_E] = KEY_E,
|
|
|
|
[Q_KEY_CODE_R] = KEY_R,
|
|
|
|
[Q_KEY_CODE_T] = KEY_T,
|
|
|
|
[Q_KEY_CODE_Y] = KEY_Y,
|
|
|
|
[Q_KEY_CODE_U] = KEY_U,
|
|
|
|
[Q_KEY_CODE_I] = KEY_I,
|
|
|
|
[Q_KEY_CODE_O] = KEY_O,
|
|
|
|
[Q_KEY_CODE_P] = KEY_P,
|
|
|
|
[Q_KEY_CODE_BRACKET_LEFT] = KEY_LEFTBRACE,
|
|
|
|
[Q_KEY_CODE_BRACKET_RIGHT] = KEY_RIGHTBRACE,
|
|
|
|
[Q_KEY_CODE_RET] = KEY_ENTER,
|
|
|
|
|
|
|
|
[Q_KEY_CODE_CTRL] = KEY_LEFTCTRL,
|
|
|
|
[Q_KEY_CODE_A] = KEY_A,
|
|
|
|
[Q_KEY_CODE_S] = KEY_S,
|
|
|
|
[Q_KEY_CODE_D] = KEY_D,
|
|
|
|
[Q_KEY_CODE_F] = KEY_F,
|
|
|
|
[Q_KEY_CODE_G] = KEY_G,
|
|
|
|
[Q_KEY_CODE_H] = KEY_H,
|
|
|
|
[Q_KEY_CODE_J] = KEY_J,
|
|
|
|
[Q_KEY_CODE_K] = KEY_K,
|
|
|
|
[Q_KEY_CODE_L] = KEY_L,
|
|
|
|
[Q_KEY_CODE_SEMICOLON] = KEY_SEMICOLON,
|
|
|
|
[Q_KEY_CODE_APOSTROPHE] = KEY_APOSTROPHE,
|
|
|
|
[Q_KEY_CODE_GRAVE_ACCENT] = KEY_GRAVE,
|
|
|
|
|
|
|
|
[Q_KEY_CODE_SHIFT] = KEY_LEFTSHIFT,
|
|
|
|
[Q_KEY_CODE_BACKSLASH] = KEY_BACKSLASH,
|
|
|
|
[Q_KEY_CODE_LESS] = KEY_102ND,
|
|
|
|
[Q_KEY_CODE_Z] = KEY_Z,
|
|
|
|
[Q_KEY_CODE_X] = KEY_X,
|
|
|
|
[Q_KEY_CODE_C] = KEY_C,
|
|
|
|
[Q_KEY_CODE_V] = KEY_V,
|
|
|
|
[Q_KEY_CODE_B] = KEY_B,
|
|
|
|
[Q_KEY_CODE_N] = KEY_N,
|
|
|
|
[Q_KEY_CODE_M] = KEY_M,
|
|
|
|
[Q_KEY_CODE_COMMA] = KEY_COMMA,
|
|
|
|
[Q_KEY_CODE_DOT] = KEY_DOT,
|
|
|
|
[Q_KEY_CODE_SLASH] = KEY_SLASH,
|
|
|
|
[Q_KEY_CODE_SHIFT_R] = KEY_RIGHTSHIFT,
|
|
|
|
|
|
|
|
[Q_KEY_CODE_ALT] = KEY_LEFTALT,
|
|
|
|
[Q_KEY_CODE_SPC] = KEY_SPACE,
|
|
|
|
[Q_KEY_CODE_CAPS_LOCK] = KEY_CAPSLOCK,
|
|
|
|
|
|
|
|
[Q_KEY_CODE_F1] = KEY_F1,
|
|
|
|
[Q_KEY_CODE_F2] = KEY_F2,
|
|
|
|
[Q_KEY_CODE_F3] = KEY_F3,
|
|
|
|
[Q_KEY_CODE_F4] = KEY_F4,
|
|
|
|
[Q_KEY_CODE_F5] = KEY_F5,
|
|
|
|
[Q_KEY_CODE_F6] = KEY_F6,
|
|
|
|
[Q_KEY_CODE_F7] = KEY_F7,
|
|
|
|
[Q_KEY_CODE_F8] = KEY_F8,
|
|
|
|
[Q_KEY_CODE_F9] = KEY_F9,
|
|
|
|
[Q_KEY_CODE_F10] = KEY_F10,
|
|
|
|
[Q_KEY_CODE_NUM_LOCK] = KEY_NUMLOCK,
|
|
|
|
[Q_KEY_CODE_SCROLL_LOCK] = KEY_SCROLLLOCK,
|
|
|
|
|
|
|
|
[Q_KEY_CODE_KP_0] = KEY_KP0,
|
|
|
|
[Q_KEY_CODE_KP_1] = KEY_KP1,
|
|
|
|
[Q_KEY_CODE_KP_2] = KEY_KP2,
|
|
|
|
[Q_KEY_CODE_KP_3] = KEY_KP3,
|
|
|
|
[Q_KEY_CODE_KP_4] = KEY_KP4,
|
|
|
|
[Q_KEY_CODE_KP_5] = KEY_KP5,
|
|
|
|
[Q_KEY_CODE_KP_6] = KEY_KP6,
|
|
|
|
[Q_KEY_CODE_KP_7] = KEY_KP7,
|
|
|
|
[Q_KEY_CODE_KP_8] = KEY_KP8,
|
|
|
|
[Q_KEY_CODE_KP_9] = KEY_KP9,
|
|
|
|
[Q_KEY_CODE_KP_SUBTRACT] = KEY_KPMINUS,
|
|
|
|
[Q_KEY_CODE_KP_ADD] = KEY_KPPLUS,
|
|
|
|
[Q_KEY_CODE_KP_DECIMAL] = KEY_KPDOT,
|
|
|
|
[Q_KEY_CODE_KP_ENTER] = KEY_KPENTER,
|
|
|
|
[Q_KEY_CODE_KP_DIVIDE] = KEY_KPSLASH,
|
|
|
|
[Q_KEY_CODE_KP_MULTIPLY] = KEY_KPASTERISK,
|
|
|
|
|
|
|
|
[Q_KEY_CODE_F11] = KEY_F11,
|
|
|
|
[Q_KEY_CODE_F12] = KEY_F12,
|
|
|
|
|
|
|
|
[Q_KEY_CODE_CTRL_R] = KEY_RIGHTCTRL,
|
|
|
|
[Q_KEY_CODE_SYSRQ] = KEY_SYSRQ,
|
2016-03-30 16:07:20 +03:00
|
|
|
[Q_KEY_CODE_PRINT] = KEY_SYSRQ,
|
|
|
|
[Q_KEY_CODE_PAUSE] = KEY_PAUSE,
|
2014-04-01 12:06:29 +04:00
|
|
|
[Q_KEY_CODE_ALT_R] = KEY_RIGHTALT,
|
|
|
|
|
|
|
|
[Q_KEY_CODE_HOME] = KEY_HOME,
|
|
|
|
[Q_KEY_CODE_UP] = KEY_UP,
|
|
|
|
[Q_KEY_CODE_PGUP] = KEY_PAGEUP,
|
|
|
|
[Q_KEY_CODE_LEFT] = KEY_LEFT,
|
|
|
|
[Q_KEY_CODE_RIGHT] = KEY_RIGHT,
|
|
|
|
[Q_KEY_CODE_END] = KEY_END,
|
|
|
|
[Q_KEY_CODE_DOWN] = KEY_DOWN,
|
|
|
|
[Q_KEY_CODE_PGDN] = KEY_PAGEDOWN,
|
|
|
|
[Q_KEY_CODE_INSERT] = KEY_INSERT,
|
|
|
|
[Q_KEY_CODE_DELETE] = KEY_DELETE,
|
|
|
|
|
|
|
|
[Q_KEY_CODE_META_L] = KEY_LEFTMETA,
|
|
|
|
[Q_KEY_CODE_META_R] = KEY_RIGHTMETA,
|
|
|
|
[Q_KEY_CODE_MENU] = KEY_MENU,
|
|
|
|
};
|
|
|
|
|
qapi: Don't let implicit enum MAX member collide
Now that we guarantee the user doesn't have any enum values
beginning with a single underscore, we can use that for our
own purposes. Renaming ENUM_MAX to ENUM__MAX makes it obvious
that the sentinel is generated.
This patch was mostly generated by applying a temporary patch:
|diff --git a/scripts/qapi.py b/scripts/qapi.py
|index e6d014b..b862ec9 100644
|--- a/scripts/qapi.py
|+++ b/scripts/qapi.py
|@@ -1570,6 +1570,7 @@ const char *const %(c_name)s_lookup[] = {
| max_index = c_enum_const(name, 'MAX', prefix)
| ret += mcgen('''
| [%(max_index)s] = NULL,
|+// %(max_index)s
| };
| ''',
| max_index=max_index)
then running:
$ cat qapi-{types,event}.c tests/test-qapi-types.c |
sed -n 's,^// \(.*\)MAX,s|\1MAX|\1_MAX|g,p' > list
$ git grep -l _MAX | xargs sed -i -f list
The only things not generated are the changes in scripts/qapi.py.
Rejecting enum members named 'MAX' is now useless, and will be dropped
in the next patch.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-23-git-send-email-eblake@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[Rebased to current master, commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 11:52:57 +03:00
|
|
|
static const unsigned int keymap_button[INPUT_BUTTON__MAX] = {
|
2014-04-01 12:06:29 +04:00
|
|
|
[INPUT_BUTTON_LEFT] = BTN_LEFT,
|
|
|
|
[INPUT_BUTTON_RIGHT] = BTN_RIGHT,
|
|
|
|
[INPUT_BUTTON_MIDDLE] = BTN_MIDDLE,
|
2016-01-12 14:14:12 +03:00
|
|
|
[INPUT_BUTTON_WHEEL_UP] = BTN_GEAR_UP,
|
|
|
|
[INPUT_BUTTON_WHEEL_DOWN] = BTN_GEAR_DOWN,
|
2014-04-01 12:06:29 +04:00
|
|
|
};
|
|
|
|
|
qapi: Don't let implicit enum MAX member collide
Now that we guarantee the user doesn't have any enum values
beginning with a single underscore, we can use that for our
own purposes. Renaming ENUM_MAX to ENUM__MAX makes it obvious
that the sentinel is generated.
This patch was mostly generated by applying a temporary patch:
|diff --git a/scripts/qapi.py b/scripts/qapi.py
|index e6d014b..b862ec9 100644
|--- a/scripts/qapi.py
|+++ b/scripts/qapi.py
|@@ -1570,6 +1570,7 @@ const char *const %(c_name)s_lookup[] = {
| max_index = c_enum_const(name, 'MAX', prefix)
| ret += mcgen('''
| [%(max_index)s] = NULL,
|+// %(max_index)s
| };
| ''',
| max_index=max_index)
then running:
$ cat qapi-{types,event}.c tests/test-qapi-types.c |
sed -n 's,^// \(.*\)MAX,s|\1MAX|\1_MAX|g,p' > list
$ git grep -l _MAX | xargs sed -i -f list
The only things not generated are the changes in scripts/qapi.py.
Rejecting enum members named 'MAX' is now useless, and will be dropped
in the next patch.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-23-git-send-email-eblake@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[Rebased to current master, commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 11:52:57 +03:00
|
|
|
static const unsigned int axismap_rel[INPUT_AXIS__MAX] = {
|
2014-04-01 12:06:29 +04:00
|
|
|
[INPUT_AXIS_X] = REL_X,
|
|
|
|
[INPUT_AXIS_Y] = REL_Y,
|
|
|
|
};
|
|
|
|
|
qapi: Don't let implicit enum MAX member collide
Now that we guarantee the user doesn't have any enum values
beginning with a single underscore, we can use that for our
own purposes. Renaming ENUM_MAX to ENUM__MAX makes it obvious
that the sentinel is generated.
This patch was mostly generated by applying a temporary patch:
|diff --git a/scripts/qapi.py b/scripts/qapi.py
|index e6d014b..b862ec9 100644
|--- a/scripts/qapi.py
|+++ b/scripts/qapi.py
|@@ -1570,6 +1570,7 @@ const char *const %(c_name)s_lookup[] = {
| max_index = c_enum_const(name, 'MAX', prefix)
| ret += mcgen('''
| [%(max_index)s] = NULL,
|+// %(max_index)s
| };
| ''',
| max_index=max_index)
then running:
$ cat qapi-{types,event}.c tests/test-qapi-types.c |
sed -n 's,^// \(.*\)MAX,s|\1MAX|\1_MAX|g,p' > list
$ git grep -l _MAX | xargs sed -i -f list
The only things not generated are the changes in scripts/qapi.py.
Rejecting enum members named 'MAX' is now useless, and will be dropped
in the next patch.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-23-git-send-email-eblake@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[Rebased to current master, commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 11:52:57 +03:00
|
|
|
static const unsigned int axismap_abs[INPUT_AXIS__MAX] = {
|
2014-04-01 12:06:29 +04:00
|
|
|
[INPUT_AXIS_X] = ABS_X,
|
|
|
|
[INPUT_AXIS_Y] = ABS_Y,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static void virtio_input_key_config(VirtIOInput *vinput,
|
|
|
|
const unsigned int *keymap,
|
|
|
|
size_t mapsize)
|
|
|
|
{
|
|
|
|
virtio_input_config keys;
|
|
|
|
int i, bit, byte, bmax = 0;
|
|
|
|
|
|
|
|
memset(&keys, 0, sizeof(keys));
|
|
|
|
for (i = 0; i < mapsize; i++) {
|
|
|
|
bit = keymap[i];
|
|
|
|
if (!bit) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
byte = bit / 8;
|
|
|
|
bit = bit % 8;
|
|
|
|
keys.u.bitmap[byte] |= (1 << bit);
|
|
|
|
if (bmax < byte+1) {
|
|
|
|
bmax = byte+1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
keys.select = VIRTIO_INPUT_CFG_EV_BITS;
|
|
|
|
keys.subsel = EV_KEY;
|
|
|
|
keys.size = bmax;
|
|
|
|
virtio_input_add_config(vinput, &keys);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
|
|
|
|
InputEvent *evt)
|
|
|
|
{
|
|
|
|
VirtIOInput *vinput = VIRTIO_INPUT(dev);
|
|
|
|
virtio_input_event event;
|
|
|
|
int qcode;
|
2016-03-03 19:16:49 +03:00
|
|
|
InputKeyEvent *key;
|
|
|
|
InputMoveEvent *move;
|
|
|
|
InputBtnEvent *btn;
|
2014-04-01 12:06:29 +04:00
|
|
|
|
2015-10-27 01:34:58 +03:00
|
|
|
switch (evt->type) {
|
2014-04-01 12:06:29 +04:00
|
|
|
case INPUT_EVENT_KIND_KEY:
|
qapi: Don't special-case simple union wrappers
Simple unions were carrying a special case that hid their 'data'
QMP member from the resulting C struct, via the hack method
QAPISchemaObjectTypeVariant.simple_union_type(). But by using
the work we started by unboxing flat union and alternate
branches, coupled with the ability to visit the members of an
implicit type, we can now expose the simple union's implicit
type in qapi-types.h:
| struct q_obj_ImageInfoSpecificQCow2_wrapper {
| ImageInfoSpecificQCow2 *data;
| };
|
| struct q_obj_ImageInfoSpecificVmdk_wrapper {
| ImageInfoSpecificVmdk *data;
| };
...
| struct ImageInfoSpecific {
| ImageInfoSpecificKind type;
| union { /* union tag is @type */
| void *data;
|- ImageInfoSpecificQCow2 *qcow2;
|- ImageInfoSpecificVmdk *vmdk;
|+ q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
|+ q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
| } u;
| };
Doing this removes asymmetry between QAPI's QMP side and its
C side (both sides now expose 'data'), and means that the
treatment of a simple union as sugar for a flat union is now
equivalent in both languages (previously the two approaches used
a different layer of dereferencing, where the simple union could
be converted to a flat union with equivalent C layout but
different {} on the wire, or to an equivalent QMP wire form
but with different C representation). Using the implicit type
also lets us get rid of the simple_union_type() hack.
Of course, now all clients of simple unions have to adjust from
using su->u.member to using su->u.member.data; while this touches
a number of files in the tree, some earlier cleanup patches
helped minimize the change to the initialization of a temporary
variable rather than every single member access. The generated
qapi-visit.c code is also affected by the layout change:
|@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
| }
| switch (obj->type) {
| case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
|- visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
|+ visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
| break;
| case IMAGE_INFO_SPECIFIC_KIND_VMDK:
|- visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
|+ visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
| break;
| default:
| abort();
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18 01:48:37 +03:00
|
|
|
key = evt->u.key.data;
|
2016-03-03 19:16:49 +03:00
|
|
|
qcode = qemu_input_key_value_to_qcode(key->key);
|
2014-04-01 12:06:29 +04:00
|
|
|
if (qcode && keymap_qcode[qcode]) {
|
|
|
|
event.type = cpu_to_le16(EV_KEY);
|
|
|
|
event.code = cpu_to_le16(keymap_qcode[qcode]);
|
2016-03-03 19:16:49 +03:00
|
|
|
event.value = cpu_to_le32(key->down ? 1 : 0);
|
2014-04-01 12:06:29 +04:00
|
|
|
virtio_input_send(vinput, &event);
|
|
|
|
} else {
|
2016-03-03 19:16:49 +03:00
|
|
|
if (key->down) {
|
2014-04-01 12:06:29 +04:00
|
|
|
fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
|
|
|
|
qcode, QKeyCode_lookup[qcode]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case INPUT_EVENT_KIND_BTN:
|
qapi: Don't special-case simple union wrappers
Simple unions were carrying a special case that hid their 'data'
QMP member from the resulting C struct, via the hack method
QAPISchemaObjectTypeVariant.simple_union_type(). But by using
the work we started by unboxing flat union and alternate
branches, coupled with the ability to visit the members of an
implicit type, we can now expose the simple union's implicit
type in qapi-types.h:
| struct q_obj_ImageInfoSpecificQCow2_wrapper {
| ImageInfoSpecificQCow2 *data;
| };
|
| struct q_obj_ImageInfoSpecificVmdk_wrapper {
| ImageInfoSpecificVmdk *data;
| };
...
| struct ImageInfoSpecific {
| ImageInfoSpecificKind type;
| union { /* union tag is @type */
| void *data;
|- ImageInfoSpecificQCow2 *qcow2;
|- ImageInfoSpecificVmdk *vmdk;
|+ q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
|+ q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
| } u;
| };
Doing this removes asymmetry between QAPI's QMP side and its
C side (both sides now expose 'data'), and means that the
treatment of a simple union as sugar for a flat union is now
equivalent in both languages (previously the two approaches used
a different layer of dereferencing, where the simple union could
be converted to a flat union with equivalent C layout but
different {} on the wire, or to an equivalent QMP wire form
but with different C representation). Using the implicit type
also lets us get rid of the simple_union_type() hack.
Of course, now all clients of simple unions have to adjust from
using su->u.member to using su->u.member.data; while this touches
a number of files in the tree, some earlier cleanup patches
helped minimize the change to the initialization of a temporary
variable rather than every single member access. The generated
qapi-visit.c code is also affected by the layout change:
|@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
| }
| switch (obj->type) {
| case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
|- visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
|+ visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
| break;
| case IMAGE_INFO_SPECIFIC_KIND_VMDK:
|- visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
|+ visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
| break;
| default:
| abort();
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18 01:48:37 +03:00
|
|
|
btn = evt->u.btn.data;
|
2016-03-03 19:16:49 +03:00
|
|
|
if (keymap_button[btn->button]) {
|
2014-04-01 12:06:29 +04:00
|
|
|
event.type = cpu_to_le16(EV_KEY);
|
2016-03-03 19:16:49 +03:00
|
|
|
event.code = cpu_to_le16(keymap_button[btn->button]);
|
|
|
|
event.value = cpu_to_le32(btn->down ? 1 : 0);
|
2014-04-01 12:06:29 +04:00
|
|
|
virtio_input_send(vinput, &event);
|
|
|
|
} else {
|
2016-03-03 19:16:49 +03:00
|
|
|
if (btn->down) {
|
2014-04-01 12:06:29 +04:00
|
|
|
fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
|
2016-03-03 19:16:49 +03:00
|
|
|
btn->button,
|
|
|
|
InputButton_lookup[btn->button]);
|
2014-04-01 12:06:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case INPUT_EVENT_KIND_REL:
|
qapi: Don't special-case simple union wrappers
Simple unions were carrying a special case that hid their 'data'
QMP member from the resulting C struct, via the hack method
QAPISchemaObjectTypeVariant.simple_union_type(). But by using
the work we started by unboxing flat union and alternate
branches, coupled with the ability to visit the members of an
implicit type, we can now expose the simple union's implicit
type in qapi-types.h:
| struct q_obj_ImageInfoSpecificQCow2_wrapper {
| ImageInfoSpecificQCow2 *data;
| };
|
| struct q_obj_ImageInfoSpecificVmdk_wrapper {
| ImageInfoSpecificVmdk *data;
| };
...
| struct ImageInfoSpecific {
| ImageInfoSpecificKind type;
| union { /* union tag is @type */
| void *data;
|- ImageInfoSpecificQCow2 *qcow2;
|- ImageInfoSpecificVmdk *vmdk;
|+ q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
|+ q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
| } u;
| };
Doing this removes asymmetry between QAPI's QMP side and its
C side (both sides now expose 'data'), and means that the
treatment of a simple union as sugar for a flat union is now
equivalent in both languages (previously the two approaches used
a different layer of dereferencing, where the simple union could
be converted to a flat union with equivalent C layout but
different {} on the wire, or to an equivalent QMP wire form
but with different C representation). Using the implicit type
also lets us get rid of the simple_union_type() hack.
Of course, now all clients of simple unions have to adjust from
using su->u.member to using su->u.member.data; while this touches
a number of files in the tree, some earlier cleanup patches
helped minimize the change to the initialization of a temporary
variable rather than every single member access. The generated
qapi-visit.c code is also affected by the layout change:
|@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
| }
| switch (obj->type) {
| case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
|- visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
|+ visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
| break;
| case IMAGE_INFO_SPECIFIC_KIND_VMDK:
|- visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
|+ visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
| break;
| default:
| abort();
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18 01:48:37 +03:00
|
|
|
move = evt->u.rel.data;
|
2014-04-01 12:06:29 +04:00
|
|
|
event.type = cpu_to_le16(EV_REL);
|
2016-03-03 19:16:49 +03:00
|
|
|
event.code = cpu_to_le16(axismap_rel[move->axis]);
|
|
|
|
event.value = cpu_to_le32(move->value);
|
2014-04-01 12:06:29 +04:00
|
|
|
virtio_input_send(vinput, &event);
|
|
|
|
break;
|
|
|
|
case INPUT_EVENT_KIND_ABS:
|
qapi: Don't special-case simple union wrappers
Simple unions were carrying a special case that hid their 'data'
QMP member from the resulting C struct, via the hack method
QAPISchemaObjectTypeVariant.simple_union_type(). But by using
the work we started by unboxing flat union and alternate
branches, coupled with the ability to visit the members of an
implicit type, we can now expose the simple union's implicit
type in qapi-types.h:
| struct q_obj_ImageInfoSpecificQCow2_wrapper {
| ImageInfoSpecificQCow2 *data;
| };
|
| struct q_obj_ImageInfoSpecificVmdk_wrapper {
| ImageInfoSpecificVmdk *data;
| };
...
| struct ImageInfoSpecific {
| ImageInfoSpecificKind type;
| union { /* union tag is @type */
| void *data;
|- ImageInfoSpecificQCow2 *qcow2;
|- ImageInfoSpecificVmdk *vmdk;
|+ q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
|+ q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
| } u;
| };
Doing this removes asymmetry between QAPI's QMP side and its
C side (both sides now expose 'data'), and means that the
treatment of a simple union as sugar for a flat union is now
equivalent in both languages (previously the two approaches used
a different layer of dereferencing, where the simple union could
be converted to a flat union with equivalent C layout but
different {} on the wire, or to an equivalent QMP wire form
but with different C representation). Using the implicit type
also lets us get rid of the simple_union_type() hack.
Of course, now all clients of simple unions have to adjust from
using su->u.member to using su->u.member.data; while this touches
a number of files in the tree, some earlier cleanup patches
helped minimize the change to the initialization of a temporary
variable rather than every single member access. The generated
qapi-visit.c code is also affected by the layout change:
|@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
| }
| switch (obj->type) {
| case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
|- visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
|+ visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
| break;
| case IMAGE_INFO_SPECIFIC_KIND_VMDK:
|- visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
|+ visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
| break;
| default:
| abort();
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18 01:48:37 +03:00
|
|
|
move = evt->u.abs.data;
|
2014-04-01 12:06:29 +04:00
|
|
|
event.type = cpu_to_le16(EV_ABS);
|
2016-03-03 19:16:49 +03:00
|
|
|
event.code = cpu_to_le16(axismap_abs[move->axis]);
|
|
|
|
event.value = cpu_to_le32(move->value);
|
2014-04-01 12:06:29 +04:00
|
|
|
virtio_input_send(vinput, &event);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* keep gcc happy */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void virtio_input_handle_sync(DeviceState *dev)
|
|
|
|
{
|
|
|
|
VirtIOInput *vinput = VIRTIO_INPUT(dev);
|
|
|
|
virtio_input_event event = {
|
|
|
|
.type = cpu_to_le16(EV_SYN),
|
|
|
|
.code = cpu_to_le16(SYN_REPORT),
|
|
|
|
.value = 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
virtio_input_send(vinput, &event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void virtio_input_hid_realize(DeviceState *dev, Error **errp)
|
|
|
|
{
|
|
|
|
VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
|
2015-06-24 12:59:16 +03:00
|
|
|
|
2014-04-01 12:06:29 +04:00
|
|
|
vhid->hs = qemu_input_handler_register(dev, vhid->handler);
|
2015-06-24 12:59:16 +03:00
|
|
|
if (vhid->display && vhid->hs) {
|
|
|
|
qemu_input_handler_bind(vhid->hs, vhid->display, vhid->head, NULL);
|
|
|
|
}
|
2014-04-01 12:06:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void virtio_input_hid_unrealize(DeviceState *dev, Error **errp)
|
|
|
|
{
|
|
|
|
VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
|
|
|
|
qemu_input_handler_unregister(vhid->hs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void virtio_input_hid_change_active(VirtIOInput *vinput)
|
|
|
|
{
|
|
|
|
VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
|
|
|
|
|
|
|
|
if (vinput->active) {
|
|
|
|
qemu_input_handler_activate(vhid->hs);
|
|
|
|
} else {
|
|
|
|
qemu_input_handler_deactivate(vhid->hs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void virtio_input_hid_handle_status(VirtIOInput *vinput,
|
|
|
|
virtio_input_event *event)
|
|
|
|
{
|
|
|
|
VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
|
|
|
|
int ledbit = 0;
|
|
|
|
|
|
|
|
switch (le16_to_cpu(event->type)) {
|
|
|
|
case EV_LED:
|
|
|
|
if (event->code == LED_NUML) {
|
|
|
|
ledbit = QEMU_NUM_LOCK_LED;
|
|
|
|
} else if (event->code == LED_CAPSL) {
|
|
|
|
ledbit = QEMU_CAPS_LOCK_LED;
|
|
|
|
} else if (event->code == LED_SCROLLL) {
|
|
|
|
ledbit = QEMU_SCROLL_LOCK_LED;
|
|
|
|
}
|
|
|
|
if (event->value) {
|
|
|
|
vhid->ledstate |= ledbit;
|
|
|
|
} else {
|
|
|
|
vhid->ledstate &= ~ledbit;
|
|
|
|
}
|
|
|
|
kbd_put_ledstate(vhid->ledstate);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "%s: unknown type %d\n", __func__,
|
|
|
|
le16_to_cpu(event->type));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-24 12:59:16 +03:00
|
|
|
static Property virtio_input_hid_properties[] = {
|
|
|
|
DEFINE_PROP_STRING("display", VirtIOInputHID, display),
|
|
|
|
DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0),
|
2015-07-14 14:27:30 +03:00
|
|
|
DEFINE_PROP_END_OF_LIST(),
|
2015-06-24 12:59:16 +03:00
|
|
|
};
|
|
|
|
|
2014-04-01 12:06:29 +04:00
|
|
|
static void virtio_input_hid_class_init(ObjectClass *klass, void *data)
|
|
|
|
{
|
2015-06-24 12:59:16 +03:00
|
|
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
2014-04-01 12:06:29 +04:00
|
|
|
VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
|
|
|
|
|
2015-06-24 12:59:16 +03:00
|
|
|
dc->props = virtio_input_hid_properties;
|
2014-04-01 12:06:29 +04:00
|
|
|
vic->realize = virtio_input_hid_realize;
|
|
|
|
vic->unrealize = virtio_input_hid_unrealize;
|
|
|
|
vic->change_active = virtio_input_hid_change_active;
|
|
|
|
vic->handle_status = virtio_input_hid_handle_status;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const TypeInfo virtio_input_hid_info = {
|
|
|
|
.name = TYPE_VIRTIO_INPUT_HID,
|
|
|
|
.parent = TYPE_VIRTIO_INPUT,
|
|
|
|
.instance_size = sizeof(VirtIOInputHID),
|
|
|
|
.class_init = virtio_input_hid_class_init,
|
|
|
|
.abstract = true,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static QemuInputHandler virtio_keyboard_handler = {
|
|
|
|
.name = VIRTIO_ID_NAME_KEYBOARD,
|
|
|
|
.mask = INPUT_EVENT_MASK_KEY,
|
|
|
|
.event = virtio_input_handle_event,
|
|
|
|
.sync = virtio_input_handle_sync,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct virtio_input_config virtio_keyboard_config[] = {
|
|
|
|
{
|
|
|
|
.select = VIRTIO_INPUT_CFG_ID_NAME,
|
|
|
|
.size = sizeof(VIRTIO_ID_NAME_KEYBOARD),
|
|
|
|
.u.string = VIRTIO_ID_NAME_KEYBOARD,
|
|
|
|
},{
|
|
|
|
.select = VIRTIO_INPUT_CFG_ID_DEVIDS,
|
|
|
|
.size = sizeof(struct virtio_input_devids),
|
|
|
|
.u.ids = {
|
|
|
|
.bustype = const_le16(BUS_VIRTUAL),
|
|
|
|
.vendor = const_le16(0x0627), /* same we use for usb hid devices */
|
|
|
|
.product = const_le16(0x0001),
|
|
|
|
.version = const_le16(0x0001),
|
|
|
|
},
|
|
|
|
},{
|
|
|
|
.select = VIRTIO_INPUT_CFG_EV_BITS,
|
|
|
|
.subsel = EV_REP,
|
|
|
|
.size = 1,
|
|
|
|
},{
|
|
|
|
.select = VIRTIO_INPUT_CFG_EV_BITS,
|
|
|
|
.subsel = EV_LED,
|
|
|
|
.size = 1,
|
|
|
|
.u.bitmap = {
|
|
|
|
(1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ /* end of list */ },
|
|
|
|
};
|
|
|
|
|
|
|
|
static void virtio_keyboard_init(Object *obj)
|
|
|
|
{
|
|
|
|
VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
|
|
|
|
VirtIOInput *vinput = VIRTIO_INPUT(obj);
|
|
|
|
|
|
|
|
vhid->handler = &virtio_keyboard_handler;
|
|
|
|
virtio_input_init_config(vinput, virtio_keyboard_config);
|
|
|
|
virtio_input_key_config(vinput, keymap_qcode,
|
|
|
|
ARRAY_SIZE(keymap_qcode));
|
|
|
|
}
|
|
|
|
|
|
|
|
static const TypeInfo virtio_keyboard_info = {
|
|
|
|
.name = TYPE_VIRTIO_KEYBOARD,
|
|
|
|
.parent = TYPE_VIRTIO_INPUT_HID,
|
|
|
|
.instance_size = sizeof(VirtIOInputHID),
|
|
|
|
.instance_init = virtio_keyboard_init,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static QemuInputHandler virtio_mouse_handler = {
|
|
|
|
.name = VIRTIO_ID_NAME_MOUSE,
|
|
|
|
.mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
|
|
|
|
.event = virtio_input_handle_event,
|
|
|
|
.sync = virtio_input_handle_sync,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct virtio_input_config virtio_mouse_config[] = {
|
|
|
|
{
|
|
|
|
.select = VIRTIO_INPUT_CFG_ID_NAME,
|
|
|
|
.size = sizeof(VIRTIO_ID_NAME_MOUSE),
|
|
|
|
.u.string = VIRTIO_ID_NAME_MOUSE,
|
|
|
|
},{
|
|
|
|
.select = VIRTIO_INPUT_CFG_ID_DEVIDS,
|
|
|
|
.size = sizeof(struct virtio_input_devids),
|
|
|
|
.u.ids = {
|
|
|
|
.bustype = const_le16(BUS_VIRTUAL),
|
|
|
|
.vendor = const_le16(0x0627), /* same we use for usb hid devices */
|
|
|
|
.product = const_le16(0x0002),
|
|
|
|
.version = const_le16(0x0001),
|
|
|
|
},
|
|
|
|
},{
|
|
|
|
.select = VIRTIO_INPUT_CFG_EV_BITS,
|
|
|
|
.subsel = EV_REL,
|
|
|
|
.size = 1,
|
|
|
|
.u.bitmap = {
|
|
|
|
(1 << REL_X) | (1 << REL_Y),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ /* end of list */ },
|
|
|
|
};
|
|
|
|
|
|
|
|
static void virtio_mouse_init(Object *obj)
|
|
|
|
{
|
|
|
|
VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
|
|
|
|
VirtIOInput *vinput = VIRTIO_INPUT(obj);
|
|
|
|
|
|
|
|
vhid->handler = &virtio_mouse_handler;
|
|
|
|
virtio_input_init_config(vinput, virtio_mouse_config);
|
|
|
|
virtio_input_key_config(vinput, keymap_button,
|
|
|
|
ARRAY_SIZE(keymap_button));
|
|
|
|
}
|
|
|
|
|
|
|
|
static const TypeInfo virtio_mouse_info = {
|
|
|
|
.name = TYPE_VIRTIO_MOUSE,
|
|
|
|
.parent = TYPE_VIRTIO_INPUT_HID,
|
|
|
|
.instance_size = sizeof(VirtIOInputHID),
|
|
|
|
.instance_init = virtio_mouse_init,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static QemuInputHandler virtio_tablet_handler = {
|
|
|
|
.name = VIRTIO_ID_NAME_TABLET,
|
|
|
|
.mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
|
|
|
|
.event = virtio_input_handle_event,
|
|
|
|
.sync = virtio_input_handle_sync,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct virtio_input_config virtio_tablet_config[] = {
|
|
|
|
{
|
|
|
|
.select = VIRTIO_INPUT_CFG_ID_NAME,
|
|
|
|
.size = sizeof(VIRTIO_ID_NAME_TABLET),
|
|
|
|
.u.string = VIRTIO_ID_NAME_TABLET,
|
|
|
|
},{
|
|
|
|
.select = VIRTIO_INPUT_CFG_ID_DEVIDS,
|
|
|
|
.size = sizeof(struct virtio_input_devids),
|
|
|
|
.u.ids = {
|
|
|
|
.bustype = const_le16(BUS_VIRTUAL),
|
|
|
|
.vendor = const_le16(0x0627), /* same we use for usb hid devices */
|
|
|
|
.product = const_le16(0x0003),
|
|
|
|
.version = const_le16(0x0001),
|
|
|
|
},
|
|
|
|
},{
|
|
|
|
.select = VIRTIO_INPUT_CFG_EV_BITS,
|
|
|
|
.subsel = EV_ABS,
|
|
|
|
.size = 1,
|
|
|
|
.u.bitmap = {
|
|
|
|
(1 << ABS_X) | (1 << ABS_Y),
|
|
|
|
},
|
|
|
|
},{
|
|
|
|
.select = VIRTIO_INPUT_CFG_ABS_INFO,
|
|
|
|
.subsel = ABS_X,
|
|
|
|
.size = sizeof(virtio_input_absinfo),
|
2016-04-08 18:21:33 +03:00
|
|
|
.u.abs.max = const_le32(INPUT_EVENT_ABS_SIZE - 1),
|
2014-04-01 12:06:29 +04:00
|
|
|
},{
|
|
|
|
.select = VIRTIO_INPUT_CFG_ABS_INFO,
|
|
|
|
.subsel = ABS_Y,
|
|
|
|
.size = sizeof(virtio_input_absinfo),
|
2016-04-08 18:21:33 +03:00
|
|
|
.u.abs.max = const_le32(INPUT_EVENT_ABS_SIZE - 1),
|
2014-04-01 12:06:29 +04:00
|
|
|
},
|
|
|
|
{ /* end of list */ },
|
|
|
|
};
|
|
|
|
|
|
|
|
static void virtio_tablet_init(Object *obj)
|
|
|
|
{
|
|
|
|
VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
|
|
|
|
VirtIOInput *vinput = VIRTIO_INPUT(obj);
|
|
|
|
|
|
|
|
vhid->handler = &virtio_tablet_handler;
|
|
|
|
virtio_input_init_config(vinput, virtio_tablet_config);
|
|
|
|
virtio_input_key_config(vinput, keymap_button,
|
|
|
|
ARRAY_SIZE(keymap_button));
|
|
|
|
}
|
|
|
|
|
|
|
|
static const TypeInfo virtio_tablet_info = {
|
|
|
|
.name = TYPE_VIRTIO_TABLET,
|
|
|
|
.parent = TYPE_VIRTIO_INPUT_HID,
|
|
|
|
.instance_size = sizeof(VirtIOInputHID),
|
|
|
|
.instance_init = virtio_tablet_init,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static void virtio_register_types(void)
|
|
|
|
{
|
|
|
|
type_register_static(&virtio_input_hid_info);
|
|
|
|
type_register_static(&virtio_keyboard_info);
|
|
|
|
type_register_static(&virtio_mouse_info);
|
|
|
|
type_register_static(&virtio_tablet_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_init(virtio_register_types)
|