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"
228e9ebd75SSergio Lopez #define VIRTIO_ID_NAME_MULTITOUCH "QEMU Virtio MultiTouch"
2355a1d80aSGerd Hoffmann
2455a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
2555a1d80aSGerd Hoffmann
26ae6b06abSDaniel P. Berrange static const unsigned short keymap_button[INPUT_BUTTON__MAX] = {
2755a1d80aSGerd Hoffmann [INPUT_BUTTON_LEFT] = BTN_LEFT,
2855a1d80aSGerd Hoffmann [INPUT_BUTTON_RIGHT] = BTN_RIGHT,
2955a1d80aSGerd Hoffmann [INPUT_BUTTON_MIDDLE] = BTN_MIDDLE,
30f22d0af0SGerd Hoffmann [INPUT_BUTTON_WHEEL_UP] = BTN_GEAR_UP,
31f22d0af0SGerd Hoffmann [INPUT_BUTTON_WHEEL_DOWN] = BTN_GEAR_DOWN,
322416760fSMiika S [INPUT_BUTTON_SIDE] = BTN_SIDE,
332416760fSMiika S [INPUT_BUTTON_EXTRA] = BTN_EXTRA,
348e9ebd75SSergio Lopez [INPUT_BUTTON_TOUCH] = BTN_TOUCH,
3555a1d80aSGerd Hoffmann };
3655a1d80aSGerd Hoffmann
37ae6b06abSDaniel P. Berrange static const unsigned short axismap_rel[INPUT_AXIS__MAX] = {
3855a1d80aSGerd Hoffmann [INPUT_AXIS_X] = REL_X,
3955a1d80aSGerd Hoffmann [INPUT_AXIS_Y] = REL_Y,
4055a1d80aSGerd Hoffmann };
4155a1d80aSGerd Hoffmann
42ae6b06abSDaniel P. Berrange static const unsigned short axismap_abs[INPUT_AXIS__MAX] = {
4355a1d80aSGerd Hoffmann [INPUT_AXIS_X] = ABS_X,
4455a1d80aSGerd Hoffmann [INPUT_AXIS_Y] = ABS_Y,
4555a1d80aSGerd Hoffmann };
4655a1d80aSGerd Hoffmann
478e9ebd75SSergio Lopez static const unsigned short axismap_tch[INPUT_AXIS__MAX] = {
488e9ebd75SSergio Lopez [INPUT_AXIS_X] = ABS_MT_POSITION_X,
498e9ebd75SSergio Lopez [INPUT_AXIS_Y] = ABS_MT_POSITION_Y,
508e9ebd75SSergio Lopez };
518e9ebd75SSergio Lopez
5255a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
5355a1d80aSGerd Hoffmann
virtio_input_extend_config(VirtIOInput * vinput,const unsigned short * map,size_t mapsize,uint8_t select,uint8_t subsel)54944ae6d9SSergio Lopez static void virtio_input_extend_config(VirtIOInput *vinput,
55944ae6d9SSergio Lopez const unsigned short *map,
56944ae6d9SSergio Lopez size_t mapsize,
57944ae6d9SSergio Lopez uint8_t select, uint8_t subsel)
5855a1d80aSGerd Hoffmann {
59944ae6d9SSergio Lopez virtio_input_config ext;
6055a1d80aSGerd Hoffmann int i, bit, byte, bmax = 0;
6155a1d80aSGerd Hoffmann
62944ae6d9SSergio Lopez memset(&ext, 0, sizeof(ext));
6355a1d80aSGerd Hoffmann for (i = 0; i < mapsize; i++) {
64944ae6d9SSergio Lopez bit = map[i];
6555a1d80aSGerd Hoffmann if (!bit) {
6655a1d80aSGerd Hoffmann continue;
6755a1d80aSGerd Hoffmann }
6855a1d80aSGerd Hoffmann byte = bit / 8;
6955a1d80aSGerd Hoffmann bit = bit % 8;
70944ae6d9SSergio Lopez ext.u.bitmap[byte] |= (1 << bit);
7155a1d80aSGerd Hoffmann if (bmax < byte+1) {
7255a1d80aSGerd Hoffmann bmax = byte+1;
7355a1d80aSGerd Hoffmann }
7455a1d80aSGerd Hoffmann }
75944ae6d9SSergio Lopez ext.select = select;
76944ae6d9SSergio Lopez ext.subsel = subsel;
77944ae6d9SSergio Lopez ext.size = bmax;
78944ae6d9SSergio Lopez virtio_input_add_config(vinput, &ext);
7955a1d80aSGerd Hoffmann }
8055a1d80aSGerd Hoffmann
virtio_input_handle_event(DeviceState * dev,QemuConsole * src,InputEvent * evt)8155a1d80aSGerd Hoffmann static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
8255a1d80aSGerd Hoffmann InputEvent *evt)
8355a1d80aSGerd Hoffmann {
84f4924974SGerd Hoffmann VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
8555a1d80aSGerd Hoffmann VirtIOInput *vinput = VIRTIO_INPUT(dev);
8655a1d80aSGerd Hoffmann virtio_input_event event;
8755a1d80aSGerd Hoffmann int qcode;
88b5a1b443SEric Blake InputKeyEvent *key;
89b5a1b443SEric Blake InputMoveEvent *move;
90b5a1b443SEric Blake InputBtnEvent *btn;
918e9ebd75SSergio Lopez InputMultiTouchEvent *mtt;
9255a1d80aSGerd Hoffmann
93568c73a4SEric Blake switch (evt->type) {
9455a1d80aSGerd Hoffmann case INPUT_EVENT_KIND_KEY:
9532bafa8fSEric Blake key = evt->u.key.data;
96b5a1b443SEric Blake qcode = qemu_input_key_value_to_qcode(key->key);
97ae6b06abSDaniel P. Berrange if (qcode < qemu_input_map_qcode_to_linux_len &&
98ae6b06abSDaniel P. Berrange qemu_input_map_qcode_to_linux[qcode]) {
9955a1d80aSGerd Hoffmann event.type = cpu_to_le16(EV_KEY);
100ae6b06abSDaniel P. Berrange event.code = cpu_to_le16(qemu_input_map_qcode_to_linux[qcode]);
101b5a1b443SEric Blake event.value = cpu_to_le32(key->down ? 1 : 0);
10255a1d80aSGerd Hoffmann virtio_input_send(vinput, &event);
10355a1d80aSGerd Hoffmann } else {
104b5a1b443SEric Blake if (key->down) {
10555a1d80aSGerd Hoffmann fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
106977c736fSMarkus Armbruster qcode, QKeyCode_str(qcode));
10755a1d80aSGerd Hoffmann }
10855a1d80aSGerd Hoffmann }
10955a1d80aSGerd Hoffmann break;
11055a1d80aSGerd Hoffmann case INPUT_EVENT_KIND_BTN:
11132bafa8fSEric Blake btn = evt->u.btn.data;
112a5f99be4SMiika S if (vhid->wheel_axis &&
113a5f99be4SMiika S (btn->button == INPUT_BUTTON_WHEEL_UP ||
114a5f99be4SMiika S btn->button == INPUT_BUTTON_WHEEL_DOWN) &&
115a5f99be4SMiika S btn->down) {
116f4924974SGerd Hoffmann event.type = cpu_to_le16(EV_REL);
117f4924974SGerd Hoffmann event.code = cpu_to_le16(REL_WHEEL);
118f4924974SGerd Hoffmann event.value = cpu_to_le32(btn->button == INPUT_BUTTON_WHEEL_UP
119f4924974SGerd Hoffmann ? 1 : -1);
120f4924974SGerd Hoffmann virtio_input_send(vinput, &event);
121f4924974SGerd Hoffmann } else if (keymap_button[btn->button]) {
12255a1d80aSGerd Hoffmann event.type = cpu_to_le16(EV_KEY);
123b5a1b443SEric Blake event.code = cpu_to_le16(keymap_button[btn->button]);
124b5a1b443SEric Blake event.value = cpu_to_le32(btn->down ? 1 : 0);
12555a1d80aSGerd Hoffmann virtio_input_send(vinput, &event);
12655a1d80aSGerd Hoffmann } else {
127b5a1b443SEric Blake if (btn->down) {
12855a1d80aSGerd Hoffmann fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
129b5a1b443SEric Blake btn->button,
130977c736fSMarkus Armbruster InputButton_str(btn->button));
13155a1d80aSGerd Hoffmann }
13255a1d80aSGerd Hoffmann }
13355a1d80aSGerd Hoffmann break;
13455a1d80aSGerd Hoffmann case INPUT_EVENT_KIND_REL:
13532bafa8fSEric Blake move = evt->u.rel.data;
13655a1d80aSGerd Hoffmann event.type = cpu_to_le16(EV_REL);
137b5a1b443SEric Blake event.code = cpu_to_le16(axismap_rel[move->axis]);
138b5a1b443SEric Blake event.value = cpu_to_le32(move->value);
13955a1d80aSGerd Hoffmann virtio_input_send(vinput, &event);
14055a1d80aSGerd Hoffmann break;
14155a1d80aSGerd Hoffmann case INPUT_EVENT_KIND_ABS:
14232bafa8fSEric Blake move = evt->u.abs.data;
14355a1d80aSGerd Hoffmann event.type = cpu_to_le16(EV_ABS);
144b5a1b443SEric Blake event.code = cpu_to_le16(axismap_abs[move->axis]);
145b5a1b443SEric Blake event.value = cpu_to_le32(move->value);
14655a1d80aSGerd Hoffmann virtio_input_send(vinput, &event);
14755a1d80aSGerd Hoffmann break;
1488e9ebd75SSergio Lopez case INPUT_EVENT_KIND_MTT:
1498e9ebd75SSergio Lopez mtt = evt->u.mtt.data;
1508e9ebd75SSergio Lopez if (mtt->type == INPUT_MULTI_TOUCH_TYPE_DATA) {
1518e9ebd75SSergio Lopez event.type = cpu_to_le16(EV_ABS);
1528e9ebd75SSergio Lopez event.code = cpu_to_le16(axismap_tch[mtt->axis]);
1538e9ebd75SSergio Lopez event.value = cpu_to_le32(mtt->value);
1548e9ebd75SSergio Lopez virtio_input_send(vinput, &event);
1558e9ebd75SSergio Lopez } else {
1568e9ebd75SSergio Lopez event.type = cpu_to_le16(EV_ABS);
1578e9ebd75SSergio Lopez event.code = cpu_to_le16(ABS_MT_SLOT);
1588e9ebd75SSergio Lopez event.value = cpu_to_le32(mtt->slot);
1598e9ebd75SSergio Lopez virtio_input_send(vinput, &event);
1608e9ebd75SSergio Lopez event.type = cpu_to_le16(EV_ABS);
1618e9ebd75SSergio Lopez event.code = cpu_to_le16(ABS_MT_TRACKING_ID);
1628e9ebd75SSergio Lopez event.value = cpu_to_le32(mtt->tracking_id);
1638e9ebd75SSergio Lopez virtio_input_send(vinput, &event);
1648e9ebd75SSergio Lopez }
1658e9ebd75SSergio Lopez break;
16655a1d80aSGerd Hoffmann default:
16755a1d80aSGerd Hoffmann /* keep gcc happy */
16855a1d80aSGerd Hoffmann break;
16955a1d80aSGerd Hoffmann }
17055a1d80aSGerd Hoffmann }
17155a1d80aSGerd Hoffmann
virtio_input_handle_sync(DeviceState * dev)17255a1d80aSGerd Hoffmann static void virtio_input_handle_sync(DeviceState *dev)
17355a1d80aSGerd Hoffmann {
17455a1d80aSGerd Hoffmann VirtIOInput *vinput = VIRTIO_INPUT(dev);
17555a1d80aSGerd Hoffmann virtio_input_event event = {
17655a1d80aSGerd Hoffmann .type = cpu_to_le16(EV_SYN),
17755a1d80aSGerd Hoffmann .code = cpu_to_le16(SYN_REPORT),
17855a1d80aSGerd Hoffmann .value = 0,
17955a1d80aSGerd Hoffmann };
18055a1d80aSGerd Hoffmann
18155a1d80aSGerd Hoffmann virtio_input_send(vinput, &event);
18255a1d80aSGerd Hoffmann }
18355a1d80aSGerd Hoffmann
virtio_input_hid_realize(DeviceState * dev,Error ** errp)18455a1d80aSGerd Hoffmann static void virtio_input_hid_realize(DeviceState *dev, Error **errp)
18555a1d80aSGerd Hoffmann {
18655a1d80aSGerd Hoffmann VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
1875cce1733SGerd Hoffmann
18855a1d80aSGerd Hoffmann vhid->hs = qemu_input_handler_register(dev, vhid->handler);
1895cce1733SGerd Hoffmann if (vhid->display && vhid->hs) {
1905cce1733SGerd Hoffmann qemu_input_handler_bind(vhid->hs, vhid->display, vhid->head, NULL);
1915cce1733SGerd Hoffmann }
19255a1d80aSGerd Hoffmann }
19355a1d80aSGerd Hoffmann
virtio_input_hid_unrealize(DeviceState * dev)194b69c3c21SMarkus Armbruster static void virtio_input_hid_unrealize(DeviceState *dev)
19555a1d80aSGerd Hoffmann {
19655a1d80aSGerd Hoffmann VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
19755a1d80aSGerd Hoffmann qemu_input_handler_unregister(vhid->hs);
19855a1d80aSGerd Hoffmann }
19955a1d80aSGerd Hoffmann
virtio_input_hid_change_active(VirtIOInput * vinput)20055a1d80aSGerd Hoffmann static void virtio_input_hid_change_active(VirtIOInput *vinput)
20155a1d80aSGerd Hoffmann {
20255a1d80aSGerd Hoffmann VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
20355a1d80aSGerd Hoffmann
20455a1d80aSGerd Hoffmann if (vinput->active) {
20555a1d80aSGerd Hoffmann qemu_input_handler_activate(vhid->hs);
20655a1d80aSGerd Hoffmann } else {
20755a1d80aSGerd Hoffmann qemu_input_handler_deactivate(vhid->hs);
20855a1d80aSGerd Hoffmann }
20955a1d80aSGerd Hoffmann }
21055a1d80aSGerd Hoffmann
virtio_input_hid_handle_status(VirtIOInput * vinput,virtio_input_event * event)21155a1d80aSGerd Hoffmann static void virtio_input_hid_handle_status(VirtIOInput *vinput,
21255a1d80aSGerd Hoffmann virtio_input_event *event)
21355a1d80aSGerd Hoffmann {
21455a1d80aSGerd Hoffmann VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
21555a1d80aSGerd Hoffmann int ledbit = 0;
21655a1d80aSGerd Hoffmann
21755a1d80aSGerd Hoffmann switch (le16_to_cpu(event->type)) {
21855a1d80aSGerd Hoffmann case EV_LED:
21955a1d80aSGerd Hoffmann if (event->code == LED_NUML) {
22055a1d80aSGerd Hoffmann ledbit = QEMU_NUM_LOCK_LED;
22155a1d80aSGerd Hoffmann } else if (event->code == LED_CAPSL) {
22255a1d80aSGerd Hoffmann ledbit = QEMU_CAPS_LOCK_LED;
22355a1d80aSGerd Hoffmann } else if (event->code == LED_SCROLLL) {
22455a1d80aSGerd Hoffmann ledbit = QEMU_SCROLL_LOCK_LED;
22555a1d80aSGerd Hoffmann }
22655a1d80aSGerd Hoffmann if (event->value) {
22755a1d80aSGerd Hoffmann vhid->ledstate |= ledbit;
22855a1d80aSGerd Hoffmann } else {
22955a1d80aSGerd Hoffmann vhid->ledstate &= ~ledbit;
23055a1d80aSGerd Hoffmann }
23155a1d80aSGerd Hoffmann kbd_put_ledstate(vhid->ledstate);
23255a1d80aSGerd Hoffmann break;
23355a1d80aSGerd Hoffmann default:
23455a1d80aSGerd Hoffmann fprintf(stderr, "%s: unknown type %d\n", __func__,
23555a1d80aSGerd Hoffmann le16_to_cpu(event->type));
23655a1d80aSGerd Hoffmann break;
23755a1d80aSGerd Hoffmann }
23855a1d80aSGerd Hoffmann }
23955a1d80aSGerd Hoffmann
2409eb5c799SRichard Henderson static const Property virtio_input_hid_properties[] = {
2415cce1733SGerd Hoffmann DEFINE_PROP_STRING("display", VirtIOInputHID, display),
2425cce1733SGerd Hoffmann DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0),
2435cce1733SGerd Hoffmann };
2445cce1733SGerd Hoffmann
virtio_input_hid_class_init(ObjectClass * klass,const void * data)245*12d1a768SPhilippe Mathieu-Daudé static void virtio_input_hid_class_init(ObjectClass *klass, const void *data)
24655a1d80aSGerd Hoffmann {
2475cce1733SGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass);
24855a1d80aSGerd Hoffmann VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
24955a1d80aSGerd Hoffmann
2504f67d30bSMarc-André Lureau device_class_set_props(dc, virtio_input_hid_properties);
25155a1d80aSGerd Hoffmann vic->realize = virtio_input_hid_realize;
25255a1d80aSGerd Hoffmann vic->unrealize = virtio_input_hid_unrealize;
25355a1d80aSGerd Hoffmann vic->change_active = virtio_input_hid_change_active;
25455a1d80aSGerd Hoffmann vic->handle_status = virtio_input_hid_handle_status;
25555a1d80aSGerd Hoffmann }
25655a1d80aSGerd Hoffmann
25755a1d80aSGerd Hoffmann static const TypeInfo virtio_input_hid_info = {
25855a1d80aSGerd Hoffmann .name = TYPE_VIRTIO_INPUT_HID,
25955a1d80aSGerd Hoffmann .parent = TYPE_VIRTIO_INPUT,
26055a1d80aSGerd Hoffmann .instance_size = sizeof(VirtIOInputHID),
26155a1d80aSGerd Hoffmann .class_init = virtio_input_hid_class_init,
26255a1d80aSGerd Hoffmann .abstract = true,
26355a1d80aSGerd Hoffmann };
26455a1d80aSGerd Hoffmann
26555a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
26655a1d80aSGerd Hoffmann
267b1be65f6SPhilippe Mathieu-Daudé static const QemuInputHandler virtio_keyboard_handler = {
26855a1d80aSGerd Hoffmann .name = VIRTIO_ID_NAME_KEYBOARD,
26955a1d80aSGerd Hoffmann .mask = INPUT_EVENT_MASK_KEY,
27055a1d80aSGerd Hoffmann .event = virtio_input_handle_event,
27155a1d80aSGerd Hoffmann .sync = virtio_input_handle_sync,
27255a1d80aSGerd Hoffmann };
27355a1d80aSGerd Hoffmann
27455a1d80aSGerd Hoffmann static struct virtio_input_config virtio_keyboard_config[] = {
27555a1d80aSGerd Hoffmann {
27655a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_NAME,
27755a1d80aSGerd Hoffmann .size = sizeof(VIRTIO_ID_NAME_KEYBOARD),
27855a1d80aSGerd Hoffmann .u.string = VIRTIO_ID_NAME_KEYBOARD,
27955a1d80aSGerd Hoffmann },{
28055a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
28155a1d80aSGerd Hoffmann .size = sizeof(struct virtio_input_devids),
28255a1d80aSGerd Hoffmann .u.ids = {
28355a1d80aSGerd Hoffmann .bustype = const_le16(BUS_VIRTUAL),
28455a1d80aSGerd Hoffmann .vendor = const_le16(0x0627), /* same we use for usb hid devices */
28555a1d80aSGerd Hoffmann .product = const_le16(0x0001),
28655a1d80aSGerd Hoffmann .version = const_le16(0x0001),
28755a1d80aSGerd Hoffmann },
28855a1d80aSGerd Hoffmann },{
28955a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS,
29055a1d80aSGerd Hoffmann .subsel = EV_REP,
29155a1d80aSGerd Hoffmann .size = 1,
29255a1d80aSGerd Hoffmann },{
29355a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS,
29455a1d80aSGerd Hoffmann .subsel = EV_LED,
29555a1d80aSGerd Hoffmann .size = 1,
29655a1d80aSGerd Hoffmann .u.bitmap = {
29755a1d80aSGerd Hoffmann (1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL),
29855a1d80aSGerd Hoffmann },
29955a1d80aSGerd Hoffmann },
30055a1d80aSGerd Hoffmann { /* end of list */ },
30155a1d80aSGerd Hoffmann };
30255a1d80aSGerd Hoffmann
virtio_keyboard_init(Object * obj)30355a1d80aSGerd Hoffmann static void virtio_keyboard_init(Object *obj)
30455a1d80aSGerd Hoffmann {
30555a1d80aSGerd Hoffmann VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
30655a1d80aSGerd Hoffmann VirtIOInput *vinput = VIRTIO_INPUT(obj);
30755a1d80aSGerd Hoffmann
30855a1d80aSGerd Hoffmann vhid->handler = &virtio_keyboard_handler;
30955a1d80aSGerd Hoffmann virtio_input_init_config(vinput, virtio_keyboard_config);
310944ae6d9SSergio Lopez virtio_input_extend_config(vinput, qemu_input_map_qcode_to_linux,
311944ae6d9SSergio Lopez qemu_input_map_qcode_to_linux_len,
312944ae6d9SSergio Lopez VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
31355a1d80aSGerd Hoffmann }
31455a1d80aSGerd Hoffmann
31555a1d80aSGerd Hoffmann static const TypeInfo virtio_keyboard_info = {
31655a1d80aSGerd Hoffmann .name = TYPE_VIRTIO_KEYBOARD,
31755a1d80aSGerd Hoffmann .parent = TYPE_VIRTIO_INPUT_HID,
31855a1d80aSGerd Hoffmann .instance_size = sizeof(VirtIOInputHID),
31955a1d80aSGerd Hoffmann .instance_init = virtio_keyboard_init,
32055a1d80aSGerd Hoffmann };
32155a1d80aSGerd Hoffmann
32255a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
32355a1d80aSGerd Hoffmann
324b1be65f6SPhilippe Mathieu-Daudé static const QemuInputHandler virtio_mouse_handler = {
32555a1d80aSGerd Hoffmann .name = VIRTIO_ID_NAME_MOUSE,
32655a1d80aSGerd Hoffmann .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
32755a1d80aSGerd Hoffmann .event = virtio_input_handle_event,
32855a1d80aSGerd Hoffmann .sync = virtio_input_handle_sync,
32955a1d80aSGerd Hoffmann };
33055a1d80aSGerd Hoffmann
331f4924974SGerd Hoffmann static struct virtio_input_config virtio_mouse_config_v1[] = {
33255a1d80aSGerd Hoffmann {
33355a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_NAME,
33455a1d80aSGerd Hoffmann .size = sizeof(VIRTIO_ID_NAME_MOUSE),
33555a1d80aSGerd Hoffmann .u.string = VIRTIO_ID_NAME_MOUSE,
33655a1d80aSGerd Hoffmann },{
33755a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
33855a1d80aSGerd Hoffmann .size = sizeof(struct virtio_input_devids),
33955a1d80aSGerd Hoffmann .u.ids = {
34055a1d80aSGerd Hoffmann .bustype = const_le16(BUS_VIRTUAL),
34155a1d80aSGerd Hoffmann .vendor = const_le16(0x0627), /* same we use for usb hid devices */
34255a1d80aSGerd Hoffmann .product = const_le16(0x0002),
34355a1d80aSGerd Hoffmann .version = const_le16(0x0001),
34455a1d80aSGerd Hoffmann },
34555a1d80aSGerd Hoffmann },{
34655a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS,
34755a1d80aSGerd Hoffmann .subsel = EV_REL,
34855a1d80aSGerd Hoffmann .size = 1,
34955a1d80aSGerd Hoffmann .u.bitmap = {
35055a1d80aSGerd Hoffmann (1 << REL_X) | (1 << REL_Y),
35155a1d80aSGerd Hoffmann },
35255a1d80aSGerd Hoffmann },
35355a1d80aSGerd Hoffmann { /* end of list */ },
35455a1d80aSGerd Hoffmann };
35555a1d80aSGerd Hoffmann
356f4924974SGerd Hoffmann static struct virtio_input_config virtio_mouse_config_v2[] = {
357f4924974SGerd Hoffmann {
358f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_NAME,
359f4924974SGerd Hoffmann .size = sizeof(VIRTIO_ID_NAME_MOUSE),
360f4924974SGerd Hoffmann .u.string = VIRTIO_ID_NAME_MOUSE,
361f4924974SGerd Hoffmann },{
362f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
363f4924974SGerd Hoffmann .size = sizeof(struct virtio_input_devids),
364f4924974SGerd Hoffmann .u.ids = {
365f4924974SGerd Hoffmann .bustype = const_le16(BUS_VIRTUAL),
366f4924974SGerd Hoffmann .vendor = const_le16(0x0627), /* same we use for usb hid devices */
367f4924974SGerd Hoffmann .product = const_le16(0x0002),
368f4924974SGerd Hoffmann .version = const_le16(0x0002),
369f4924974SGerd Hoffmann },
370f4924974SGerd Hoffmann },{
371f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS,
372f4924974SGerd Hoffmann .subsel = EV_REL,
373f4924974SGerd Hoffmann .size = 2,
374f4924974SGerd Hoffmann .u.bitmap = {
375f4924974SGerd Hoffmann (1 << REL_X) | (1 << REL_Y),
376f4924974SGerd Hoffmann (1 << (REL_WHEEL - 8))
377f4924974SGerd Hoffmann },
378f4924974SGerd Hoffmann },
379f4924974SGerd Hoffmann { /* end of list */ },
380f4924974SGerd Hoffmann };
381f4924974SGerd Hoffmann
3829eb5c799SRichard Henderson static const Property virtio_mouse_properties[] = {
383f4924974SGerd Hoffmann DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
384f4924974SGerd Hoffmann };
385f4924974SGerd Hoffmann
virtio_mouse_class_init(ObjectClass * klass,const void * data)386*12d1a768SPhilippe Mathieu-Daudé static void virtio_mouse_class_init(ObjectClass *klass, const void *data)
387f4924974SGerd Hoffmann {
388f4924974SGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass);
389f4924974SGerd Hoffmann
3904f67d30bSMarc-André Lureau device_class_set_props(dc, virtio_mouse_properties);
391f4924974SGerd Hoffmann }
392f4924974SGerd Hoffmann
virtio_mouse_init(Object * obj)39355a1d80aSGerd Hoffmann static void virtio_mouse_init(Object *obj)
39455a1d80aSGerd Hoffmann {
39555a1d80aSGerd Hoffmann VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
39655a1d80aSGerd Hoffmann VirtIOInput *vinput = VIRTIO_INPUT(obj);
39755a1d80aSGerd Hoffmann
39855a1d80aSGerd Hoffmann vhid->handler = &virtio_mouse_handler;
399f4924974SGerd Hoffmann virtio_input_init_config(vinput, vhid->wheel_axis
400f4924974SGerd Hoffmann ? virtio_mouse_config_v2
401f4924974SGerd Hoffmann : virtio_mouse_config_v1);
402944ae6d9SSergio Lopez virtio_input_extend_config(vinput, keymap_button,
403944ae6d9SSergio Lopez ARRAY_SIZE(keymap_button),
404944ae6d9SSergio Lopez VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
40555a1d80aSGerd Hoffmann }
40655a1d80aSGerd Hoffmann
40755a1d80aSGerd Hoffmann static const TypeInfo virtio_mouse_info = {
40855a1d80aSGerd Hoffmann .name = TYPE_VIRTIO_MOUSE,
40955a1d80aSGerd Hoffmann .parent = TYPE_VIRTIO_INPUT_HID,
41055a1d80aSGerd Hoffmann .instance_size = sizeof(VirtIOInputHID),
41155a1d80aSGerd Hoffmann .instance_init = virtio_mouse_init,
412f4924974SGerd Hoffmann .class_init = virtio_mouse_class_init,
41355a1d80aSGerd Hoffmann };
41455a1d80aSGerd Hoffmann
41555a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
41655a1d80aSGerd Hoffmann
417b1be65f6SPhilippe Mathieu-Daudé static const QemuInputHandler virtio_tablet_handler = {
41855a1d80aSGerd Hoffmann .name = VIRTIO_ID_NAME_TABLET,
41955a1d80aSGerd Hoffmann .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
42055a1d80aSGerd Hoffmann .event = virtio_input_handle_event,
42155a1d80aSGerd Hoffmann .sync = virtio_input_handle_sync,
42255a1d80aSGerd Hoffmann };
42355a1d80aSGerd Hoffmann
424f4924974SGerd Hoffmann static struct virtio_input_config virtio_tablet_config_v1[] = {
42555a1d80aSGerd Hoffmann {
42655a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_NAME,
42755a1d80aSGerd Hoffmann .size = sizeof(VIRTIO_ID_NAME_TABLET),
42855a1d80aSGerd Hoffmann .u.string = VIRTIO_ID_NAME_TABLET,
42955a1d80aSGerd Hoffmann },{
43055a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
43155a1d80aSGerd Hoffmann .size = sizeof(struct virtio_input_devids),
43255a1d80aSGerd Hoffmann .u.ids = {
43355a1d80aSGerd Hoffmann .bustype = const_le16(BUS_VIRTUAL),
43455a1d80aSGerd Hoffmann .vendor = const_le16(0x0627), /* same we use for usb hid devices */
43555a1d80aSGerd Hoffmann .product = const_le16(0x0003),
43655a1d80aSGerd Hoffmann .version = const_le16(0x0001),
43755a1d80aSGerd Hoffmann },
43855a1d80aSGerd Hoffmann },{
43955a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS,
44055a1d80aSGerd Hoffmann .subsel = EV_ABS,
44155a1d80aSGerd Hoffmann .size = 1,
44255a1d80aSGerd Hoffmann .u.bitmap = {
44355a1d80aSGerd Hoffmann (1 << ABS_X) | (1 << ABS_Y),
44455a1d80aSGerd Hoffmann },
44555a1d80aSGerd Hoffmann },{
44655a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ABS_INFO,
44755a1d80aSGerd Hoffmann .subsel = ABS_X,
44855a1d80aSGerd Hoffmann .size = sizeof(virtio_input_absinfo),
4499cfa7ab9SPhilippe Voinov .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
4509cfa7ab9SPhilippe Voinov .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
45155a1d80aSGerd Hoffmann },{
45255a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ABS_INFO,
45355a1d80aSGerd Hoffmann .subsel = ABS_Y,
45455a1d80aSGerd Hoffmann .size = sizeof(virtio_input_absinfo),
4559cfa7ab9SPhilippe Voinov .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
4569cfa7ab9SPhilippe Voinov .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
45755a1d80aSGerd Hoffmann },
45855a1d80aSGerd Hoffmann { /* end of list */ },
45955a1d80aSGerd Hoffmann };
46055a1d80aSGerd Hoffmann
461f4924974SGerd Hoffmann static struct virtio_input_config virtio_tablet_config_v2[] = {
462f4924974SGerd Hoffmann {
463f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_NAME,
464f4924974SGerd Hoffmann .size = sizeof(VIRTIO_ID_NAME_TABLET),
465f4924974SGerd Hoffmann .u.string = VIRTIO_ID_NAME_TABLET,
466f4924974SGerd Hoffmann },{
467f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
468f4924974SGerd Hoffmann .size = sizeof(struct virtio_input_devids),
469f4924974SGerd Hoffmann .u.ids = {
470f4924974SGerd Hoffmann .bustype = const_le16(BUS_VIRTUAL),
471f4924974SGerd Hoffmann .vendor = const_le16(0x0627), /* same we use for usb hid devices */
472f4924974SGerd Hoffmann .product = const_le16(0x0003),
473f4924974SGerd Hoffmann .version = const_le16(0x0002),
474f4924974SGerd Hoffmann },
475f4924974SGerd Hoffmann },{
476f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS,
477f4924974SGerd Hoffmann .subsel = EV_ABS,
478f4924974SGerd Hoffmann .size = 1,
479f4924974SGerd Hoffmann .u.bitmap = {
480f4924974SGerd Hoffmann (1 << ABS_X) | (1 << ABS_Y),
481f4924974SGerd Hoffmann },
482f4924974SGerd Hoffmann },{
483f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS,
484f4924974SGerd Hoffmann .subsel = EV_REL,
485f4924974SGerd Hoffmann .size = 2,
486f4924974SGerd Hoffmann .u.bitmap = {
487f4924974SGerd Hoffmann 0,
488f4924974SGerd Hoffmann (1 << (REL_WHEEL - 8))
489f4924974SGerd Hoffmann },
490f4924974SGerd Hoffmann },{
491f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ABS_INFO,
492f4924974SGerd Hoffmann .subsel = ABS_X,
493f4924974SGerd Hoffmann .size = sizeof(virtio_input_absinfo),
494f4924974SGerd Hoffmann .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
495f4924974SGerd Hoffmann .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
496f4924974SGerd Hoffmann },{
497f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ABS_INFO,
498f4924974SGerd Hoffmann .subsel = ABS_Y,
499f4924974SGerd Hoffmann .size = sizeof(virtio_input_absinfo),
500f4924974SGerd Hoffmann .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
501f4924974SGerd Hoffmann .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
502f4924974SGerd Hoffmann },
503f4924974SGerd Hoffmann { /* end of list */ },
504f4924974SGerd Hoffmann };
505f4924974SGerd Hoffmann
5069eb5c799SRichard Henderson static const Property virtio_tablet_properties[] = {
507f4924974SGerd Hoffmann DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
508f4924974SGerd Hoffmann };
509f4924974SGerd Hoffmann
virtio_tablet_class_init(ObjectClass * klass,const void * data)510*12d1a768SPhilippe Mathieu-Daudé static void virtio_tablet_class_init(ObjectClass *klass, const void *data)
511f4924974SGerd Hoffmann {
512f4924974SGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass);
513f4924974SGerd Hoffmann
5144f67d30bSMarc-André Lureau device_class_set_props(dc, virtio_tablet_properties);
515f4924974SGerd Hoffmann }
516f4924974SGerd Hoffmann
virtio_tablet_init(Object * obj)51755a1d80aSGerd Hoffmann static void virtio_tablet_init(Object *obj)
51855a1d80aSGerd Hoffmann {
51955a1d80aSGerd Hoffmann VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
52055a1d80aSGerd Hoffmann VirtIOInput *vinput = VIRTIO_INPUT(obj);
52155a1d80aSGerd Hoffmann
52255a1d80aSGerd Hoffmann vhid->handler = &virtio_tablet_handler;
523f4924974SGerd Hoffmann virtio_input_init_config(vinput, vhid->wheel_axis
524f4924974SGerd Hoffmann ? virtio_tablet_config_v2
525f4924974SGerd Hoffmann : virtio_tablet_config_v1);
526944ae6d9SSergio Lopez virtio_input_extend_config(vinput, keymap_button,
527944ae6d9SSergio Lopez ARRAY_SIZE(keymap_button),
528944ae6d9SSergio Lopez VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
52955a1d80aSGerd Hoffmann }
53055a1d80aSGerd Hoffmann
53155a1d80aSGerd Hoffmann static const TypeInfo virtio_tablet_info = {
53255a1d80aSGerd Hoffmann .name = TYPE_VIRTIO_TABLET,
53355a1d80aSGerd Hoffmann .parent = TYPE_VIRTIO_INPUT_HID,
53455a1d80aSGerd Hoffmann .instance_size = sizeof(VirtIOInputHID),
53555a1d80aSGerd Hoffmann .instance_init = virtio_tablet_init,
536f4924974SGerd Hoffmann .class_init = virtio_tablet_class_init,
53755a1d80aSGerd Hoffmann };
53855a1d80aSGerd Hoffmann
53955a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */
54055a1d80aSGerd Hoffmann
541b1be65f6SPhilippe Mathieu-Daudé static const QemuInputHandler virtio_multitouch_handler = {
5428e9ebd75SSergio Lopez .name = VIRTIO_ID_NAME_MULTITOUCH,
5438e9ebd75SSergio Lopez .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_MTT,
5448e9ebd75SSergio Lopez .event = virtio_input_handle_event,
5458e9ebd75SSergio Lopez .sync = virtio_input_handle_sync,
5468e9ebd75SSergio Lopez };
5478e9ebd75SSergio Lopez
5488e9ebd75SSergio Lopez static struct virtio_input_config virtio_multitouch_config[] = {
5498e9ebd75SSergio Lopez {
5508e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ID_NAME,
5518e9ebd75SSergio Lopez .size = sizeof(VIRTIO_ID_NAME_MULTITOUCH),
5528e9ebd75SSergio Lopez .u.string = VIRTIO_ID_NAME_MULTITOUCH,
5538e9ebd75SSergio Lopez },{
5548e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
5558e9ebd75SSergio Lopez .size = sizeof(struct virtio_input_devids),
5568e9ebd75SSergio Lopez .u.ids = {
5578e9ebd75SSergio Lopez .bustype = const_le16(BUS_VIRTUAL),
5588e9ebd75SSergio Lopez .vendor = const_le16(0x0627), /* same we use for usb hid devices */
5598e9ebd75SSergio Lopez .product = const_le16(0x0003),
5608e9ebd75SSergio Lopez .version = const_le16(0x0001),
5618e9ebd75SSergio Lopez },
5628e9ebd75SSergio Lopez },{
5638e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ABS_INFO,
5648e9ebd75SSergio Lopez .subsel = ABS_MT_SLOT,
5658e9ebd75SSergio Lopez .size = sizeof(virtio_input_absinfo),
5668e9ebd75SSergio Lopez .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
5678e9ebd75SSergio Lopez .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
5688e9ebd75SSergio Lopez },{
5698e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ABS_INFO,
5708e9ebd75SSergio Lopez .subsel = ABS_MT_TRACKING_ID,
5718e9ebd75SSergio Lopez .size = sizeof(virtio_input_absinfo),
5728e9ebd75SSergio Lopez .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
5738e9ebd75SSergio Lopez .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
5748e9ebd75SSergio Lopez },{
5758e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ABS_INFO,
5768e9ebd75SSergio Lopez .subsel = ABS_MT_POSITION_X,
5778e9ebd75SSergio Lopez .size = sizeof(virtio_input_absinfo),
5788e9ebd75SSergio Lopez .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
5798e9ebd75SSergio Lopez .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
5808e9ebd75SSergio Lopez },{
5818e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ABS_INFO,
5828e9ebd75SSergio Lopez .subsel = ABS_MT_POSITION_Y,
5838e9ebd75SSergio Lopez .size = sizeof(virtio_input_absinfo),
5848e9ebd75SSergio Lopez .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
5858e9ebd75SSergio Lopez .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
5868e9ebd75SSergio Lopez },
5878e9ebd75SSergio Lopez { /* end of list */ },
5888e9ebd75SSergio Lopez };
5898e9ebd75SSergio Lopez
virtio_multitouch_init(Object * obj)5908e9ebd75SSergio Lopez static void virtio_multitouch_init(Object *obj)
5918e9ebd75SSergio Lopez {
5928e9ebd75SSergio Lopez VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
5938e9ebd75SSergio Lopez VirtIOInput *vinput = VIRTIO_INPUT(obj);
5948e9ebd75SSergio Lopez unsigned short abs_props[] = {
5958e9ebd75SSergio Lopez INPUT_PROP_DIRECT,
5968e9ebd75SSergio Lopez };
5978e9ebd75SSergio Lopez unsigned short abs_bits[] = {
5988e9ebd75SSergio Lopez ABS_MT_SLOT,
5998e9ebd75SSergio Lopez ABS_MT_TRACKING_ID,
6008e9ebd75SSergio Lopez ABS_MT_POSITION_X,
6018e9ebd75SSergio Lopez ABS_MT_POSITION_Y,
6028e9ebd75SSergio Lopez };
6038e9ebd75SSergio Lopez
6048e9ebd75SSergio Lopez vhid->handler = &virtio_multitouch_handler;
6058e9ebd75SSergio Lopez virtio_input_init_config(vinput, virtio_multitouch_config);
6068e9ebd75SSergio Lopez virtio_input_extend_config(vinput, keymap_button,
6078e9ebd75SSergio Lopez ARRAY_SIZE(keymap_button),
6088e9ebd75SSergio Lopez VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
6098e9ebd75SSergio Lopez virtio_input_extend_config(vinput, abs_props,
6108e9ebd75SSergio Lopez ARRAY_SIZE(abs_props),
6118e9ebd75SSergio Lopez VIRTIO_INPUT_CFG_PROP_BITS, 0);
6128e9ebd75SSergio Lopez virtio_input_extend_config(vinput, abs_bits,
6138e9ebd75SSergio Lopez ARRAY_SIZE(abs_bits),
6148e9ebd75SSergio Lopez VIRTIO_INPUT_CFG_EV_BITS, EV_ABS);
6158e9ebd75SSergio Lopez }
6168e9ebd75SSergio Lopez
6178e9ebd75SSergio Lopez static const TypeInfo virtio_multitouch_info = {
6188e9ebd75SSergio Lopez .name = TYPE_VIRTIO_MULTITOUCH,
6198e9ebd75SSergio Lopez .parent = TYPE_VIRTIO_INPUT_HID,
6208e9ebd75SSergio Lopez .instance_size = sizeof(VirtIOInputHID),
6218e9ebd75SSergio Lopez .instance_init = virtio_multitouch_init,
6228e9ebd75SSergio Lopez };
6238e9ebd75SSergio Lopez
6248e9ebd75SSergio Lopez /* ----------------------------------------------------------------- */
6258e9ebd75SSergio Lopez
virtio_register_types(void)62655a1d80aSGerd Hoffmann static void virtio_register_types(void)
62755a1d80aSGerd Hoffmann {
62855a1d80aSGerd Hoffmann type_register_static(&virtio_input_hid_info);
62955a1d80aSGerd Hoffmann type_register_static(&virtio_keyboard_info);
63055a1d80aSGerd Hoffmann type_register_static(&virtio_mouse_info);
63155a1d80aSGerd Hoffmann type_register_static(&virtio_tablet_info);
6328e9ebd75SSergio Lopez type_register_static(&virtio_multitouch_info);
63355a1d80aSGerd Hoffmann }
63455a1d80aSGerd Hoffmann
63555a1d80aSGerd Hoffmann type_init(virtio_register_types)
636