1 /* 2 * This work is licensed under the terms of the GNU GPL, version 2 or 3 * (at your option) any later version. See the COPYING file in the 4 * top-level directory. 5 */ 6 7 #include "qemu/osdep.h" 8 #include "qemu/iov.h" 9 #include "qemu/module.h" 10 11 #include "hw/virtio/virtio.h" 12 #include "hw/qdev-properties.h" 13 #include "hw/virtio/virtio-input.h" 14 15 #include "ui/console.h" 16 17 #include "standard-headers/linux/input.h" 18 19 #define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard" 20 #define VIRTIO_ID_NAME_MOUSE "QEMU Virtio Mouse" 21 #define VIRTIO_ID_NAME_TABLET "QEMU Virtio Tablet" 22 #define VIRTIO_ID_NAME_MULTITOUCH "QEMU Virtio MultiTouch" 23 24 /* ----------------------------------------------------------------- */ 25 26 static const unsigned short keymap_button[INPUT_BUTTON__MAX] = { 27 [INPUT_BUTTON_LEFT] = BTN_LEFT, 28 [INPUT_BUTTON_RIGHT] = BTN_RIGHT, 29 [INPUT_BUTTON_MIDDLE] = BTN_MIDDLE, 30 [INPUT_BUTTON_WHEEL_UP] = BTN_GEAR_UP, 31 [INPUT_BUTTON_WHEEL_DOWN] = BTN_GEAR_DOWN, 32 [INPUT_BUTTON_SIDE] = BTN_SIDE, 33 [INPUT_BUTTON_EXTRA] = BTN_EXTRA, 34 [INPUT_BUTTON_TOUCH] = BTN_TOUCH, 35 }; 36 37 static const unsigned short axismap_rel[INPUT_AXIS__MAX] = { 38 [INPUT_AXIS_X] = REL_X, 39 [INPUT_AXIS_Y] = REL_Y, 40 }; 41 42 static const unsigned short axismap_abs[INPUT_AXIS__MAX] = { 43 [INPUT_AXIS_X] = ABS_X, 44 [INPUT_AXIS_Y] = ABS_Y, 45 }; 46 47 static const unsigned short axismap_tch[INPUT_AXIS__MAX] = { 48 [INPUT_AXIS_X] = ABS_MT_POSITION_X, 49 [INPUT_AXIS_Y] = ABS_MT_POSITION_Y, 50 }; 51 52 /* ----------------------------------------------------------------- */ 53 54 static void virtio_input_extend_config(VirtIOInput *vinput, 55 const unsigned short *map, 56 size_t mapsize, 57 uint8_t select, uint8_t subsel) 58 { 59 virtio_input_config ext; 60 int i, bit, byte, bmax = 0; 61 62 memset(&ext, 0, sizeof(ext)); 63 for (i = 0; i < mapsize; i++) { 64 bit = map[i]; 65 if (!bit) { 66 continue; 67 } 68 byte = bit / 8; 69 bit = bit % 8; 70 ext.u.bitmap[byte] |= (1 << bit); 71 if (bmax < byte+1) { 72 bmax = byte+1; 73 } 74 } 75 ext.select = select; 76 ext.subsel = subsel; 77 ext.size = bmax; 78 virtio_input_add_config(vinput, &ext); 79 } 80 81 static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src, 82 InputEvent *evt) 83 { 84 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev); 85 VirtIOInput *vinput = VIRTIO_INPUT(dev); 86 virtio_input_event event; 87 int qcode; 88 InputKeyEvent *key; 89 InputMoveEvent *move; 90 InputBtnEvent *btn; 91 InputMultiTouchEvent *mtt; 92 93 switch (evt->type) { 94 case INPUT_EVENT_KIND_KEY: 95 key = evt->u.key.data; 96 qcode = qemu_input_key_value_to_qcode(key->key); 97 if (qcode < qemu_input_map_qcode_to_linux_len && 98 qemu_input_map_qcode_to_linux[qcode]) { 99 event.type = cpu_to_le16(EV_KEY); 100 event.code = cpu_to_le16(qemu_input_map_qcode_to_linux[qcode]); 101 event.value = cpu_to_le32(key->down ? 1 : 0); 102 virtio_input_send(vinput, &event); 103 } else { 104 if (key->down) { 105 fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__, 106 qcode, QKeyCode_str(qcode)); 107 } 108 } 109 break; 110 case INPUT_EVENT_KIND_BTN: 111 btn = evt->u.btn.data; 112 if (vhid->wheel_axis && 113 (btn->button == INPUT_BUTTON_WHEEL_UP || 114 btn->button == INPUT_BUTTON_WHEEL_DOWN) && 115 btn->down) { 116 event.type = cpu_to_le16(EV_REL); 117 event.code = cpu_to_le16(REL_WHEEL); 118 event.value = cpu_to_le32(btn->button == INPUT_BUTTON_WHEEL_UP 119 ? 1 : -1); 120 virtio_input_send(vinput, &event); 121 } else if (keymap_button[btn->button]) { 122 event.type = cpu_to_le16(EV_KEY); 123 event.code = cpu_to_le16(keymap_button[btn->button]); 124 event.value = cpu_to_le32(btn->down ? 1 : 0); 125 virtio_input_send(vinput, &event); 126 } else { 127 if (btn->down) { 128 fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__, 129 btn->button, 130 InputButton_str(btn->button)); 131 } 132 } 133 break; 134 case INPUT_EVENT_KIND_REL: 135 move = evt->u.rel.data; 136 event.type = cpu_to_le16(EV_REL); 137 event.code = cpu_to_le16(axismap_rel[move->axis]); 138 event.value = cpu_to_le32(move->value); 139 virtio_input_send(vinput, &event); 140 break; 141 case INPUT_EVENT_KIND_ABS: 142 move = evt->u.abs.data; 143 event.type = cpu_to_le16(EV_ABS); 144 event.code = cpu_to_le16(axismap_abs[move->axis]); 145 event.value = cpu_to_le32(move->value); 146 virtio_input_send(vinput, &event); 147 break; 148 case INPUT_EVENT_KIND_MTT: 149 mtt = evt->u.mtt.data; 150 if (mtt->type == INPUT_MULTI_TOUCH_TYPE_DATA) { 151 event.type = cpu_to_le16(EV_ABS); 152 event.code = cpu_to_le16(axismap_tch[mtt->axis]); 153 event.value = cpu_to_le32(mtt->value); 154 virtio_input_send(vinput, &event); 155 } else { 156 event.type = cpu_to_le16(EV_ABS); 157 event.code = cpu_to_le16(ABS_MT_SLOT); 158 event.value = cpu_to_le32(mtt->slot); 159 virtio_input_send(vinput, &event); 160 event.type = cpu_to_le16(EV_ABS); 161 event.code = cpu_to_le16(ABS_MT_TRACKING_ID); 162 event.value = cpu_to_le32(mtt->tracking_id); 163 virtio_input_send(vinput, &event); 164 } 165 break; 166 default: 167 /* keep gcc happy */ 168 break; 169 } 170 } 171 172 static void virtio_input_handle_sync(DeviceState *dev) 173 { 174 VirtIOInput *vinput = VIRTIO_INPUT(dev); 175 virtio_input_event event = { 176 .type = cpu_to_le16(EV_SYN), 177 .code = cpu_to_le16(SYN_REPORT), 178 .value = 0, 179 }; 180 181 virtio_input_send(vinput, &event); 182 } 183 184 static void virtio_input_hid_realize(DeviceState *dev, Error **errp) 185 { 186 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev); 187 188 vhid->hs = qemu_input_handler_register(dev, vhid->handler); 189 if (vhid->display && vhid->hs) { 190 qemu_input_handler_bind(vhid->hs, vhid->display, vhid->head, NULL); 191 } 192 } 193 194 static void virtio_input_hid_unrealize(DeviceState *dev) 195 { 196 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev); 197 qemu_input_handler_unregister(vhid->hs); 198 } 199 200 static void virtio_input_hid_change_active(VirtIOInput *vinput) 201 { 202 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput); 203 204 if (vinput->active) { 205 qemu_input_handler_activate(vhid->hs); 206 } else { 207 qemu_input_handler_deactivate(vhid->hs); 208 } 209 } 210 211 static void virtio_input_hid_handle_status(VirtIOInput *vinput, 212 virtio_input_event *event) 213 { 214 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput); 215 int ledbit = 0; 216 217 switch (le16_to_cpu(event->type)) { 218 case EV_LED: 219 if (event->code == LED_NUML) { 220 ledbit = QEMU_NUM_LOCK_LED; 221 } else if (event->code == LED_CAPSL) { 222 ledbit = QEMU_CAPS_LOCK_LED; 223 } else if (event->code == LED_SCROLLL) { 224 ledbit = QEMU_SCROLL_LOCK_LED; 225 } 226 if (event->value) { 227 vhid->ledstate |= ledbit; 228 } else { 229 vhid->ledstate &= ~ledbit; 230 } 231 kbd_put_ledstate(vhid->ledstate); 232 break; 233 default: 234 fprintf(stderr, "%s: unknown type %d\n", __func__, 235 le16_to_cpu(event->type)); 236 break; 237 } 238 } 239 240 static Property virtio_input_hid_properties[] = { 241 DEFINE_PROP_STRING("display", VirtIOInputHID, display), 242 DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0), 243 DEFINE_PROP_END_OF_LIST(), 244 }; 245 246 static void virtio_input_hid_class_init(ObjectClass *klass, void *data) 247 { 248 DeviceClass *dc = DEVICE_CLASS(klass); 249 VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass); 250 251 device_class_set_props(dc, virtio_input_hid_properties); 252 vic->realize = virtio_input_hid_realize; 253 vic->unrealize = virtio_input_hid_unrealize; 254 vic->change_active = virtio_input_hid_change_active; 255 vic->handle_status = virtio_input_hid_handle_status; 256 } 257 258 static const TypeInfo virtio_input_hid_info = { 259 .name = TYPE_VIRTIO_INPUT_HID, 260 .parent = TYPE_VIRTIO_INPUT, 261 .instance_size = sizeof(VirtIOInputHID), 262 .class_init = virtio_input_hid_class_init, 263 .abstract = true, 264 }; 265 266 /* ----------------------------------------------------------------- */ 267 268 static const QemuInputHandler virtio_keyboard_handler = { 269 .name = VIRTIO_ID_NAME_KEYBOARD, 270 .mask = INPUT_EVENT_MASK_KEY, 271 .event = virtio_input_handle_event, 272 .sync = virtio_input_handle_sync, 273 }; 274 275 static struct virtio_input_config virtio_keyboard_config[] = { 276 { 277 .select = VIRTIO_INPUT_CFG_ID_NAME, 278 .size = sizeof(VIRTIO_ID_NAME_KEYBOARD), 279 .u.string = VIRTIO_ID_NAME_KEYBOARD, 280 },{ 281 .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 282 .size = sizeof(struct virtio_input_devids), 283 .u.ids = { 284 .bustype = const_le16(BUS_VIRTUAL), 285 .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 286 .product = const_le16(0x0001), 287 .version = const_le16(0x0001), 288 }, 289 },{ 290 .select = VIRTIO_INPUT_CFG_EV_BITS, 291 .subsel = EV_REP, 292 .size = 1, 293 },{ 294 .select = VIRTIO_INPUT_CFG_EV_BITS, 295 .subsel = EV_LED, 296 .size = 1, 297 .u.bitmap = { 298 (1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL), 299 }, 300 }, 301 { /* end of list */ }, 302 }; 303 304 static void virtio_keyboard_init(Object *obj) 305 { 306 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj); 307 VirtIOInput *vinput = VIRTIO_INPUT(obj); 308 309 vhid->handler = &virtio_keyboard_handler; 310 virtio_input_init_config(vinput, virtio_keyboard_config); 311 virtio_input_extend_config(vinput, qemu_input_map_qcode_to_linux, 312 qemu_input_map_qcode_to_linux_len, 313 VIRTIO_INPUT_CFG_EV_BITS, EV_KEY); 314 } 315 316 static const TypeInfo virtio_keyboard_info = { 317 .name = TYPE_VIRTIO_KEYBOARD, 318 .parent = TYPE_VIRTIO_INPUT_HID, 319 .instance_size = sizeof(VirtIOInputHID), 320 .instance_init = virtio_keyboard_init, 321 }; 322 323 /* ----------------------------------------------------------------- */ 324 325 static const QemuInputHandler virtio_mouse_handler = { 326 .name = VIRTIO_ID_NAME_MOUSE, 327 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, 328 .event = virtio_input_handle_event, 329 .sync = virtio_input_handle_sync, 330 }; 331 332 static struct virtio_input_config virtio_mouse_config_v1[] = { 333 { 334 .select = VIRTIO_INPUT_CFG_ID_NAME, 335 .size = sizeof(VIRTIO_ID_NAME_MOUSE), 336 .u.string = VIRTIO_ID_NAME_MOUSE, 337 },{ 338 .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 339 .size = sizeof(struct virtio_input_devids), 340 .u.ids = { 341 .bustype = const_le16(BUS_VIRTUAL), 342 .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 343 .product = const_le16(0x0002), 344 .version = const_le16(0x0001), 345 }, 346 },{ 347 .select = VIRTIO_INPUT_CFG_EV_BITS, 348 .subsel = EV_REL, 349 .size = 1, 350 .u.bitmap = { 351 (1 << REL_X) | (1 << REL_Y), 352 }, 353 }, 354 { /* end of list */ }, 355 }; 356 357 static struct virtio_input_config virtio_mouse_config_v2[] = { 358 { 359 .select = VIRTIO_INPUT_CFG_ID_NAME, 360 .size = sizeof(VIRTIO_ID_NAME_MOUSE), 361 .u.string = VIRTIO_ID_NAME_MOUSE, 362 },{ 363 .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 364 .size = sizeof(struct virtio_input_devids), 365 .u.ids = { 366 .bustype = const_le16(BUS_VIRTUAL), 367 .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 368 .product = const_le16(0x0002), 369 .version = const_le16(0x0002), 370 }, 371 },{ 372 .select = VIRTIO_INPUT_CFG_EV_BITS, 373 .subsel = EV_REL, 374 .size = 2, 375 .u.bitmap = { 376 (1 << REL_X) | (1 << REL_Y), 377 (1 << (REL_WHEEL - 8)) 378 }, 379 }, 380 { /* end of list */ }, 381 }; 382 383 static Property virtio_mouse_properties[] = { 384 DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true), 385 DEFINE_PROP_END_OF_LIST(), 386 }; 387 388 static void virtio_mouse_class_init(ObjectClass *klass, void *data) 389 { 390 DeviceClass *dc = DEVICE_CLASS(klass); 391 392 device_class_set_props(dc, virtio_mouse_properties); 393 } 394 395 static void virtio_mouse_init(Object *obj) 396 { 397 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj); 398 VirtIOInput *vinput = VIRTIO_INPUT(obj); 399 400 vhid->handler = &virtio_mouse_handler; 401 virtio_input_init_config(vinput, vhid->wheel_axis 402 ? virtio_mouse_config_v2 403 : virtio_mouse_config_v1); 404 virtio_input_extend_config(vinput, keymap_button, 405 ARRAY_SIZE(keymap_button), 406 VIRTIO_INPUT_CFG_EV_BITS, EV_KEY); 407 } 408 409 static const TypeInfo virtio_mouse_info = { 410 .name = TYPE_VIRTIO_MOUSE, 411 .parent = TYPE_VIRTIO_INPUT_HID, 412 .instance_size = sizeof(VirtIOInputHID), 413 .instance_init = virtio_mouse_init, 414 .class_init = virtio_mouse_class_init, 415 }; 416 417 /* ----------------------------------------------------------------- */ 418 419 static const QemuInputHandler virtio_tablet_handler = { 420 .name = VIRTIO_ID_NAME_TABLET, 421 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS, 422 .event = virtio_input_handle_event, 423 .sync = virtio_input_handle_sync, 424 }; 425 426 static struct virtio_input_config virtio_tablet_config_v1[] = { 427 { 428 .select = VIRTIO_INPUT_CFG_ID_NAME, 429 .size = sizeof(VIRTIO_ID_NAME_TABLET), 430 .u.string = VIRTIO_ID_NAME_TABLET, 431 },{ 432 .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 433 .size = sizeof(struct virtio_input_devids), 434 .u.ids = { 435 .bustype = const_le16(BUS_VIRTUAL), 436 .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 437 .product = const_le16(0x0003), 438 .version = const_le16(0x0001), 439 }, 440 },{ 441 .select = VIRTIO_INPUT_CFG_EV_BITS, 442 .subsel = EV_ABS, 443 .size = 1, 444 .u.bitmap = { 445 (1 << ABS_X) | (1 << ABS_Y), 446 }, 447 },{ 448 .select = VIRTIO_INPUT_CFG_ABS_INFO, 449 .subsel = ABS_X, 450 .size = sizeof(virtio_input_absinfo), 451 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 452 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 453 },{ 454 .select = VIRTIO_INPUT_CFG_ABS_INFO, 455 .subsel = ABS_Y, 456 .size = sizeof(virtio_input_absinfo), 457 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 458 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 459 }, 460 { /* end of list */ }, 461 }; 462 463 static struct virtio_input_config virtio_tablet_config_v2[] = { 464 { 465 .select = VIRTIO_INPUT_CFG_ID_NAME, 466 .size = sizeof(VIRTIO_ID_NAME_TABLET), 467 .u.string = VIRTIO_ID_NAME_TABLET, 468 },{ 469 .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 470 .size = sizeof(struct virtio_input_devids), 471 .u.ids = { 472 .bustype = const_le16(BUS_VIRTUAL), 473 .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 474 .product = const_le16(0x0003), 475 .version = const_le16(0x0002), 476 }, 477 },{ 478 .select = VIRTIO_INPUT_CFG_EV_BITS, 479 .subsel = EV_ABS, 480 .size = 1, 481 .u.bitmap = { 482 (1 << ABS_X) | (1 << ABS_Y), 483 }, 484 },{ 485 .select = VIRTIO_INPUT_CFG_EV_BITS, 486 .subsel = EV_REL, 487 .size = 2, 488 .u.bitmap = { 489 0, 490 (1 << (REL_WHEEL - 8)) 491 }, 492 },{ 493 .select = VIRTIO_INPUT_CFG_ABS_INFO, 494 .subsel = ABS_X, 495 .size = sizeof(virtio_input_absinfo), 496 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 497 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 498 },{ 499 .select = VIRTIO_INPUT_CFG_ABS_INFO, 500 .subsel = ABS_Y, 501 .size = sizeof(virtio_input_absinfo), 502 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 503 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 504 }, 505 { /* end of list */ }, 506 }; 507 508 static Property virtio_tablet_properties[] = { 509 DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true), 510 DEFINE_PROP_END_OF_LIST(), 511 }; 512 513 static void virtio_tablet_class_init(ObjectClass *klass, void *data) 514 { 515 DeviceClass *dc = DEVICE_CLASS(klass); 516 517 device_class_set_props(dc, virtio_tablet_properties); 518 } 519 520 static void virtio_tablet_init(Object *obj) 521 { 522 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj); 523 VirtIOInput *vinput = VIRTIO_INPUT(obj); 524 525 vhid->handler = &virtio_tablet_handler; 526 virtio_input_init_config(vinput, vhid->wheel_axis 527 ? virtio_tablet_config_v2 528 : virtio_tablet_config_v1); 529 virtio_input_extend_config(vinput, keymap_button, 530 ARRAY_SIZE(keymap_button), 531 VIRTIO_INPUT_CFG_EV_BITS, EV_KEY); 532 } 533 534 static const TypeInfo virtio_tablet_info = { 535 .name = TYPE_VIRTIO_TABLET, 536 .parent = TYPE_VIRTIO_INPUT_HID, 537 .instance_size = sizeof(VirtIOInputHID), 538 .instance_init = virtio_tablet_init, 539 .class_init = virtio_tablet_class_init, 540 }; 541 542 /* ----------------------------------------------------------------- */ 543 544 static const QemuInputHandler virtio_multitouch_handler = { 545 .name = VIRTIO_ID_NAME_MULTITOUCH, 546 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_MTT, 547 .event = virtio_input_handle_event, 548 .sync = virtio_input_handle_sync, 549 }; 550 551 static struct virtio_input_config virtio_multitouch_config[] = { 552 { 553 .select = VIRTIO_INPUT_CFG_ID_NAME, 554 .size = sizeof(VIRTIO_ID_NAME_MULTITOUCH), 555 .u.string = VIRTIO_ID_NAME_MULTITOUCH, 556 },{ 557 .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 558 .size = sizeof(struct virtio_input_devids), 559 .u.ids = { 560 .bustype = const_le16(BUS_VIRTUAL), 561 .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 562 .product = const_le16(0x0003), 563 .version = const_le16(0x0001), 564 }, 565 },{ 566 .select = VIRTIO_INPUT_CFG_ABS_INFO, 567 .subsel = ABS_MT_SLOT, 568 .size = sizeof(virtio_input_absinfo), 569 .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN), 570 .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX), 571 },{ 572 .select = VIRTIO_INPUT_CFG_ABS_INFO, 573 .subsel = ABS_MT_TRACKING_ID, 574 .size = sizeof(virtio_input_absinfo), 575 .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN), 576 .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX), 577 },{ 578 .select = VIRTIO_INPUT_CFG_ABS_INFO, 579 .subsel = ABS_MT_POSITION_X, 580 .size = sizeof(virtio_input_absinfo), 581 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 582 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 583 },{ 584 .select = VIRTIO_INPUT_CFG_ABS_INFO, 585 .subsel = ABS_MT_POSITION_Y, 586 .size = sizeof(virtio_input_absinfo), 587 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 588 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 589 }, 590 { /* end of list */ }, 591 }; 592 593 static void virtio_multitouch_init(Object *obj) 594 { 595 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj); 596 VirtIOInput *vinput = VIRTIO_INPUT(obj); 597 unsigned short abs_props[] = { 598 INPUT_PROP_DIRECT, 599 }; 600 unsigned short abs_bits[] = { 601 ABS_MT_SLOT, 602 ABS_MT_TRACKING_ID, 603 ABS_MT_POSITION_X, 604 ABS_MT_POSITION_Y, 605 }; 606 607 vhid->handler = &virtio_multitouch_handler; 608 virtio_input_init_config(vinput, virtio_multitouch_config); 609 virtio_input_extend_config(vinput, keymap_button, 610 ARRAY_SIZE(keymap_button), 611 VIRTIO_INPUT_CFG_EV_BITS, EV_KEY); 612 virtio_input_extend_config(vinput, abs_props, 613 ARRAY_SIZE(abs_props), 614 VIRTIO_INPUT_CFG_PROP_BITS, 0); 615 virtio_input_extend_config(vinput, abs_bits, 616 ARRAY_SIZE(abs_bits), 617 VIRTIO_INPUT_CFG_EV_BITS, EV_ABS); 618 } 619 620 static const TypeInfo virtio_multitouch_info = { 621 .name = TYPE_VIRTIO_MULTITOUCH, 622 .parent = TYPE_VIRTIO_INPUT_HID, 623 .instance_size = sizeof(VirtIOInputHID), 624 .instance_init = virtio_multitouch_init, 625 }; 626 627 /* ----------------------------------------------------------------- */ 628 629 static void virtio_register_types(void) 630 { 631 type_register_static(&virtio_input_hid_info); 632 type_register_static(&virtio_keyboard_info); 633 type_register_static(&virtio_mouse_info); 634 type_register_static(&virtio_tablet_info); 635 type_register_static(&virtio_multitouch_info); 636 } 637 638 type_init(virtio_register_types) 639