xref: /qemu/hw/input/virtio-input-hid.c (revision 944ae6d9f17c3c6609f8d0832311b7a050d6c4b6)
155a1d80aSGerd Hoffmann /*
255a1d80aSGerd Hoffmann  * This work is licensed under the terms of the GNU GPL, version 2 or
355a1d80aSGerd Hoffmann  * (at your option) any later version.  See the COPYING file in the
455a1d80aSGerd Hoffmann  * top-level directory.
555a1d80aSGerd Hoffmann  */
655a1d80aSGerd Hoffmann 
79b8bfe21SPeter Maydell #include "qemu/osdep.h"
855a1d80aSGerd Hoffmann #include "qemu/iov.h"
90b8fa32fSMarkus Armbruster #include "qemu/module.h"
1055a1d80aSGerd Hoffmann 
1155a1d80aSGerd Hoffmann #include "hw/virtio/virtio.h"
12a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
1355a1d80aSGerd Hoffmann #include "hw/virtio/virtio-input.h"
1455a1d80aSGerd Hoffmann 
1555a1d80aSGerd Hoffmann #include "ui/console.h"
1655a1d80aSGerd Hoffmann 
1755a1d80aSGerd Hoffmann #include "standard-headers/linux/input.h"
1855a1d80aSGerd Hoffmann 
1955a1d80aSGerd Hoffmann #define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard"
2055a1d80aSGerd Hoffmann #define VIRTIO_ID_NAME_MOUSE    "QEMU Virtio Mouse"
2155a1d80aSGerd Hoffmann #define VIRTIO_ID_NAME_TABLET   "QEMU Virtio Tablet"
2255a1d80aSGerd Hoffmann 
2355a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
2455a1d80aSGerd Hoffmann 
25ae6b06abSDaniel P. Berrange static const unsigned short keymap_button[INPUT_BUTTON__MAX] = {
2655a1d80aSGerd Hoffmann     [INPUT_BUTTON_LEFT]              = BTN_LEFT,
2755a1d80aSGerd Hoffmann     [INPUT_BUTTON_RIGHT]             = BTN_RIGHT,
2855a1d80aSGerd Hoffmann     [INPUT_BUTTON_MIDDLE]            = BTN_MIDDLE,
29f22d0af0SGerd Hoffmann     [INPUT_BUTTON_WHEEL_UP]          = BTN_GEAR_UP,
30f22d0af0SGerd Hoffmann     [INPUT_BUTTON_WHEEL_DOWN]        = BTN_GEAR_DOWN,
312416760fSMiika S     [INPUT_BUTTON_SIDE]              = BTN_SIDE,
322416760fSMiika S     [INPUT_BUTTON_EXTRA]             = BTN_EXTRA,
3355a1d80aSGerd Hoffmann };
3455a1d80aSGerd Hoffmann 
35ae6b06abSDaniel P. Berrange static const unsigned short axismap_rel[INPUT_AXIS__MAX] = {
3655a1d80aSGerd Hoffmann     [INPUT_AXIS_X]                   = REL_X,
3755a1d80aSGerd Hoffmann     [INPUT_AXIS_Y]                   = REL_Y,
3855a1d80aSGerd Hoffmann };
3955a1d80aSGerd Hoffmann 
40ae6b06abSDaniel P. Berrange static const unsigned short axismap_abs[INPUT_AXIS__MAX] = {
4155a1d80aSGerd Hoffmann     [INPUT_AXIS_X]                   = ABS_X,
4255a1d80aSGerd Hoffmann     [INPUT_AXIS_Y]                   = ABS_Y,
4355a1d80aSGerd Hoffmann };
4455a1d80aSGerd Hoffmann 
4555a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
4655a1d80aSGerd Hoffmann 
47*944ae6d9SSergio Lopez static void virtio_input_extend_config(VirtIOInput *vinput,
48*944ae6d9SSergio Lopez                                        const unsigned short *map,
49*944ae6d9SSergio Lopez                                        size_t mapsize,
50*944ae6d9SSergio Lopez                                        uint8_t select, uint8_t subsel)
5155a1d80aSGerd Hoffmann {
52*944ae6d9SSergio Lopez     virtio_input_config ext;
5355a1d80aSGerd Hoffmann     int i, bit, byte, bmax = 0;
5455a1d80aSGerd Hoffmann 
55*944ae6d9SSergio Lopez     memset(&ext, 0, sizeof(ext));
5655a1d80aSGerd Hoffmann     for (i = 0; i < mapsize; i++) {
57*944ae6d9SSergio Lopez         bit = map[i];
5855a1d80aSGerd Hoffmann         if (!bit) {
5955a1d80aSGerd Hoffmann             continue;
6055a1d80aSGerd Hoffmann         }
6155a1d80aSGerd Hoffmann         byte = bit / 8;
6255a1d80aSGerd Hoffmann         bit  = bit % 8;
63*944ae6d9SSergio Lopez         ext.u.bitmap[byte] |= (1 << bit);
6455a1d80aSGerd Hoffmann         if (bmax < byte+1) {
6555a1d80aSGerd Hoffmann             bmax = byte+1;
6655a1d80aSGerd Hoffmann         }
6755a1d80aSGerd Hoffmann     }
68*944ae6d9SSergio Lopez     ext.select = select;
69*944ae6d9SSergio Lopez     ext.subsel = subsel;
70*944ae6d9SSergio Lopez     ext.size   = bmax;
71*944ae6d9SSergio Lopez     virtio_input_add_config(vinput, &ext);
7255a1d80aSGerd Hoffmann }
7355a1d80aSGerd Hoffmann 
7455a1d80aSGerd Hoffmann static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
7555a1d80aSGerd Hoffmann                                       InputEvent *evt)
7655a1d80aSGerd Hoffmann {
77f4924974SGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
7855a1d80aSGerd Hoffmann     VirtIOInput *vinput = VIRTIO_INPUT(dev);
7955a1d80aSGerd Hoffmann     virtio_input_event event;
8055a1d80aSGerd Hoffmann     int qcode;
81b5a1b443SEric Blake     InputKeyEvent *key;
82b5a1b443SEric Blake     InputMoveEvent *move;
83b5a1b443SEric Blake     InputBtnEvent *btn;
8455a1d80aSGerd Hoffmann 
85568c73a4SEric Blake     switch (evt->type) {
8655a1d80aSGerd Hoffmann     case INPUT_EVENT_KIND_KEY:
8732bafa8fSEric Blake         key = evt->u.key.data;
88b5a1b443SEric Blake         qcode = qemu_input_key_value_to_qcode(key->key);
89ae6b06abSDaniel P. Berrange         if (qcode < qemu_input_map_qcode_to_linux_len &&
90ae6b06abSDaniel P. Berrange             qemu_input_map_qcode_to_linux[qcode]) {
9155a1d80aSGerd Hoffmann             event.type  = cpu_to_le16(EV_KEY);
92ae6b06abSDaniel P. Berrange             event.code  = cpu_to_le16(qemu_input_map_qcode_to_linux[qcode]);
93b5a1b443SEric Blake             event.value = cpu_to_le32(key->down ? 1 : 0);
9455a1d80aSGerd Hoffmann             virtio_input_send(vinput, &event);
9555a1d80aSGerd Hoffmann         } else {
96b5a1b443SEric Blake             if (key->down) {
9755a1d80aSGerd Hoffmann                 fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
98977c736fSMarkus Armbruster                         qcode, QKeyCode_str(qcode));
9955a1d80aSGerd Hoffmann             }
10055a1d80aSGerd Hoffmann         }
10155a1d80aSGerd Hoffmann         break;
10255a1d80aSGerd Hoffmann     case INPUT_EVENT_KIND_BTN:
10332bafa8fSEric Blake         btn = evt->u.btn.data;
104a5f99be4SMiika S         if (vhid->wheel_axis &&
105a5f99be4SMiika S             (btn->button == INPUT_BUTTON_WHEEL_UP ||
106a5f99be4SMiika S              btn->button == INPUT_BUTTON_WHEEL_DOWN) &&
107a5f99be4SMiika S             btn->down) {
108f4924974SGerd Hoffmann             event.type  = cpu_to_le16(EV_REL);
109f4924974SGerd Hoffmann             event.code  = cpu_to_le16(REL_WHEEL);
110f4924974SGerd Hoffmann             event.value = cpu_to_le32(btn->button == INPUT_BUTTON_WHEEL_UP
111f4924974SGerd Hoffmann                                       ? 1 : -1);
112f4924974SGerd Hoffmann             virtio_input_send(vinput, &event);
113f4924974SGerd Hoffmann         } else if (keymap_button[btn->button]) {
11455a1d80aSGerd Hoffmann             event.type  = cpu_to_le16(EV_KEY);
115b5a1b443SEric Blake             event.code  = cpu_to_le16(keymap_button[btn->button]);
116b5a1b443SEric Blake             event.value = cpu_to_le32(btn->down ? 1 : 0);
11755a1d80aSGerd Hoffmann             virtio_input_send(vinput, &event);
11855a1d80aSGerd Hoffmann         } else {
119b5a1b443SEric Blake             if (btn->down) {
12055a1d80aSGerd Hoffmann                 fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
121b5a1b443SEric Blake                         btn->button,
122977c736fSMarkus Armbruster                         InputButton_str(btn->button));
12355a1d80aSGerd Hoffmann             }
12455a1d80aSGerd Hoffmann         }
12555a1d80aSGerd Hoffmann         break;
12655a1d80aSGerd Hoffmann     case INPUT_EVENT_KIND_REL:
12732bafa8fSEric Blake         move = evt->u.rel.data;
12855a1d80aSGerd Hoffmann         event.type  = cpu_to_le16(EV_REL);
129b5a1b443SEric Blake         event.code  = cpu_to_le16(axismap_rel[move->axis]);
130b5a1b443SEric Blake         event.value = cpu_to_le32(move->value);
13155a1d80aSGerd Hoffmann         virtio_input_send(vinput, &event);
13255a1d80aSGerd Hoffmann         break;
13355a1d80aSGerd Hoffmann     case INPUT_EVENT_KIND_ABS:
13432bafa8fSEric Blake         move = evt->u.abs.data;
13555a1d80aSGerd Hoffmann         event.type  = cpu_to_le16(EV_ABS);
136b5a1b443SEric Blake         event.code  = cpu_to_le16(axismap_abs[move->axis]);
137b5a1b443SEric Blake         event.value = cpu_to_le32(move->value);
13855a1d80aSGerd Hoffmann         virtio_input_send(vinput, &event);
13955a1d80aSGerd Hoffmann         break;
14055a1d80aSGerd Hoffmann     default:
14155a1d80aSGerd Hoffmann         /* keep gcc happy */
14255a1d80aSGerd Hoffmann         break;
14355a1d80aSGerd Hoffmann     }
14455a1d80aSGerd Hoffmann }
14555a1d80aSGerd Hoffmann 
14655a1d80aSGerd Hoffmann static void virtio_input_handle_sync(DeviceState *dev)
14755a1d80aSGerd Hoffmann {
14855a1d80aSGerd Hoffmann     VirtIOInput *vinput = VIRTIO_INPUT(dev);
14955a1d80aSGerd Hoffmann     virtio_input_event event = {
15055a1d80aSGerd Hoffmann         .type  = cpu_to_le16(EV_SYN),
15155a1d80aSGerd Hoffmann         .code  = cpu_to_le16(SYN_REPORT),
15255a1d80aSGerd Hoffmann         .value = 0,
15355a1d80aSGerd Hoffmann     };
15455a1d80aSGerd Hoffmann 
15555a1d80aSGerd Hoffmann     virtio_input_send(vinput, &event);
15655a1d80aSGerd Hoffmann }
15755a1d80aSGerd Hoffmann 
15855a1d80aSGerd Hoffmann static void virtio_input_hid_realize(DeviceState *dev, Error **errp)
15955a1d80aSGerd Hoffmann {
16055a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
1615cce1733SGerd Hoffmann 
16255a1d80aSGerd Hoffmann     vhid->hs = qemu_input_handler_register(dev, vhid->handler);
1635cce1733SGerd Hoffmann     if (vhid->display && vhid->hs) {
1645cce1733SGerd Hoffmann         qemu_input_handler_bind(vhid->hs, vhid->display, vhid->head, NULL);
1655cce1733SGerd Hoffmann     }
16655a1d80aSGerd Hoffmann }
16755a1d80aSGerd Hoffmann 
168b69c3c21SMarkus Armbruster static void virtio_input_hid_unrealize(DeviceState *dev)
16955a1d80aSGerd Hoffmann {
17055a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
17155a1d80aSGerd Hoffmann     qemu_input_handler_unregister(vhid->hs);
17255a1d80aSGerd Hoffmann }
17355a1d80aSGerd Hoffmann 
17455a1d80aSGerd Hoffmann static void virtio_input_hid_change_active(VirtIOInput *vinput)
17555a1d80aSGerd Hoffmann {
17655a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
17755a1d80aSGerd Hoffmann 
17855a1d80aSGerd Hoffmann     if (vinput->active) {
17955a1d80aSGerd Hoffmann         qemu_input_handler_activate(vhid->hs);
18055a1d80aSGerd Hoffmann     } else {
18155a1d80aSGerd Hoffmann         qemu_input_handler_deactivate(vhid->hs);
18255a1d80aSGerd Hoffmann     }
18355a1d80aSGerd Hoffmann }
18455a1d80aSGerd Hoffmann 
18555a1d80aSGerd Hoffmann static void virtio_input_hid_handle_status(VirtIOInput *vinput,
18655a1d80aSGerd Hoffmann                                            virtio_input_event *event)
18755a1d80aSGerd Hoffmann {
18855a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
18955a1d80aSGerd Hoffmann     int ledbit = 0;
19055a1d80aSGerd Hoffmann 
19155a1d80aSGerd Hoffmann     switch (le16_to_cpu(event->type)) {
19255a1d80aSGerd Hoffmann     case EV_LED:
19355a1d80aSGerd Hoffmann         if (event->code == LED_NUML) {
19455a1d80aSGerd Hoffmann             ledbit = QEMU_NUM_LOCK_LED;
19555a1d80aSGerd Hoffmann         } else if (event->code == LED_CAPSL) {
19655a1d80aSGerd Hoffmann             ledbit = QEMU_CAPS_LOCK_LED;
19755a1d80aSGerd Hoffmann         } else if (event->code == LED_SCROLLL) {
19855a1d80aSGerd Hoffmann             ledbit = QEMU_SCROLL_LOCK_LED;
19955a1d80aSGerd Hoffmann         }
20055a1d80aSGerd Hoffmann         if (event->value) {
20155a1d80aSGerd Hoffmann             vhid->ledstate |= ledbit;
20255a1d80aSGerd Hoffmann         } else {
20355a1d80aSGerd Hoffmann             vhid->ledstate &= ~ledbit;
20455a1d80aSGerd Hoffmann         }
20555a1d80aSGerd Hoffmann         kbd_put_ledstate(vhid->ledstate);
20655a1d80aSGerd Hoffmann         break;
20755a1d80aSGerd Hoffmann     default:
20855a1d80aSGerd Hoffmann         fprintf(stderr, "%s: unknown type %d\n", __func__,
20955a1d80aSGerd Hoffmann                 le16_to_cpu(event->type));
21055a1d80aSGerd Hoffmann         break;
21155a1d80aSGerd Hoffmann     }
21255a1d80aSGerd Hoffmann }
21355a1d80aSGerd Hoffmann 
2145cce1733SGerd Hoffmann static Property virtio_input_hid_properties[] = {
2155cce1733SGerd Hoffmann     DEFINE_PROP_STRING("display", VirtIOInputHID, display),
2165cce1733SGerd Hoffmann     DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0),
2172a19b229SLin Ma     DEFINE_PROP_END_OF_LIST(),
2185cce1733SGerd Hoffmann };
2195cce1733SGerd Hoffmann 
22055a1d80aSGerd Hoffmann static void virtio_input_hid_class_init(ObjectClass *klass, void *data)
22155a1d80aSGerd Hoffmann {
2225cce1733SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
22355a1d80aSGerd Hoffmann     VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
22455a1d80aSGerd Hoffmann 
2254f67d30bSMarc-André Lureau     device_class_set_props(dc, virtio_input_hid_properties);
22655a1d80aSGerd Hoffmann     vic->realize       = virtio_input_hid_realize;
22755a1d80aSGerd Hoffmann     vic->unrealize     = virtio_input_hid_unrealize;
22855a1d80aSGerd Hoffmann     vic->change_active = virtio_input_hid_change_active;
22955a1d80aSGerd Hoffmann     vic->handle_status = virtio_input_hid_handle_status;
23055a1d80aSGerd Hoffmann }
23155a1d80aSGerd Hoffmann 
23255a1d80aSGerd Hoffmann static const TypeInfo virtio_input_hid_info = {
23355a1d80aSGerd Hoffmann     .name          = TYPE_VIRTIO_INPUT_HID,
23455a1d80aSGerd Hoffmann     .parent        = TYPE_VIRTIO_INPUT,
23555a1d80aSGerd Hoffmann     .instance_size = sizeof(VirtIOInputHID),
23655a1d80aSGerd Hoffmann     .class_init    = virtio_input_hid_class_init,
23755a1d80aSGerd Hoffmann     .abstract      = true,
23855a1d80aSGerd Hoffmann };
23955a1d80aSGerd Hoffmann 
24055a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
24155a1d80aSGerd Hoffmann 
24255a1d80aSGerd Hoffmann static QemuInputHandler virtio_keyboard_handler = {
24355a1d80aSGerd Hoffmann     .name  = VIRTIO_ID_NAME_KEYBOARD,
24455a1d80aSGerd Hoffmann     .mask  = INPUT_EVENT_MASK_KEY,
24555a1d80aSGerd Hoffmann     .event = virtio_input_handle_event,
24655a1d80aSGerd Hoffmann     .sync  = virtio_input_handle_sync,
24755a1d80aSGerd Hoffmann };
24855a1d80aSGerd Hoffmann 
24955a1d80aSGerd Hoffmann static struct virtio_input_config virtio_keyboard_config[] = {
25055a1d80aSGerd Hoffmann     {
25155a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_NAME,
25255a1d80aSGerd Hoffmann         .size      = sizeof(VIRTIO_ID_NAME_KEYBOARD),
25355a1d80aSGerd Hoffmann         .u.string  = VIRTIO_ID_NAME_KEYBOARD,
25455a1d80aSGerd Hoffmann     },{
25555a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
25655a1d80aSGerd Hoffmann         .size      = sizeof(struct virtio_input_devids),
25755a1d80aSGerd Hoffmann         .u.ids     = {
25855a1d80aSGerd Hoffmann             .bustype = const_le16(BUS_VIRTUAL),
25955a1d80aSGerd Hoffmann             .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
26055a1d80aSGerd Hoffmann             .product = const_le16(0x0001),
26155a1d80aSGerd Hoffmann             .version = const_le16(0x0001),
26255a1d80aSGerd Hoffmann         },
26355a1d80aSGerd Hoffmann     },{
26455a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
26555a1d80aSGerd Hoffmann         .subsel    = EV_REP,
26655a1d80aSGerd Hoffmann         .size      = 1,
26755a1d80aSGerd Hoffmann     },{
26855a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
26955a1d80aSGerd Hoffmann         .subsel    = EV_LED,
27055a1d80aSGerd Hoffmann         .size      = 1,
27155a1d80aSGerd Hoffmann         .u.bitmap  = {
27255a1d80aSGerd Hoffmann             (1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL),
27355a1d80aSGerd Hoffmann         },
27455a1d80aSGerd Hoffmann     },
27555a1d80aSGerd Hoffmann     { /* end of list */ },
27655a1d80aSGerd Hoffmann };
27755a1d80aSGerd Hoffmann 
27855a1d80aSGerd Hoffmann static void virtio_keyboard_init(Object *obj)
27955a1d80aSGerd Hoffmann {
28055a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
28155a1d80aSGerd Hoffmann     VirtIOInput *vinput = VIRTIO_INPUT(obj);
28255a1d80aSGerd Hoffmann 
28355a1d80aSGerd Hoffmann     vhid->handler = &virtio_keyboard_handler;
28455a1d80aSGerd Hoffmann     virtio_input_init_config(vinput, virtio_keyboard_config);
285*944ae6d9SSergio Lopez     virtio_input_extend_config(vinput, qemu_input_map_qcode_to_linux,
286*944ae6d9SSergio Lopez                                qemu_input_map_qcode_to_linux_len,
287*944ae6d9SSergio Lopez                                VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
28855a1d80aSGerd Hoffmann }
28955a1d80aSGerd Hoffmann 
29055a1d80aSGerd Hoffmann static const TypeInfo virtio_keyboard_info = {
29155a1d80aSGerd Hoffmann     .name          = TYPE_VIRTIO_KEYBOARD,
29255a1d80aSGerd Hoffmann     .parent        = TYPE_VIRTIO_INPUT_HID,
29355a1d80aSGerd Hoffmann     .instance_size = sizeof(VirtIOInputHID),
29455a1d80aSGerd Hoffmann     .instance_init = virtio_keyboard_init,
29555a1d80aSGerd Hoffmann };
29655a1d80aSGerd Hoffmann 
29755a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
29855a1d80aSGerd Hoffmann 
29955a1d80aSGerd Hoffmann static QemuInputHandler virtio_mouse_handler = {
30055a1d80aSGerd Hoffmann     .name  = VIRTIO_ID_NAME_MOUSE,
30155a1d80aSGerd Hoffmann     .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
30255a1d80aSGerd Hoffmann     .event = virtio_input_handle_event,
30355a1d80aSGerd Hoffmann     .sync  = virtio_input_handle_sync,
30455a1d80aSGerd Hoffmann };
30555a1d80aSGerd Hoffmann 
306f4924974SGerd Hoffmann static struct virtio_input_config virtio_mouse_config_v1[] = {
30755a1d80aSGerd Hoffmann     {
30855a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_NAME,
30955a1d80aSGerd Hoffmann         .size      = sizeof(VIRTIO_ID_NAME_MOUSE),
31055a1d80aSGerd Hoffmann         .u.string  = VIRTIO_ID_NAME_MOUSE,
31155a1d80aSGerd Hoffmann     },{
31255a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
31355a1d80aSGerd Hoffmann         .size      = sizeof(struct virtio_input_devids),
31455a1d80aSGerd Hoffmann         .u.ids     = {
31555a1d80aSGerd Hoffmann             .bustype = const_le16(BUS_VIRTUAL),
31655a1d80aSGerd Hoffmann             .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
31755a1d80aSGerd Hoffmann             .product = const_le16(0x0002),
31855a1d80aSGerd Hoffmann             .version = const_le16(0x0001),
31955a1d80aSGerd Hoffmann         },
32055a1d80aSGerd Hoffmann     },{
32155a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
32255a1d80aSGerd Hoffmann         .subsel    = EV_REL,
32355a1d80aSGerd Hoffmann         .size      = 1,
32455a1d80aSGerd Hoffmann         .u.bitmap  = {
32555a1d80aSGerd Hoffmann             (1 << REL_X) | (1 << REL_Y),
32655a1d80aSGerd Hoffmann         },
32755a1d80aSGerd Hoffmann     },
32855a1d80aSGerd Hoffmann     { /* end of list */ },
32955a1d80aSGerd Hoffmann };
33055a1d80aSGerd Hoffmann 
331f4924974SGerd Hoffmann static struct virtio_input_config virtio_mouse_config_v2[] = {
332f4924974SGerd Hoffmann     {
333f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_NAME,
334f4924974SGerd Hoffmann         .size      = sizeof(VIRTIO_ID_NAME_MOUSE),
335f4924974SGerd Hoffmann         .u.string  = VIRTIO_ID_NAME_MOUSE,
336f4924974SGerd Hoffmann     },{
337f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
338f4924974SGerd Hoffmann         .size      = sizeof(struct virtio_input_devids),
339f4924974SGerd Hoffmann         .u.ids     = {
340f4924974SGerd Hoffmann             .bustype = const_le16(BUS_VIRTUAL),
341f4924974SGerd Hoffmann             .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
342f4924974SGerd Hoffmann             .product = const_le16(0x0002),
343f4924974SGerd Hoffmann             .version = const_le16(0x0002),
344f4924974SGerd Hoffmann         },
345f4924974SGerd Hoffmann     },{
346f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
347f4924974SGerd Hoffmann         .subsel    = EV_REL,
348f4924974SGerd Hoffmann         .size      = 2,
349f4924974SGerd Hoffmann         .u.bitmap  = {
350f4924974SGerd Hoffmann             (1 << REL_X) | (1 << REL_Y),
351f4924974SGerd Hoffmann             (1 << (REL_WHEEL - 8))
352f4924974SGerd Hoffmann         },
353f4924974SGerd Hoffmann     },
354f4924974SGerd Hoffmann     { /* end of list */ },
355f4924974SGerd Hoffmann };
356f4924974SGerd Hoffmann 
357f4924974SGerd Hoffmann static Property virtio_mouse_properties[] = {
358f4924974SGerd Hoffmann     DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
359f4924974SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
360f4924974SGerd Hoffmann };
361f4924974SGerd Hoffmann 
362f4924974SGerd Hoffmann static void virtio_mouse_class_init(ObjectClass *klass, void *data)
363f4924974SGerd Hoffmann {
364f4924974SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
365f4924974SGerd Hoffmann 
3664f67d30bSMarc-André Lureau     device_class_set_props(dc, virtio_mouse_properties);
367f4924974SGerd Hoffmann }
368f4924974SGerd Hoffmann 
36955a1d80aSGerd Hoffmann static void virtio_mouse_init(Object *obj)
37055a1d80aSGerd Hoffmann {
37155a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
37255a1d80aSGerd Hoffmann     VirtIOInput *vinput = VIRTIO_INPUT(obj);
37355a1d80aSGerd Hoffmann 
37455a1d80aSGerd Hoffmann     vhid->handler = &virtio_mouse_handler;
375f4924974SGerd Hoffmann     virtio_input_init_config(vinput, vhid->wheel_axis
376f4924974SGerd Hoffmann                              ? virtio_mouse_config_v2
377f4924974SGerd Hoffmann                              : virtio_mouse_config_v1);
378*944ae6d9SSergio Lopez     virtio_input_extend_config(vinput, keymap_button,
379*944ae6d9SSergio Lopez                                ARRAY_SIZE(keymap_button),
380*944ae6d9SSergio Lopez                                VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
38155a1d80aSGerd Hoffmann }
38255a1d80aSGerd Hoffmann 
38355a1d80aSGerd Hoffmann static const TypeInfo virtio_mouse_info = {
38455a1d80aSGerd Hoffmann     .name          = TYPE_VIRTIO_MOUSE,
38555a1d80aSGerd Hoffmann     .parent        = TYPE_VIRTIO_INPUT_HID,
38655a1d80aSGerd Hoffmann     .instance_size = sizeof(VirtIOInputHID),
38755a1d80aSGerd Hoffmann     .instance_init = virtio_mouse_init,
388f4924974SGerd Hoffmann     .class_init    = virtio_mouse_class_init,
38955a1d80aSGerd Hoffmann };
39055a1d80aSGerd Hoffmann 
39155a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
39255a1d80aSGerd Hoffmann 
39355a1d80aSGerd Hoffmann static QemuInputHandler virtio_tablet_handler = {
39455a1d80aSGerd Hoffmann     .name  = VIRTIO_ID_NAME_TABLET,
39555a1d80aSGerd Hoffmann     .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
39655a1d80aSGerd Hoffmann     .event = virtio_input_handle_event,
39755a1d80aSGerd Hoffmann     .sync  = virtio_input_handle_sync,
39855a1d80aSGerd Hoffmann };
39955a1d80aSGerd Hoffmann 
400f4924974SGerd Hoffmann static struct virtio_input_config virtio_tablet_config_v1[] = {
40155a1d80aSGerd Hoffmann     {
40255a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_NAME,
40355a1d80aSGerd Hoffmann         .size      = sizeof(VIRTIO_ID_NAME_TABLET),
40455a1d80aSGerd Hoffmann         .u.string  = VIRTIO_ID_NAME_TABLET,
40555a1d80aSGerd Hoffmann     },{
40655a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
40755a1d80aSGerd Hoffmann         .size      = sizeof(struct virtio_input_devids),
40855a1d80aSGerd Hoffmann         .u.ids     = {
40955a1d80aSGerd Hoffmann             .bustype = const_le16(BUS_VIRTUAL),
41055a1d80aSGerd Hoffmann             .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
41155a1d80aSGerd Hoffmann             .product = const_le16(0x0003),
41255a1d80aSGerd Hoffmann             .version = const_le16(0x0001),
41355a1d80aSGerd Hoffmann         },
41455a1d80aSGerd Hoffmann     },{
41555a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
41655a1d80aSGerd Hoffmann         .subsel    = EV_ABS,
41755a1d80aSGerd Hoffmann         .size      = 1,
41855a1d80aSGerd Hoffmann         .u.bitmap  = {
41955a1d80aSGerd Hoffmann             (1 << ABS_X) | (1 << ABS_Y),
42055a1d80aSGerd Hoffmann         },
42155a1d80aSGerd Hoffmann     },{
42255a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ABS_INFO,
42355a1d80aSGerd Hoffmann         .subsel    = ABS_X,
42455a1d80aSGerd Hoffmann         .size      = sizeof(virtio_input_absinfo),
4259cfa7ab9SPhilippe Voinov         .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
4269cfa7ab9SPhilippe Voinov         .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
42755a1d80aSGerd Hoffmann     },{
42855a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ABS_INFO,
42955a1d80aSGerd Hoffmann         .subsel    = ABS_Y,
43055a1d80aSGerd Hoffmann         .size      = sizeof(virtio_input_absinfo),
4319cfa7ab9SPhilippe Voinov         .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
4329cfa7ab9SPhilippe Voinov         .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
43355a1d80aSGerd Hoffmann     },
43455a1d80aSGerd Hoffmann     { /* end of list */ },
43555a1d80aSGerd Hoffmann };
43655a1d80aSGerd Hoffmann 
437f4924974SGerd Hoffmann static struct virtio_input_config virtio_tablet_config_v2[] = {
438f4924974SGerd Hoffmann     {
439f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_NAME,
440f4924974SGerd Hoffmann         .size      = sizeof(VIRTIO_ID_NAME_TABLET),
441f4924974SGerd Hoffmann         .u.string  = VIRTIO_ID_NAME_TABLET,
442f4924974SGerd Hoffmann     },{
443f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
444f4924974SGerd Hoffmann         .size      = sizeof(struct virtio_input_devids),
445f4924974SGerd Hoffmann         .u.ids     = {
446f4924974SGerd Hoffmann             .bustype = const_le16(BUS_VIRTUAL),
447f4924974SGerd Hoffmann             .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
448f4924974SGerd Hoffmann             .product = const_le16(0x0003),
449f4924974SGerd Hoffmann             .version = const_le16(0x0002),
450f4924974SGerd Hoffmann         },
451f4924974SGerd Hoffmann     },{
452f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
453f4924974SGerd Hoffmann         .subsel    = EV_ABS,
454f4924974SGerd Hoffmann         .size      = 1,
455f4924974SGerd Hoffmann         .u.bitmap  = {
456f4924974SGerd Hoffmann             (1 << ABS_X) | (1 << ABS_Y),
457f4924974SGerd Hoffmann         },
458f4924974SGerd Hoffmann     },{
459f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
460f4924974SGerd Hoffmann         .subsel    = EV_REL,
461f4924974SGerd Hoffmann         .size      = 2,
462f4924974SGerd Hoffmann         .u.bitmap  = {
463f4924974SGerd Hoffmann             0,
464f4924974SGerd Hoffmann             (1 << (REL_WHEEL - 8))
465f4924974SGerd Hoffmann         },
466f4924974SGerd Hoffmann     },{
467f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ABS_INFO,
468f4924974SGerd Hoffmann         .subsel    = ABS_X,
469f4924974SGerd Hoffmann         .size      = sizeof(virtio_input_absinfo),
470f4924974SGerd Hoffmann         .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
471f4924974SGerd Hoffmann         .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
472f4924974SGerd Hoffmann     },{
473f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ABS_INFO,
474f4924974SGerd Hoffmann         .subsel    = ABS_Y,
475f4924974SGerd Hoffmann         .size      = sizeof(virtio_input_absinfo),
476f4924974SGerd Hoffmann         .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
477f4924974SGerd Hoffmann         .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
478f4924974SGerd Hoffmann     },
479f4924974SGerd Hoffmann     { /* end of list */ },
480f4924974SGerd Hoffmann };
481f4924974SGerd Hoffmann 
482f4924974SGerd Hoffmann static Property virtio_tablet_properties[] = {
483f4924974SGerd Hoffmann     DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
484f4924974SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
485f4924974SGerd Hoffmann };
486f4924974SGerd Hoffmann 
487f4924974SGerd Hoffmann static void virtio_tablet_class_init(ObjectClass *klass, void *data)
488f4924974SGerd Hoffmann {
489f4924974SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
490f4924974SGerd Hoffmann 
4914f67d30bSMarc-André Lureau     device_class_set_props(dc, virtio_tablet_properties);
492f4924974SGerd Hoffmann }
493f4924974SGerd Hoffmann 
49455a1d80aSGerd Hoffmann static void virtio_tablet_init(Object *obj)
49555a1d80aSGerd Hoffmann {
49655a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
49755a1d80aSGerd Hoffmann     VirtIOInput *vinput = VIRTIO_INPUT(obj);
49855a1d80aSGerd Hoffmann 
49955a1d80aSGerd Hoffmann     vhid->handler = &virtio_tablet_handler;
500f4924974SGerd Hoffmann     virtio_input_init_config(vinput, vhid->wheel_axis
501f4924974SGerd Hoffmann                              ? virtio_tablet_config_v2
502f4924974SGerd Hoffmann                              : virtio_tablet_config_v1);
503*944ae6d9SSergio Lopez     virtio_input_extend_config(vinput, keymap_button,
504*944ae6d9SSergio Lopez                                ARRAY_SIZE(keymap_button),
505*944ae6d9SSergio Lopez                                VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
50655a1d80aSGerd Hoffmann }
50755a1d80aSGerd Hoffmann 
50855a1d80aSGerd Hoffmann static const TypeInfo virtio_tablet_info = {
50955a1d80aSGerd Hoffmann     .name          = TYPE_VIRTIO_TABLET,
51055a1d80aSGerd Hoffmann     .parent        = TYPE_VIRTIO_INPUT_HID,
51155a1d80aSGerd Hoffmann     .instance_size = sizeof(VirtIOInputHID),
51255a1d80aSGerd Hoffmann     .instance_init = virtio_tablet_init,
513f4924974SGerd Hoffmann     .class_init    = virtio_tablet_class_init,
51455a1d80aSGerd Hoffmann };
51555a1d80aSGerd Hoffmann 
51655a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
51755a1d80aSGerd Hoffmann 
51855a1d80aSGerd Hoffmann static void virtio_register_types(void)
51955a1d80aSGerd Hoffmann {
52055a1d80aSGerd Hoffmann     type_register_static(&virtio_input_hid_info);
52155a1d80aSGerd Hoffmann     type_register_static(&virtio_keyboard_info);
52255a1d80aSGerd Hoffmann     type_register_static(&virtio_mouse_info);
52355a1d80aSGerd Hoffmann     type_register_static(&virtio_tablet_info);
52455a1d80aSGerd Hoffmann }
52555a1d80aSGerd Hoffmann 
52655a1d80aSGerd Hoffmann type_init(virtio_register_types)
527