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" 22*8e9ebd75SSergio 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, 34*8e9ebd75SSergio 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 47*8e9ebd75SSergio Lopez static const unsigned short axismap_tch[INPUT_AXIS__MAX] = { 48*8e9ebd75SSergio Lopez [INPUT_AXIS_X] = ABS_MT_POSITION_X, 49*8e9ebd75SSergio Lopez [INPUT_AXIS_Y] = ABS_MT_POSITION_Y, 50*8e9ebd75SSergio Lopez }; 51*8e9ebd75SSergio Lopez 5255a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */ 5355a1d80aSGerd Hoffmann 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 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; 91*8e9ebd75SSergio 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; 148*8e9ebd75SSergio Lopez case INPUT_EVENT_KIND_MTT: 149*8e9ebd75SSergio Lopez mtt = evt->u.mtt.data; 150*8e9ebd75SSergio Lopez if (mtt->type == INPUT_MULTI_TOUCH_TYPE_DATA) { 151*8e9ebd75SSergio Lopez event.type = cpu_to_le16(EV_ABS); 152*8e9ebd75SSergio Lopez event.code = cpu_to_le16(axismap_tch[mtt->axis]); 153*8e9ebd75SSergio Lopez event.value = cpu_to_le32(mtt->value); 154*8e9ebd75SSergio Lopez virtio_input_send(vinput, &event); 155*8e9ebd75SSergio Lopez } else { 156*8e9ebd75SSergio Lopez event.type = cpu_to_le16(EV_ABS); 157*8e9ebd75SSergio Lopez event.code = cpu_to_le16(ABS_MT_SLOT); 158*8e9ebd75SSergio Lopez event.value = cpu_to_le32(mtt->slot); 159*8e9ebd75SSergio Lopez virtio_input_send(vinput, &event); 160*8e9ebd75SSergio Lopez event.type = cpu_to_le16(EV_ABS); 161*8e9ebd75SSergio Lopez event.code = cpu_to_le16(ABS_MT_TRACKING_ID); 162*8e9ebd75SSergio Lopez event.value = cpu_to_le32(mtt->tracking_id); 163*8e9ebd75SSergio Lopez virtio_input_send(vinput, &event); 164*8e9ebd75SSergio Lopez } 165*8e9ebd75SSergio Lopez break; 16655a1d80aSGerd Hoffmann default: 16755a1d80aSGerd Hoffmann /* keep gcc happy */ 16855a1d80aSGerd Hoffmann break; 16955a1d80aSGerd Hoffmann } 17055a1d80aSGerd Hoffmann } 17155a1d80aSGerd Hoffmann 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 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 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 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 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 2405cce1733SGerd Hoffmann static Property virtio_input_hid_properties[] = { 2415cce1733SGerd Hoffmann DEFINE_PROP_STRING("display", VirtIOInputHID, display), 2425cce1733SGerd Hoffmann DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0), 2432a19b229SLin Ma DEFINE_PROP_END_OF_LIST(), 2445cce1733SGerd Hoffmann }; 2455cce1733SGerd Hoffmann 24655a1d80aSGerd Hoffmann static void virtio_input_hid_class_init(ObjectClass *klass, void *data) 24755a1d80aSGerd Hoffmann { 2485cce1733SGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass); 24955a1d80aSGerd Hoffmann VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass); 25055a1d80aSGerd Hoffmann 2514f67d30bSMarc-André Lureau device_class_set_props(dc, virtio_input_hid_properties); 25255a1d80aSGerd Hoffmann vic->realize = virtio_input_hid_realize; 25355a1d80aSGerd Hoffmann vic->unrealize = virtio_input_hid_unrealize; 25455a1d80aSGerd Hoffmann vic->change_active = virtio_input_hid_change_active; 25555a1d80aSGerd Hoffmann vic->handle_status = virtio_input_hid_handle_status; 25655a1d80aSGerd Hoffmann } 25755a1d80aSGerd Hoffmann 25855a1d80aSGerd Hoffmann static const TypeInfo virtio_input_hid_info = { 25955a1d80aSGerd Hoffmann .name = TYPE_VIRTIO_INPUT_HID, 26055a1d80aSGerd Hoffmann .parent = TYPE_VIRTIO_INPUT, 26155a1d80aSGerd Hoffmann .instance_size = sizeof(VirtIOInputHID), 26255a1d80aSGerd Hoffmann .class_init = virtio_input_hid_class_init, 26355a1d80aSGerd Hoffmann .abstract = true, 26455a1d80aSGerd Hoffmann }; 26555a1d80aSGerd Hoffmann 26655a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */ 26755a1d80aSGerd Hoffmann 26855a1d80aSGerd Hoffmann static QemuInputHandler virtio_keyboard_handler = { 26955a1d80aSGerd Hoffmann .name = VIRTIO_ID_NAME_KEYBOARD, 27055a1d80aSGerd Hoffmann .mask = INPUT_EVENT_MASK_KEY, 27155a1d80aSGerd Hoffmann .event = virtio_input_handle_event, 27255a1d80aSGerd Hoffmann .sync = virtio_input_handle_sync, 27355a1d80aSGerd Hoffmann }; 27455a1d80aSGerd Hoffmann 27555a1d80aSGerd Hoffmann static struct virtio_input_config virtio_keyboard_config[] = { 27655a1d80aSGerd Hoffmann { 27755a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_NAME, 27855a1d80aSGerd Hoffmann .size = sizeof(VIRTIO_ID_NAME_KEYBOARD), 27955a1d80aSGerd Hoffmann .u.string = VIRTIO_ID_NAME_KEYBOARD, 28055a1d80aSGerd Hoffmann },{ 28155a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 28255a1d80aSGerd Hoffmann .size = sizeof(struct virtio_input_devids), 28355a1d80aSGerd Hoffmann .u.ids = { 28455a1d80aSGerd Hoffmann .bustype = const_le16(BUS_VIRTUAL), 28555a1d80aSGerd Hoffmann .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 28655a1d80aSGerd Hoffmann .product = const_le16(0x0001), 28755a1d80aSGerd Hoffmann .version = const_le16(0x0001), 28855a1d80aSGerd Hoffmann }, 28955a1d80aSGerd Hoffmann },{ 29055a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS, 29155a1d80aSGerd Hoffmann .subsel = EV_REP, 29255a1d80aSGerd Hoffmann .size = 1, 29355a1d80aSGerd Hoffmann },{ 29455a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS, 29555a1d80aSGerd Hoffmann .subsel = EV_LED, 29655a1d80aSGerd Hoffmann .size = 1, 29755a1d80aSGerd Hoffmann .u.bitmap = { 29855a1d80aSGerd Hoffmann (1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL), 29955a1d80aSGerd Hoffmann }, 30055a1d80aSGerd Hoffmann }, 30155a1d80aSGerd Hoffmann { /* end of list */ }, 30255a1d80aSGerd Hoffmann }; 30355a1d80aSGerd Hoffmann 30455a1d80aSGerd Hoffmann static void virtio_keyboard_init(Object *obj) 30555a1d80aSGerd Hoffmann { 30655a1d80aSGerd Hoffmann VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj); 30755a1d80aSGerd Hoffmann VirtIOInput *vinput = VIRTIO_INPUT(obj); 30855a1d80aSGerd Hoffmann 30955a1d80aSGerd Hoffmann vhid->handler = &virtio_keyboard_handler; 31055a1d80aSGerd Hoffmann virtio_input_init_config(vinput, virtio_keyboard_config); 311944ae6d9SSergio Lopez virtio_input_extend_config(vinput, qemu_input_map_qcode_to_linux, 312944ae6d9SSergio Lopez qemu_input_map_qcode_to_linux_len, 313944ae6d9SSergio Lopez VIRTIO_INPUT_CFG_EV_BITS, EV_KEY); 31455a1d80aSGerd Hoffmann } 31555a1d80aSGerd Hoffmann 31655a1d80aSGerd Hoffmann static const TypeInfo virtio_keyboard_info = { 31755a1d80aSGerd Hoffmann .name = TYPE_VIRTIO_KEYBOARD, 31855a1d80aSGerd Hoffmann .parent = TYPE_VIRTIO_INPUT_HID, 31955a1d80aSGerd Hoffmann .instance_size = sizeof(VirtIOInputHID), 32055a1d80aSGerd Hoffmann .instance_init = virtio_keyboard_init, 32155a1d80aSGerd Hoffmann }; 32255a1d80aSGerd Hoffmann 32355a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */ 32455a1d80aSGerd Hoffmann 32555a1d80aSGerd Hoffmann static QemuInputHandler virtio_mouse_handler = { 32655a1d80aSGerd Hoffmann .name = VIRTIO_ID_NAME_MOUSE, 32755a1d80aSGerd Hoffmann .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, 32855a1d80aSGerd Hoffmann .event = virtio_input_handle_event, 32955a1d80aSGerd Hoffmann .sync = virtio_input_handle_sync, 33055a1d80aSGerd Hoffmann }; 33155a1d80aSGerd Hoffmann 332f4924974SGerd Hoffmann static struct virtio_input_config virtio_mouse_config_v1[] = { 33355a1d80aSGerd Hoffmann { 33455a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_NAME, 33555a1d80aSGerd Hoffmann .size = sizeof(VIRTIO_ID_NAME_MOUSE), 33655a1d80aSGerd Hoffmann .u.string = VIRTIO_ID_NAME_MOUSE, 33755a1d80aSGerd Hoffmann },{ 33855a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 33955a1d80aSGerd Hoffmann .size = sizeof(struct virtio_input_devids), 34055a1d80aSGerd Hoffmann .u.ids = { 34155a1d80aSGerd Hoffmann .bustype = const_le16(BUS_VIRTUAL), 34255a1d80aSGerd Hoffmann .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 34355a1d80aSGerd Hoffmann .product = const_le16(0x0002), 34455a1d80aSGerd Hoffmann .version = const_le16(0x0001), 34555a1d80aSGerd Hoffmann }, 34655a1d80aSGerd Hoffmann },{ 34755a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS, 34855a1d80aSGerd Hoffmann .subsel = EV_REL, 34955a1d80aSGerd Hoffmann .size = 1, 35055a1d80aSGerd Hoffmann .u.bitmap = { 35155a1d80aSGerd Hoffmann (1 << REL_X) | (1 << REL_Y), 35255a1d80aSGerd Hoffmann }, 35355a1d80aSGerd Hoffmann }, 35455a1d80aSGerd Hoffmann { /* end of list */ }, 35555a1d80aSGerd Hoffmann }; 35655a1d80aSGerd Hoffmann 357f4924974SGerd Hoffmann static struct virtio_input_config virtio_mouse_config_v2[] = { 358f4924974SGerd Hoffmann { 359f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_NAME, 360f4924974SGerd Hoffmann .size = sizeof(VIRTIO_ID_NAME_MOUSE), 361f4924974SGerd Hoffmann .u.string = VIRTIO_ID_NAME_MOUSE, 362f4924974SGerd Hoffmann },{ 363f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 364f4924974SGerd Hoffmann .size = sizeof(struct virtio_input_devids), 365f4924974SGerd Hoffmann .u.ids = { 366f4924974SGerd Hoffmann .bustype = const_le16(BUS_VIRTUAL), 367f4924974SGerd Hoffmann .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 368f4924974SGerd Hoffmann .product = const_le16(0x0002), 369f4924974SGerd Hoffmann .version = const_le16(0x0002), 370f4924974SGerd Hoffmann }, 371f4924974SGerd Hoffmann },{ 372f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS, 373f4924974SGerd Hoffmann .subsel = EV_REL, 374f4924974SGerd Hoffmann .size = 2, 375f4924974SGerd Hoffmann .u.bitmap = { 376f4924974SGerd Hoffmann (1 << REL_X) | (1 << REL_Y), 377f4924974SGerd Hoffmann (1 << (REL_WHEEL - 8)) 378f4924974SGerd Hoffmann }, 379f4924974SGerd Hoffmann }, 380f4924974SGerd Hoffmann { /* end of list */ }, 381f4924974SGerd Hoffmann }; 382f4924974SGerd Hoffmann 383f4924974SGerd Hoffmann static Property virtio_mouse_properties[] = { 384f4924974SGerd Hoffmann DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true), 385f4924974SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 386f4924974SGerd Hoffmann }; 387f4924974SGerd Hoffmann 388f4924974SGerd Hoffmann static void virtio_mouse_class_init(ObjectClass *klass, void *data) 389f4924974SGerd Hoffmann { 390f4924974SGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass); 391f4924974SGerd Hoffmann 3924f67d30bSMarc-André Lureau device_class_set_props(dc, virtio_mouse_properties); 393f4924974SGerd Hoffmann } 394f4924974SGerd Hoffmann 39555a1d80aSGerd Hoffmann static void virtio_mouse_init(Object *obj) 39655a1d80aSGerd Hoffmann { 39755a1d80aSGerd Hoffmann VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj); 39855a1d80aSGerd Hoffmann VirtIOInput *vinput = VIRTIO_INPUT(obj); 39955a1d80aSGerd Hoffmann 40055a1d80aSGerd Hoffmann vhid->handler = &virtio_mouse_handler; 401f4924974SGerd Hoffmann virtio_input_init_config(vinput, vhid->wheel_axis 402f4924974SGerd Hoffmann ? virtio_mouse_config_v2 403f4924974SGerd Hoffmann : virtio_mouse_config_v1); 404944ae6d9SSergio Lopez virtio_input_extend_config(vinput, keymap_button, 405944ae6d9SSergio Lopez ARRAY_SIZE(keymap_button), 406944ae6d9SSergio Lopez VIRTIO_INPUT_CFG_EV_BITS, EV_KEY); 40755a1d80aSGerd Hoffmann } 40855a1d80aSGerd Hoffmann 40955a1d80aSGerd Hoffmann static const TypeInfo virtio_mouse_info = { 41055a1d80aSGerd Hoffmann .name = TYPE_VIRTIO_MOUSE, 41155a1d80aSGerd Hoffmann .parent = TYPE_VIRTIO_INPUT_HID, 41255a1d80aSGerd Hoffmann .instance_size = sizeof(VirtIOInputHID), 41355a1d80aSGerd Hoffmann .instance_init = virtio_mouse_init, 414f4924974SGerd Hoffmann .class_init = virtio_mouse_class_init, 41555a1d80aSGerd Hoffmann }; 41655a1d80aSGerd Hoffmann 41755a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */ 41855a1d80aSGerd Hoffmann 41955a1d80aSGerd Hoffmann static QemuInputHandler virtio_tablet_handler = { 42055a1d80aSGerd Hoffmann .name = VIRTIO_ID_NAME_TABLET, 42155a1d80aSGerd Hoffmann .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS, 42255a1d80aSGerd Hoffmann .event = virtio_input_handle_event, 42355a1d80aSGerd Hoffmann .sync = virtio_input_handle_sync, 42455a1d80aSGerd Hoffmann }; 42555a1d80aSGerd Hoffmann 426f4924974SGerd Hoffmann static struct virtio_input_config virtio_tablet_config_v1[] = { 42755a1d80aSGerd Hoffmann { 42855a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_NAME, 42955a1d80aSGerd Hoffmann .size = sizeof(VIRTIO_ID_NAME_TABLET), 43055a1d80aSGerd Hoffmann .u.string = VIRTIO_ID_NAME_TABLET, 43155a1d80aSGerd Hoffmann },{ 43255a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 43355a1d80aSGerd Hoffmann .size = sizeof(struct virtio_input_devids), 43455a1d80aSGerd Hoffmann .u.ids = { 43555a1d80aSGerd Hoffmann .bustype = const_le16(BUS_VIRTUAL), 43655a1d80aSGerd Hoffmann .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 43755a1d80aSGerd Hoffmann .product = const_le16(0x0003), 43855a1d80aSGerd Hoffmann .version = const_le16(0x0001), 43955a1d80aSGerd Hoffmann }, 44055a1d80aSGerd Hoffmann },{ 44155a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS, 44255a1d80aSGerd Hoffmann .subsel = EV_ABS, 44355a1d80aSGerd Hoffmann .size = 1, 44455a1d80aSGerd Hoffmann .u.bitmap = { 44555a1d80aSGerd Hoffmann (1 << ABS_X) | (1 << ABS_Y), 44655a1d80aSGerd Hoffmann }, 44755a1d80aSGerd Hoffmann },{ 44855a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ABS_INFO, 44955a1d80aSGerd Hoffmann .subsel = ABS_X, 45055a1d80aSGerd Hoffmann .size = sizeof(virtio_input_absinfo), 4519cfa7ab9SPhilippe Voinov .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 4529cfa7ab9SPhilippe Voinov .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 45355a1d80aSGerd Hoffmann },{ 45455a1d80aSGerd Hoffmann .select = VIRTIO_INPUT_CFG_ABS_INFO, 45555a1d80aSGerd Hoffmann .subsel = ABS_Y, 45655a1d80aSGerd Hoffmann .size = sizeof(virtio_input_absinfo), 4579cfa7ab9SPhilippe Voinov .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 4589cfa7ab9SPhilippe Voinov .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 45955a1d80aSGerd Hoffmann }, 46055a1d80aSGerd Hoffmann { /* end of list */ }, 46155a1d80aSGerd Hoffmann }; 46255a1d80aSGerd Hoffmann 463f4924974SGerd Hoffmann static struct virtio_input_config virtio_tablet_config_v2[] = { 464f4924974SGerd Hoffmann { 465f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_NAME, 466f4924974SGerd Hoffmann .size = sizeof(VIRTIO_ID_NAME_TABLET), 467f4924974SGerd Hoffmann .u.string = VIRTIO_ID_NAME_TABLET, 468f4924974SGerd Hoffmann },{ 469f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 470f4924974SGerd Hoffmann .size = sizeof(struct virtio_input_devids), 471f4924974SGerd Hoffmann .u.ids = { 472f4924974SGerd Hoffmann .bustype = const_le16(BUS_VIRTUAL), 473f4924974SGerd Hoffmann .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 474f4924974SGerd Hoffmann .product = const_le16(0x0003), 475f4924974SGerd Hoffmann .version = const_le16(0x0002), 476f4924974SGerd Hoffmann }, 477f4924974SGerd Hoffmann },{ 478f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS, 479f4924974SGerd Hoffmann .subsel = EV_ABS, 480f4924974SGerd Hoffmann .size = 1, 481f4924974SGerd Hoffmann .u.bitmap = { 482f4924974SGerd Hoffmann (1 << ABS_X) | (1 << ABS_Y), 483f4924974SGerd Hoffmann }, 484f4924974SGerd Hoffmann },{ 485f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_EV_BITS, 486f4924974SGerd Hoffmann .subsel = EV_REL, 487f4924974SGerd Hoffmann .size = 2, 488f4924974SGerd Hoffmann .u.bitmap = { 489f4924974SGerd Hoffmann 0, 490f4924974SGerd Hoffmann (1 << (REL_WHEEL - 8)) 491f4924974SGerd Hoffmann }, 492f4924974SGerd Hoffmann },{ 493f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ABS_INFO, 494f4924974SGerd Hoffmann .subsel = ABS_X, 495f4924974SGerd Hoffmann .size = sizeof(virtio_input_absinfo), 496f4924974SGerd Hoffmann .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 497f4924974SGerd Hoffmann .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 498f4924974SGerd Hoffmann },{ 499f4924974SGerd Hoffmann .select = VIRTIO_INPUT_CFG_ABS_INFO, 500f4924974SGerd Hoffmann .subsel = ABS_Y, 501f4924974SGerd Hoffmann .size = sizeof(virtio_input_absinfo), 502f4924974SGerd Hoffmann .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 503f4924974SGerd Hoffmann .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 504f4924974SGerd Hoffmann }, 505f4924974SGerd Hoffmann { /* end of list */ }, 506f4924974SGerd Hoffmann }; 507f4924974SGerd Hoffmann 508f4924974SGerd Hoffmann static Property virtio_tablet_properties[] = { 509f4924974SGerd Hoffmann DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true), 510f4924974SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 511f4924974SGerd Hoffmann }; 512f4924974SGerd Hoffmann 513f4924974SGerd Hoffmann static void virtio_tablet_class_init(ObjectClass *klass, void *data) 514f4924974SGerd Hoffmann { 515f4924974SGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass); 516f4924974SGerd Hoffmann 5174f67d30bSMarc-André Lureau device_class_set_props(dc, virtio_tablet_properties); 518f4924974SGerd Hoffmann } 519f4924974SGerd Hoffmann 52055a1d80aSGerd Hoffmann static void virtio_tablet_init(Object *obj) 52155a1d80aSGerd Hoffmann { 52255a1d80aSGerd Hoffmann VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj); 52355a1d80aSGerd Hoffmann VirtIOInput *vinput = VIRTIO_INPUT(obj); 52455a1d80aSGerd Hoffmann 52555a1d80aSGerd Hoffmann vhid->handler = &virtio_tablet_handler; 526f4924974SGerd Hoffmann virtio_input_init_config(vinput, vhid->wheel_axis 527f4924974SGerd Hoffmann ? virtio_tablet_config_v2 528f4924974SGerd Hoffmann : virtio_tablet_config_v1); 529944ae6d9SSergio Lopez virtio_input_extend_config(vinput, keymap_button, 530944ae6d9SSergio Lopez ARRAY_SIZE(keymap_button), 531944ae6d9SSergio Lopez VIRTIO_INPUT_CFG_EV_BITS, EV_KEY); 53255a1d80aSGerd Hoffmann } 53355a1d80aSGerd Hoffmann 53455a1d80aSGerd Hoffmann static const TypeInfo virtio_tablet_info = { 53555a1d80aSGerd Hoffmann .name = TYPE_VIRTIO_TABLET, 53655a1d80aSGerd Hoffmann .parent = TYPE_VIRTIO_INPUT_HID, 53755a1d80aSGerd Hoffmann .instance_size = sizeof(VirtIOInputHID), 53855a1d80aSGerd Hoffmann .instance_init = virtio_tablet_init, 539f4924974SGerd Hoffmann .class_init = virtio_tablet_class_init, 54055a1d80aSGerd Hoffmann }; 54155a1d80aSGerd Hoffmann 54255a1d80aSGerd Hoffmann /* ----------------------------------------------------------------- */ 54355a1d80aSGerd Hoffmann 544*8e9ebd75SSergio Lopez static QemuInputHandler virtio_multitouch_handler = { 545*8e9ebd75SSergio Lopez .name = VIRTIO_ID_NAME_MULTITOUCH, 546*8e9ebd75SSergio Lopez .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_MTT, 547*8e9ebd75SSergio Lopez .event = virtio_input_handle_event, 548*8e9ebd75SSergio Lopez .sync = virtio_input_handle_sync, 549*8e9ebd75SSergio Lopez }; 550*8e9ebd75SSergio Lopez 551*8e9ebd75SSergio Lopez static struct virtio_input_config virtio_multitouch_config[] = { 552*8e9ebd75SSergio Lopez { 553*8e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ID_NAME, 554*8e9ebd75SSergio Lopez .size = sizeof(VIRTIO_ID_NAME_MULTITOUCH), 555*8e9ebd75SSergio Lopez .u.string = VIRTIO_ID_NAME_MULTITOUCH, 556*8e9ebd75SSergio Lopez },{ 557*8e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 558*8e9ebd75SSergio Lopez .size = sizeof(struct virtio_input_devids), 559*8e9ebd75SSergio Lopez .u.ids = { 560*8e9ebd75SSergio Lopez .bustype = const_le16(BUS_VIRTUAL), 561*8e9ebd75SSergio Lopez .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 562*8e9ebd75SSergio Lopez .product = const_le16(0x0003), 563*8e9ebd75SSergio Lopez .version = const_le16(0x0001), 564*8e9ebd75SSergio Lopez }, 565*8e9ebd75SSergio Lopez },{ 566*8e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ABS_INFO, 567*8e9ebd75SSergio Lopez .subsel = ABS_MT_SLOT, 568*8e9ebd75SSergio Lopez .size = sizeof(virtio_input_absinfo), 569*8e9ebd75SSergio Lopez .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN), 570*8e9ebd75SSergio Lopez .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX), 571*8e9ebd75SSergio Lopez },{ 572*8e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ABS_INFO, 573*8e9ebd75SSergio Lopez .subsel = ABS_MT_TRACKING_ID, 574*8e9ebd75SSergio Lopez .size = sizeof(virtio_input_absinfo), 575*8e9ebd75SSergio Lopez .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN), 576*8e9ebd75SSergio Lopez .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX), 577*8e9ebd75SSergio Lopez },{ 578*8e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ABS_INFO, 579*8e9ebd75SSergio Lopez .subsel = ABS_MT_POSITION_X, 580*8e9ebd75SSergio Lopez .size = sizeof(virtio_input_absinfo), 581*8e9ebd75SSergio Lopez .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 582*8e9ebd75SSergio Lopez .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 583*8e9ebd75SSergio Lopez },{ 584*8e9ebd75SSergio Lopez .select = VIRTIO_INPUT_CFG_ABS_INFO, 585*8e9ebd75SSergio Lopez .subsel = ABS_MT_POSITION_Y, 586*8e9ebd75SSergio Lopez .size = sizeof(virtio_input_absinfo), 587*8e9ebd75SSergio Lopez .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 588*8e9ebd75SSergio Lopez .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 589*8e9ebd75SSergio Lopez }, 590*8e9ebd75SSergio Lopez { /* end of list */ }, 591*8e9ebd75SSergio Lopez }; 592*8e9ebd75SSergio Lopez 593*8e9ebd75SSergio Lopez static void virtio_multitouch_init(Object *obj) 594*8e9ebd75SSergio Lopez { 595*8e9ebd75SSergio Lopez VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj); 596*8e9ebd75SSergio Lopez VirtIOInput *vinput = VIRTIO_INPUT(obj); 597*8e9ebd75SSergio Lopez unsigned short abs_props[] = { 598*8e9ebd75SSergio Lopez INPUT_PROP_DIRECT, 599*8e9ebd75SSergio Lopez }; 600*8e9ebd75SSergio Lopez unsigned short abs_bits[] = { 601*8e9ebd75SSergio Lopez ABS_MT_SLOT, 602*8e9ebd75SSergio Lopez ABS_MT_TRACKING_ID, 603*8e9ebd75SSergio Lopez ABS_MT_POSITION_X, 604*8e9ebd75SSergio Lopez ABS_MT_POSITION_Y, 605*8e9ebd75SSergio Lopez }; 606*8e9ebd75SSergio Lopez 607*8e9ebd75SSergio Lopez vhid->handler = &virtio_multitouch_handler; 608*8e9ebd75SSergio Lopez virtio_input_init_config(vinput, virtio_multitouch_config); 609*8e9ebd75SSergio Lopez virtio_input_extend_config(vinput, keymap_button, 610*8e9ebd75SSergio Lopez ARRAY_SIZE(keymap_button), 611*8e9ebd75SSergio Lopez VIRTIO_INPUT_CFG_EV_BITS, EV_KEY); 612*8e9ebd75SSergio Lopez virtio_input_extend_config(vinput, abs_props, 613*8e9ebd75SSergio Lopez ARRAY_SIZE(abs_props), 614*8e9ebd75SSergio Lopez VIRTIO_INPUT_CFG_PROP_BITS, 0); 615*8e9ebd75SSergio Lopez virtio_input_extend_config(vinput, abs_bits, 616*8e9ebd75SSergio Lopez ARRAY_SIZE(abs_bits), 617*8e9ebd75SSergio Lopez VIRTIO_INPUT_CFG_EV_BITS, EV_ABS); 618*8e9ebd75SSergio Lopez } 619*8e9ebd75SSergio Lopez 620*8e9ebd75SSergio Lopez static const TypeInfo virtio_multitouch_info = { 621*8e9ebd75SSergio Lopez .name = TYPE_VIRTIO_MULTITOUCH, 622*8e9ebd75SSergio Lopez .parent = TYPE_VIRTIO_INPUT_HID, 623*8e9ebd75SSergio Lopez .instance_size = sizeof(VirtIOInputHID), 624*8e9ebd75SSergio Lopez .instance_init = virtio_multitouch_init, 625*8e9ebd75SSergio Lopez }; 626*8e9ebd75SSergio Lopez 627*8e9ebd75SSergio Lopez /* ----------------------------------------------------------------- */ 628*8e9ebd75SSergio Lopez 62955a1d80aSGerd Hoffmann static void virtio_register_types(void) 63055a1d80aSGerd Hoffmann { 63155a1d80aSGerd Hoffmann type_register_static(&virtio_input_hid_info); 63255a1d80aSGerd Hoffmann type_register_static(&virtio_keyboard_info); 63355a1d80aSGerd Hoffmann type_register_static(&virtio_mouse_info); 63455a1d80aSGerd Hoffmann type_register_static(&virtio_tablet_info); 635*8e9ebd75SSergio Lopez type_register_static(&virtio_multitouch_info); 63655a1d80aSGerd Hoffmann } 63755a1d80aSGerd Hoffmann 63855a1d80aSGerd Hoffmann type_init(virtio_register_types) 639