xref: /qemu/hw/input/virtio-input-hid.c (revision ae6b06ab655b21c19b234ce3422f694d11a013e0)
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"
955a1d80aSGerd Hoffmann 
1055a1d80aSGerd Hoffmann #include "hw/qdev.h"
1155a1d80aSGerd Hoffmann #include "hw/virtio/virtio.h"
1255a1d80aSGerd Hoffmann #include "hw/virtio/virtio-input.h"
1355a1d80aSGerd Hoffmann 
1455a1d80aSGerd Hoffmann #undef CONFIG_CURSES
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 
25*ae6b06abSDaniel 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 
35*ae6b06abSDaniel 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 
40*ae6b06abSDaniel 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 
4755a1d80aSGerd Hoffmann static void virtio_input_key_config(VirtIOInput *vinput,
48*ae6b06abSDaniel P. Berrange                                     const unsigned short *keymap,
4955a1d80aSGerd Hoffmann                                     size_t mapsize)
5055a1d80aSGerd Hoffmann {
5155a1d80aSGerd Hoffmann     virtio_input_config keys;
5255a1d80aSGerd Hoffmann     int i, bit, byte, bmax = 0;
5355a1d80aSGerd Hoffmann 
5455a1d80aSGerd Hoffmann     memset(&keys, 0, sizeof(keys));
5555a1d80aSGerd Hoffmann     for (i = 0; i < mapsize; i++) {
5655a1d80aSGerd Hoffmann         bit = keymap[i];
5755a1d80aSGerd Hoffmann         if (!bit) {
5855a1d80aSGerd Hoffmann             continue;
5955a1d80aSGerd Hoffmann         }
6055a1d80aSGerd Hoffmann         byte = bit / 8;
6155a1d80aSGerd Hoffmann         bit  = bit % 8;
6255a1d80aSGerd Hoffmann         keys.u.bitmap[byte] |= (1 << bit);
6355a1d80aSGerd Hoffmann         if (bmax < byte+1) {
6455a1d80aSGerd Hoffmann             bmax = byte+1;
6555a1d80aSGerd Hoffmann         }
6655a1d80aSGerd Hoffmann     }
6755a1d80aSGerd Hoffmann     keys.select = VIRTIO_INPUT_CFG_EV_BITS;
6855a1d80aSGerd Hoffmann     keys.subsel = EV_KEY;
6955a1d80aSGerd Hoffmann     keys.size   = bmax;
7055a1d80aSGerd Hoffmann     virtio_input_add_config(vinput, &keys);
7155a1d80aSGerd Hoffmann }
7255a1d80aSGerd Hoffmann 
7355a1d80aSGerd Hoffmann static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
7455a1d80aSGerd Hoffmann                                       InputEvent *evt)
7555a1d80aSGerd Hoffmann {
76f4924974SGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
7755a1d80aSGerd Hoffmann     VirtIOInput *vinput = VIRTIO_INPUT(dev);
7855a1d80aSGerd Hoffmann     virtio_input_event event;
7955a1d80aSGerd Hoffmann     int qcode;
80b5a1b443SEric Blake     InputKeyEvent *key;
81b5a1b443SEric Blake     InputMoveEvent *move;
82b5a1b443SEric Blake     InputBtnEvent *btn;
8355a1d80aSGerd Hoffmann 
84568c73a4SEric Blake     switch (evt->type) {
8555a1d80aSGerd Hoffmann     case INPUT_EVENT_KIND_KEY:
8632bafa8fSEric Blake         key = evt->u.key.data;
87b5a1b443SEric Blake         qcode = qemu_input_key_value_to_qcode(key->key);
88*ae6b06abSDaniel P. Berrange         if (qcode < qemu_input_map_qcode_to_linux_len &&
89*ae6b06abSDaniel P. Berrange             qemu_input_map_qcode_to_linux[qcode]) {
9055a1d80aSGerd Hoffmann             event.type  = cpu_to_le16(EV_KEY);
91*ae6b06abSDaniel P. Berrange             event.code  = cpu_to_le16(qemu_input_map_qcode_to_linux[qcode]);
92b5a1b443SEric Blake             event.value = cpu_to_le32(key->down ? 1 : 0);
9355a1d80aSGerd Hoffmann             virtio_input_send(vinput, &event);
9455a1d80aSGerd Hoffmann         } else {
95b5a1b443SEric Blake             if (key->down) {
9655a1d80aSGerd Hoffmann                 fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
97977c736fSMarkus Armbruster                         qcode, QKeyCode_str(qcode));
9855a1d80aSGerd Hoffmann             }
9955a1d80aSGerd Hoffmann         }
10055a1d80aSGerd Hoffmann         break;
10155a1d80aSGerd Hoffmann     case INPUT_EVENT_KIND_BTN:
10232bafa8fSEric Blake         btn = evt->u.btn.data;
103a5f99be4SMiika S         if (vhid->wheel_axis &&
104a5f99be4SMiika S             (btn->button == INPUT_BUTTON_WHEEL_UP ||
105a5f99be4SMiika S              btn->button == INPUT_BUTTON_WHEEL_DOWN) &&
106a5f99be4SMiika S             btn->down) {
107f4924974SGerd Hoffmann             event.type  = cpu_to_le16(EV_REL);
108f4924974SGerd Hoffmann             event.code  = cpu_to_le16(REL_WHEEL);
109f4924974SGerd Hoffmann             event.value = cpu_to_le32(btn->button == INPUT_BUTTON_WHEEL_UP
110f4924974SGerd Hoffmann                                       ? 1 : -1);
111f4924974SGerd Hoffmann             virtio_input_send(vinput, &event);
112f4924974SGerd Hoffmann         } else if (keymap_button[btn->button]) {
11355a1d80aSGerd Hoffmann             event.type  = cpu_to_le16(EV_KEY);
114b5a1b443SEric Blake             event.code  = cpu_to_le16(keymap_button[btn->button]);
115b5a1b443SEric Blake             event.value = cpu_to_le32(btn->down ? 1 : 0);
11655a1d80aSGerd Hoffmann             virtio_input_send(vinput, &event);
11755a1d80aSGerd Hoffmann         } else {
118b5a1b443SEric Blake             if (btn->down) {
11955a1d80aSGerd Hoffmann                 fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
120b5a1b443SEric Blake                         btn->button,
121977c736fSMarkus Armbruster                         InputButton_str(btn->button));
12255a1d80aSGerd Hoffmann             }
12355a1d80aSGerd Hoffmann         }
12455a1d80aSGerd Hoffmann         break;
12555a1d80aSGerd Hoffmann     case INPUT_EVENT_KIND_REL:
12632bafa8fSEric Blake         move = evt->u.rel.data;
12755a1d80aSGerd Hoffmann         event.type  = cpu_to_le16(EV_REL);
128b5a1b443SEric Blake         event.code  = cpu_to_le16(axismap_rel[move->axis]);
129b5a1b443SEric Blake         event.value = cpu_to_le32(move->value);
13055a1d80aSGerd Hoffmann         virtio_input_send(vinput, &event);
13155a1d80aSGerd Hoffmann         break;
13255a1d80aSGerd Hoffmann     case INPUT_EVENT_KIND_ABS:
13332bafa8fSEric Blake         move = evt->u.abs.data;
13455a1d80aSGerd Hoffmann         event.type  = cpu_to_le16(EV_ABS);
135b5a1b443SEric Blake         event.code  = cpu_to_le16(axismap_abs[move->axis]);
136b5a1b443SEric Blake         event.value = cpu_to_le32(move->value);
13755a1d80aSGerd Hoffmann         virtio_input_send(vinput, &event);
13855a1d80aSGerd Hoffmann         break;
13955a1d80aSGerd Hoffmann     default:
14055a1d80aSGerd Hoffmann         /* keep gcc happy */
14155a1d80aSGerd Hoffmann         break;
14255a1d80aSGerd Hoffmann     }
14355a1d80aSGerd Hoffmann }
14455a1d80aSGerd Hoffmann 
14555a1d80aSGerd Hoffmann static void virtio_input_handle_sync(DeviceState *dev)
14655a1d80aSGerd Hoffmann {
14755a1d80aSGerd Hoffmann     VirtIOInput *vinput = VIRTIO_INPUT(dev);
14855a1d80aSGerd Hoffmann     virtio_input_event event = {
14955a1d80aSGerd Hoffmann         .type  = cpu_to_le16(EV_SYN),
15055a1d80aSGerd Hoffmann         .code  = cpu_to_le16(SYN_REPORT),
15155a1d80aSGerd Hoffmann         .value = 0,
15255a1d80aSGerd Hoffmann     };
15355a1d80aSGerd Hoffmann 
15455a1d80aSGerd Hoffmann     virtio_input_send(vinput, &event);
15555a1d80aSGerd Hoffmann }
15655a1d80aSGerd Hoffmann 
15755a1d80aSGerd Hoffmann static void virtio_input_hid_realize(DeviceState *dev, Error **errp)
15855a1d80aSGerd Hoffmann {
15955a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
1605cce1733SGerd Hoffmann 
16155a1d80aSGerd Hoffmann     vhid->hs = qemu_input_handler_register(dev, vhid->handler);
1625cce1733SGerd Hoffmann     if (vhid->display && vhid->hs) {
1635cce1733SGerd Hoffmann         qemu_input_handler_bind(vhid->hs, vhid->display, vhid->head, NULL);
1645cce1733SGerd Hoffmann     }
16555a1d80aSGerd Hoffmann }
16655a1d80aSGerd Hoffmann 
16755a1d80aSGerd Hoffmann static void virtio_input_hid_unrealize(DeviceState *dev, Error **errp)
16855a1d80aSGerd Hoffmann {
16955a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
17055a1d80aSGerd Hoffmann     qemu_input_handler_unregister(vhid->hs);
17155a1d80aSGerd Hoffmann }
17255a1d80aSGerd Hoffmann 
17355a1d80aSGerd Hoffmann static void virtio_input_hid_change_active(VirtIOInput *vinput)
17455a1d80aSGerd Hoffmann {
17555a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
17655a1d80aSGerd Hoffmann 
17755a1d80aSGerd Hoffmann     if (vinput->active) {
17855a1d80aSGerd Hoffmann         qemu_input_handler_activate(vhid->hs);
17955a1d80aSGerd Hoffmann     } else {
18055a1d80aSGerd Hoffmann         qemu_input_handler_deactivate(vhid->hs);
18155a1d80aSGerd Hoffmann     }
18255a1d80aSGerd Hoffmann }
18355a1d80aSGerd Hoffmann 
18455a1d80aSGerd Hoffmann static void virtio_input_hid_handle_status(VirtIOInput *vinput,
18555a1d80aSGerd Hoffmann                                            virtio_input_event *event)
18655a1d80aSGerd Hoffmann {
18755a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
18855a1d80aSGerd Hoffmann     int ledbit = 0;
18955a1d80aSGerd Hoffmann 
19055a1d80aSGerd Hoffmann     switch (le16_to_cpu(event->type)) {
19155a1d80aSGerd Hoffmann     case EV_LED:
19255a1d80aSGerd Hoffmann         if (event->code == LED_NUML) {
19355a1d80aSGerd Hoffmann             ledbit = QEMU_NUM_LOCK_LED;
19455a1d80aSGerd Hoffmann         } else if (event->code == LED_CAPSL) {
19555a1d80aSGerd Hoffmann             ledbit = QEMU_CAPS_LOCK_LED;
19655a1d80aSGerd Hoffmann         } else if (event->code == LED_SCROLLL) {
19755a1d80aSGerd Hoffmann             ledbit = QEMU_SCROLL_LOCK_LED;
19855a1d80aSGerd Hoffmann         }
19955a1d80aSGerd Hoffmann         if (event->value) {
20055a1d80aSGerd Hoffmann             vhid->ledstate |= ledbit;
20155a1d80aSGerd Hoffmann         } else {
20255a1d80aSGerd Hoffmann             vhid->ledstate &= ~ledbit;
20355a1d80aSGerd Hoffmann         }
20455a1d80aSGerd Hoffmann         kbd_put_ledstate(vhid->ledstate);
20555a1d80aSGerd Hoffmann         break;
20655a1d80aSGerd Hoffmann     default:
20755a1d80aSGerd Hoffmann         fprintf(stderr, "%s: unknown type %d\n", __func__,
20855a1d80aSGerd Hoffmann                 le16_to_cpu(event->type));
20955a1d80aSGerd Hoffmann         break;
21055a1d80aSGerd Hoffmann     }
21155a1d80aSGerd Hoffmann }
21255a1d80aSGerd Hoffmann 
2135cce1733SGerd Hoffmann static Property virtio_input_hid_properties[] = {
2145cce1733SGerd Hoffmann     DEFINE_PROP_STRING("display", VirtIOInputHID, display),
2155cce1733SGerd Hoffmann     DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0),
2162a19b229SLin Ma     DEFINE_PROP_END_OF_LIST(),
2175cce1733SGerd Hoffmann };
2185cce1733SGerd Hoffmann 
21955a1d80aSGerd Hoffmann static void virtio_input_hid_class_init(ObjectClass *klass, void *data)
22055a1d80aSGerd Hoffmann {
2215cce1733SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
22255a1d80aSGerd Hoffmann     VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
22355a1d80aSGerd Hoffmann 
2245cce1733SGerd Hoffmann     dc->props          = virtio_input_hid_properties;
22555a1d80aSGerd Hoffmann     vic->realize       = virtio_input_hid_realize;
22655a1d80aSGerd Hoffmann     vic->unrealize     = virtio_input_hid_unrealize;
22755a1d80aSGerd Hoffmann     vic->change_active = virtio_input_hid_change_active;
22855a1d80aSGerd Hoffmann     vic->handle_status = virtio_input_hid_handle_status;
22955a1d80aSGerd Hoffmann }
23055a1d80aSGerd Hoffmann 
23155a1d80aSGerd Hoffmann static const TypeInfo virtio_input_hid_info = {
23255a1d80aSGerd Hoffmann     .name          = TYPE_VIRTIO_INPUT_HID,
23355a1d80aSGerd Hoffmann     .parent        = TYPE_VIRTIO_INPUT,
23455a1d80aSGerd Hoffmann     .instance_size = sizeof(VirtIOInputHID),
23555a1d80aSGerd Hoffmann     .class_init    = virtio_input_hid_class_init,
23655a1d80aSGerd Hoffmann     .abstract      = true,
23755a1d80aSGerd Hoffmann };
23855a1d80aSGerd Hoffmann 
23955a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
24055a1d80aSGerd Hoffmann 
24155a1d80aSGerd Hoffmann static QemuInputHandler virtio_keyboard_handler = {
24255a1d80aSGerd Hoffmann     .name  = VIRTIO_ID_NAME_KEYBOARD,
24355a1d80aSGerd Hoffmann     .mask  = INPUT_EVENT_MASK_KEY,
24455a1d80aSGerd Hoffmann     .event = virtio_input_handle_event,
24555a1d80aSGerd Hoffmann     .sync  = virtio_input_handle_sync,
24655a1d80aSGerd Hoffmann };
24755a1d80aSGerd Hoffmann 
24855a1d80aSGerd Hoffmann static struct virtio_input_config virtio_keyboard_config[] = {
24955a1d80aSGerd Hoffmann     {
25055a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_NAME,
25155a1d80aSGerd Hoffmann         .size      = sizeof(VIRTIO_ID_NAME_KEYBOARD),
25255a1d80aSGerd Hoffmann         .u.string  = VIRTIO_ID_NAME_KEYBOARD,
25355a1d80aSGerd Hoffmann     },{
25455a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
25555a1d80aSGerd Hoffmann         .size      = sizeof(struct virtio_input_devids),
25655a1d80aSGerd Hoffmann         .u.ids     = {
25755a1d80aSGerd Hoffmann             .bustype = const_le16(BUS_VIRTUAL),
25855a1d80aSGerd Hoffmann             .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
25955a1d80aSGerd Hoffmann             .product = const_le16(0x0001),
26055a1d80aSGerd Hoffmann             .version = const_le16(0x0001),
26155a1d80aSGerd Hoffmann         },
26255a1d80aSGerd Hoffmann     },{
26355a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
26455a1d80aSGerd Hoffmann         .subsel    = EV_REP,
26555a1d80aSGerd Hoffmann         .size      = 1,
26655a1d80aSGerd Hoffmann     },{
26755a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
26855a1d80aSGerd Hoffmann         .subsel    = EV_LED,
26955a1d80aSGerd Hoffmann         .size      = 1,
27055a1d80aSGerd Hoffmann         .u.bitmap  = {
27155a1d80aSGerd Hoffmann             (1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL),
27255a1d80aSGerd Hoffmann         },
27355a1d80aSGerd Hoffmann     },
27455a1d80aSGerd Hoffmann     { /* end of list */ },
27555a1d80aSGerd Hoffmann };
27655a1d80aSGerd Hoffmann 
27755a1d80aSGerd Hoffmann static void virtio_keyboard_init(Object *obj)
27855a1d80aSGerd Hoffmann {
27955a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
28055a1d80aSGerd Hoffmann     VirtIOInput *vinput = VIRTIO_INPUT(obj);
28155a1d80aSGerd Hoffmann 
28255a1d80aSGerd Hoffmann     vhid->handler = &virtio_keyboard_handler;
28355a1d80aSGerd Hoffmann     virtio_input_init_config(vinput, virtio_keyboard_config);
284*ae6b06abSDaniel P. Berrange     virtio_input_key_config(vinput, qemu_input_map_qcode_to_linux,
285*ae6b06abSDaniel P. Berrange                             qemu_input_map_qcode_to_linux_len);
28655a1d80aSGerd Hoffmann }
28755a1d80aSGerd Hoffmann 
28855a1d80aSGerd Hoffmann static const TypeInfo virtio_keyboard_info = {
28955a1d80aSGerd Hoffmann     .name          = TYPE_VIRTIO_KEYBOARD,
29055a1d80aSGerd Hoffmann     .parent        = TYPE_VIRTIO_INPUT_HID,
29155a1d80aSGerd Hoffmann     .instance_size = sizeof(VirtIOInputHID),
29255a1d80aSGerd Hoffmann     .instance_init = virtio_keyboard_init,
29355a1d80aSGerd Hoffmann };
29455a1d80aSGerd Hoffmann 
29555a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
29655a1d80aSGerd Hoffmann 
29755a1d80aSGerd Hoffmann static QemuInputHandler virtio_mouse_handler = {
29855a1d80aSGerd Hoffmann     .name  = VIRTIO_ID_NAME_MOUSE,
29955a1d80aSGerd Hoffmann     .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
30055a1d80aSGerd Hoffmann     .event = virtio_input_handle_event,
30155a1d80aSGerd Hoffmann     .sync  = virtio_input_handle_sync,
30255a1d80aSGerd Hoffmann };
30355a1d80aSGerd Hoffmann 
304f4924974SGerd Hoffmann static struct virtio_input_config virtio_mouse_config_v1[] = {
30555a1d80aSGerd Hoffmann     {
30655a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_NAME,
30755a1d80aSGerd Hoffmann         .size      = sizeof(VIRTIO_ID_NAME_MOUSE),
30855a1d80aSGerd Hoffmann         .u.string  = VIRTIO_ID_NAME_MOUSE,
30955a1d80aSGerd Hoffmann     },{
31055a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
31155a1d80aSGerd Hoffmann         .size      = sizeof(struct virtio_input_devids),
31255a1d80aSGerd Hoffmann         .u.ids     = {
31355a1d80aSGerd Hoffmann             .bustype = const_le16(BUS_VIRTUAL),
31455a1d80aSGerd Hoffmann             .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
31555a1d80aSGerd Hoffmann             .product = const_le16(0x0002),
31655a1d80aSGerd Hoffmann             .version = const_le16(0x0001),
31755a1d80aSGerd Hoffmann         },
31855a1d80aSGerd Hoffmann     },{
31955a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
32055a1d80aSGerd Hoffmann         .subsel    = EV_REL,
32155a1d80aSGerd Hoffmann         .size      = 1,
32255a1d80aSGerd Hoffmann         .u.bitmap  = {
32355a1d80aSGerd Hoffmann             (1 << REL_X) | (1 << REL_Y),
32455a1d80aSGerd Hoffmann         },
32555a1d80aSGerd Hoffmann     },
32655a1d80aSGerd Hoffmann     { /* end of list */ },
32755a1d80aSGerd Hoffmann };
32855a1d80aSGerd Hoffmann 
329f4924974SGerd Hoffmann static struct virtio_input_config virtio_mouse_config_v2[] = {
330f4924974SGerd Hoffmann     {
331f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_NAME,
332f4924974SGerd Hoffmann         .size      = sizeof(VIRTIO_ID_NAME_MOUSE),
333f4924974SGerd Hoffmann         .u.string  = VIRTIO_ID_NAME_MOUSE,
334f4924974SGerd Hoffmann     },{
335f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
336f4924974SGerd Hoffmann         .size      = sizeof(struct virtio_input_devids),
337f4924974SGerd Hoffmann         .u.ids     = {
338f4924974SGerd Hoffmann             .bustype = const_le16(BUS_VIRTUAL),
339f4924974SGerd Hoffmann             .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
340f4924974SGerd Hoffmann             .product = const_le16(0x0002),
341f4924974SGerd Hoffmann             .version = const_le16(0x0002),
342f4924974SGerd Hoffmann         },
343f4924974SGerd Hoffmann     },{
344f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
345f4924974SGerd Hoffmann         .subsel    = EV_REL,
346f4924974SGerd Hoffmann         .size      = 2,
347f4924974SGerd Hoffmann         .u.bitmap  = {
348f4924974SGerd Hoffmann             (1 << REL_X) | (1 << REL_Y),
349f4924974SGerd Hoffmann             (1 << (REL_WHEEL - 8))
350f4924974SGerd Hoffmann         },
351f4924974SGerd Hoffmann     },
352f4924974SGerd Hoffmann     { /* end of list */ },
353f4924974SGerd Hoffmann };
354f4924974SGerd Hoffmann 
355f4924974SGerd Hoffmann static Property virtio_mouse_properties[] = {
356f4924974SGerd Hoffmann     DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
357f4924974SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
358f4924974SGerd Hoffmann };
359f4924974SGerd Hoffmann 
360f4924974SGerd Hoffmann static void virtio_mouse_class_init(ObjectClass *klass, void *data)
361f4924974SGerd Hoffmann {
362f4924974SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
363f4924974SGerd Hoffmann 
364f4924974SGerd Hoffmann     dc->props  = virtio_mouse_properties;
365f4924974SGerd Hoffmann }
366f4924974SGerd Hoffmann 
36755a1d80aSGerd Hoffmann static void virtio_mouse_init(Object *obj)
36855a1d80aSGerd Hoffmann {
36955a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
37055a1d80aSGerd Hoffmann     VirtIOInput *vinput = VIRTIO_INPUT(obj);
37155a1d80aSGerd Hoffmann 
37255a1d80aSGerd Hoffmann     vhid->handler = &virtio_mouse_handler;
373f4924974SGerd Hoffmann     virtio_input_init_config(vinput, vhid->wheel_axis
374f4924974SGerd Hoffmann                              ? virtio_mouse_config_v2
375f4924974SGerd Hoffmann                              : virtio_mouse_config_v1);
37655a1d80aSGerd Hoffmann     virtio_input_key_config(vinput, keymap_button,
37755a1d80aSGerd Hoffmann                             ARRAY_SIZE(keymap_button));
37855a1d80aSGerd Hoffmann }
37955a1d80aSGerd Hoffmann 
38055a1d80aSGerd Hoffmann static const TypeInfo virtio_mouse_info = {
38155a1d80aSGerd Hoffmann     .name          = TYPE_VIRTIO_MOUSE,
38255a1d80aSGerd Hoffmann     .parent        = TYPE_VIRTIO_INPUT_HID,
38355a1d80aSGerd Hoffmann     .instance_size = sizeof(VirtIOInputHID),
38455a1d80aSGerd Hoffmann     .instance_init = virtio_mouse_init,
385f4924974SGerd Hoffmann     .class_init    = virtio_mouse_class_init,
38655a1d80aSGerd Hoffmann };
38755a1d80aSGerd Hoffmann 
38855a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
38955a1d80aSGerd Hoffmann 
39055a1d80aSGerd Hoffmann static QemuInputHandler virtio_tablet_handler = {
39155a1d80aSGerd Hoffmann     .name  = VIRTIO_ID_NAME_TABLET,
39255a1d80aSGerd Hoffmann     .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
39355a1d80aSGerd Hoffmann     .event = virtio_input_handle_event,
39455a1d80aSGerd Hoffmann     .sync  = virtio_input_handle_sync,
39555a1d80aSGerd Hoffmann };
39655a1d80aSGerd Hoffmann 
397f4924974SGerd Hoffmann static struct virtio_input_config virtio_tablet_config_v1[] = {
39855a1d80aSGerd Hoffmann     {
39955a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_NAME,
40055a1d80aSGerd Hoffmann         .size      = sizeof(VIRTIO_ID_NAME_TABLET),
40155a1d80aSGerd Hoffmann         .u.string  = VIRTIO_ID_NAME_TABLET,
40255a1d80aSGerd Hoffmann     },{
40355a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
40455a1d80aSGerd Hoffmann         .size      = sizeof(struct virtio_input_devids),
40555a1d80aSGerd Hoffmann         .u.ids     = {
40655a1d80aSGerd Hoffmann             .bustype = const_le16(BUS_VIRTUAL),
40755a1d80aSGerd Hoffmann             .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
40855a1d80aSGerd Hoffmann             .product = const_le16(0x0003),
40955a1d80aSGerd Hoffmann             .version = const_le16(0x0001),
41055a1d80aSGerd Hoffmann         },
41155a1d80aSGerd Hoffmann     },{
41255a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
41355a1d80aSGerd Hoffmann         .subsel    = EV_ABS,
41455a1d80aSGerd Hoffmann         .size      = 1,
41555a1d80aSGerd Hoffmann         .u.bitmap  = {
41655a1d80aSGerd Hoffmann             (1 << ABS_X) | (1 << ABS_Y),
41755a1d80aSGerd Hoffmann         },
41855a1d80aSGerd Hoffmann     },{
41955a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ABS_INFO,
42055a1d80aSGerd Hoffmann         .subsel    = ABS_X,
42155a1d80aSGerd Hoffmann         .size      = sizeof(virtio_input_absinfo),
4229cfa7ab9SPhilippe Voinov         .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
4239cfa7ab9SPhilippe Voinov         .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
42455a1d80aSGerd Hoffmann     },{
42555a1d80aSGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ABS_INFO,
42655a1d80aSGerd Hoffmann         .subsel    = ABS_Y,
42755a1d80aSGerd Hoffmann         .size      = sizeof(virtio_input_absinfo),
4289cfa7ab9SPhilippe Voinov         .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
4299cfa7ab9SPhilippe Voinov         .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
43055a1d80aSGerd Hoffmann     },
43155a1d80aSGerd Hoffmann     { /* end of list */ },
43255a1d80aSGerd Hoffmann };
43355a1d80aSGerd Hoffmann 
434f4924974SGerd Hoffmann static struct virtio_input_config virtio_tablet_config_v2[] = {
435f4924974SGerd Hoffmann     {
436f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_NAME,
437f4924974SGerd Hoffmann         .size      = sizeof(VIRTIO_ID_NAME_TABLET),
438f4924974SGerd Hoffmann         .u.string  = VIRTIO_ID_NAME_TABLET,
439f4924974SGerd Hoffmann     },{
440f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
441f4924974SGerd Hoffmann         .size      = sizeof(struct virtio_input_devids),
442f4924974SGerd Hoffmann         .u.ids     = {
443f4924974SGerd Hoffmann             .bustype = const_le16(BUS_VIRTUAL),
444f4924974SGerd Hoffmann             .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
445f4924974SGerd Hoffmann             .product = const_le16(0x0003),
446f4924974SGerd Hoffmann             .version = const_le16(0x0002),
447f4924974SGerd Hoffmann         },
448f4924974SGerd Hoffmann     },{
449f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
450f4924974SGerd Hoffmann         .subsel    = EV_ABS,
451f4924974SGerd Hoffmann         .size      = 1,
452f4924974SGerd Hoffmann         .u.bitmap  = {
453f4924974SGerd Hoffmann             (1 << ABS_X) | (1 << ABS_Y),
454f4924974SGerd Hoffmann         },
455f4924974SGerd Hoffmann     },{
456f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_EV_BITS,
457f4924974SGerd Hoffmann         .subsel    = EV_REL,
458f4924974SGerd Hoffmann         .size      = 2,
459f4924974SGerd Hoffmann         .u.bitmap  = {
460f4924974SGerd Hoffmann             0,
461f4924974SGerd Hoffmann             (1 << (REL_WHEEL - 8))
462f4924974SGerd Hoffmann         },
463f4924974SGerd Hoffmann     },{
464f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ABS_INFO,
465f4924974SGerd Hoffmann         .subsel    = ABS_X,
466f4924974SGerd Hoffmann         .size      = sizeof(virtio_input_absinfo),
467f4924974SGerd Hoffmann         .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
468f4924974SGerd Hoffmann         .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
469f4924974SGerd Hoffmann     },{
470f4924974SGerd Hoffmann         .select    = VIRTIO_INPUT_CFG_ABS_INFO,
471f4924974SGerd Hoffmann         .subsel    = ABS_Y,
472f4924974SGerd Hoffmann         .size      = sizeof(virtio_input_absinfo),
473f4924974SGerd Hoffmann         .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
474f4924974SGerd Hoffmann         .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
475f4924974SGerd Hoffmann     },
476f4924974SGerd Hoffmann     { /* end of list */ },
477f4924974SGerd Hoffmann };
478f4924974SGerd Hoffmann 
479f4924974SGerd Hoffmann static Property virtio_tablet_properties[] = {
480f4924974SGerd Hoffmann     DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
481f4924974SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
482f4924974SGerd Hoffmann };
483f4924974SGerd Hoffmann 
484f4924974SGerd Hoffmann static void virtio_tablet_class_init(ObjectClass *klass, void *data)
485f4924974SGerd Hoffmann {
486f4924974SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
487f4924974SGerd Hoffmann 
488f4924974SGerd Hoffmann     dc->props  = virtio_tablet_properties;
489f4924974SGerd Hoffmann }
490f4924974SGerd Hoffmann 
49155a1d80aSGerd Hoffmann static void virtio_tablet_init(Object *obj)
49255a1d80aSGerd Hoffmann {
49355a1d80aSGerd Hoffmann     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
49455a1d80aSGerd Hoffmann     VirtIOInput *vinput = VIRTIO_INPUT(obj);
49555a1d80aSGerd Hoffmann 
49655a1d80aSGerd Hoffmann     vhid->handler = &virtio_tablet_handler;
497f4924974SGerd Hoffmann     virtio_input_init_config(vinput, vhid->wheel_axis
498f4924974SGerd Hoffmann                              ? virtio_tablet_config_v2
499f4924974SGerd Hoffmann                              : virtio_tablet_config_v1);
50055a1d80aSGerd Hoffmann     virtio_input_key_config(vinput, keymap_button,
50155a1d80aSGerd Hoffmann                             ARRAY_SIZE(keymap_button));
50255a1d80aSGerd Hoffmann }
50355a1d80aSGerd Hoffmann 
50455a1d80aSGerd Hoffmann static const TypeInfo virtio_tablet_info = {
50555a1d80aSGerd Hoffmann     .name          = TYPE_VIRTIO_TABLET,
50655a1d80aSGerd Hoffmann     .parent        = TYPE_VIRTIO_INPUT_HID,
50755a1d80aSGerd Hoffmann     .instance_size = sizeof(VirtIOInputHID),
50855a1d80aSGerd Hoffmann     .instance_init = virtio_tablet_init,
509f4924974SGerd Hoffmann     .class_init    = virtio_tablet_class_init,
51055a1d80aSGerd Hoffmann };
51155a1d80aSGerd Hoffmann 
51255a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
51355a1d80aSGerd Hoffmann 
51455a1d80aSGerd Hoffmann static void virtio_register_types(void)
51555a1d80aSGerd Hoffmann {
51655a1d80aSGerd Hoffmann     type_register_static(&virtio_input_hid_info);
51755a1d80aSGerd Hoffmann     type_register_static(&virtio_keyboard_info);
51855a1d80aSGerd Hoffmann     type_register_static(&virtio_mouse_info);
51955a1d80aSGerd Hoffmann     type_register_static(&virtio_tablet_info);
52055a1d80aSGerd Hoffmann }
52155a1d80aSGerd Hoffmann 
52255a1d80aSGerd Hoffmann type_init(virtio_register_types)
523