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 #undef CONFIG_CURSES 16 #include "ui/console.h" 17 18 #include "standard-headers/linux/input.h" 19 20 #define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard" 21 #define VIRTIO_ID_NAME_MOUSE "QEMU Virtio Mouse" 22 #define VIRTIO_ID_NAME_TABLET "QEMU Virtio Tablet" 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 }; 35 36 static const unsigned short axismap_rel[INPUT_AXIS__MAX] = { 37 [INPUT_AXIS_X] = REL_X, 38 [INPUT_AXIS_Y] = REL_Y, 39 }; 40 41 static const unsigned short axismap_abs[INPUT_AXIS__MAX] = { 42 [INPUT_AXIS_X] = ABS_X, 43 [INPUT_AXIS_Y] = ABS_Y, 44 }; 45 46 /* ----------------------------------------------------------------- */ 47 48 static void virtio_input_key_config(VirtIOInput *vinput, 49 const unsigned short *keymap, 50 size_t mapsize) 51 { 52 virtio_input_config keys; 53 int i, bit, byte, bmax = 0; 54 55 memset(&keys, 0, sizeof(keys)); 56 for (i = 0; i < mapsize; i++) { 57 bit = keymap[i]; 58 if (!bit) { 59 continue; 60 } 61 byte = bit / 8; 62 bit = bit % 8; 63 keys.u.bitmap[byte] |= (1 << bit); 64 if (bmax < byte+1) { 65 bmax = byte+1; 66 } 67 } 68 keys.select = VIRTIO_INPUT_CFG_EV_BITS; 69 keys.subsel = EV_KEY; 70 keys.size = bmax; 71 virtio_input_add_config(vinput, &keys); 72 } 73 74 static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src, 75 InputEvent *evt) 76 { 77 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev); 78 VirtIOInput *vinput = VIRTIO_INPUT(dev); 79 virtio_input_event event; 80 int qcode; 81 InputKeyEvent *key; 82 InputMoveEvent *move; 83 InputBtnEvent *btn; 84 85 switch (evt->type) { 86 case INPUT_EVENT_KIND_KEY: 87 key = evt->u.key.data; 88 qcode = qemu_input_key_value_to_qcode(key->key); 89 if (qcode < qemu_input_map_qcode_to_linux_len && 90 qemu_input_map_qcode_to_linux[qcode]) { 91 event.type = cpu_to_le16(EV_KEY); 92 event.code = cpu_to_le16(qemu_input_map_qcode_to_linux[qcode]); 93 event.value = cpu_to_le32(key->down ? 1 : 0); 94 virtio_input_send(vinput, &event); 95 } else { 96 if (key->down) { 97 fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__, 98 qcode, QKeyCode_str(qcode)); 99 } 100 } 101 break; 102 case INPUT_EVENT_KIND_BTN: 103 btn = evt->u.btn.data; 104 if (vhid->wheel_axis && 105 (btn->button == INPUT_BUTTON_WHEEL_UP || 106 btn->button == INPUT_BUTTON_WHEEL_DOWN) && 107 btn->down) { 108 event.type = cpu_to_le16(EV_REL); 109 event.code = cpu_to_le16(REL_WHEEL); 110 event.value = cpu_to_le32(btn->button == INPUT_BUTTON_WHEEL_UP 111 ? 1 : -1); 112 virtio_input_send(vinput, &event); 113 } else if (keymap_button[btn->button]) { 114 event.type = cpu_to_le16(EV_KEY); 115 event.code = cpu_to_le16(keymap_button[btn->button]); 116 event.value = cpu_to_le32(btn->down ? 1 : 0); 117 virtio_input_send(vinput, &event); 118 } else { 119 if (btn->down) { 120 fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__, 121 btn->button, 122 InputButton_str(btn->button)); 123 } 124 } 125 break; 126 case INPUT_EVENT_KIND_REL: 127 move = evt->u.rel.data; 128 event.type = cpu_to_le16(EV_REL); 129 event.code = cpu_to_le16(axismap_rel[move->axis]); 130 event.value = cpu_to_le32(move->value); 131 virtio_input_send(vinput, &event); 132 break; 133 case INPUT_EVENT_KIND_ABS: 134 move = evt->u.abs.data; 135 event.type = cpu_to_le16(EV_ABS); 136 event.code = cpu_to_le16(axismap_abs[move->axis]); 137 event.value = cpu_to_le32(move->value); 138 virtio_input_send(vinput, &event); 139 break; 140 default: 141 /* keep gcc happy */ 142 break; 143 } 144 } 145 146 static void virtio_input_handle_sync(DeviceState *dev) 147 { 148 VirtIOInput *vinput = VIRTIO_INPUT(dev); 149 virtio_input_event event = { 150 .type = cpu_to_le16(EV_SYN), 151 .code = cpu_to_le16(SYN_REPORT), 152 .value = 0, 153 }; 154 155 virtio_input_send(vinput, &event); 156 } 157 158 static void virtio_input_hid_realize(DeviceState *dev, Error **errp) 159 { 160 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev); 161 162 vhid->hs = qemu_input_handler_register(dev, vhid->handler); 163 if (vhid->display && vhid->hs) { 164 qemu_input_handler_bind(vhid->hs, vhid->display, vhid->head, NULL); 165 } 166 } 167 168 static void virtio_input_hid_unrealize(DeviceState *dev, Error **errp) 169 { 170 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev); 171 qemu_input_handler_unregister(vhid->hs); 172 } 173 174 static void virtio_input_hid_change_active(VirtIOInput *vinput) 175 { 176 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput); 177 178 if (vinput->active) { 179 qemu_input_handler_activate(vhid->hs); 180 } else { 181 qemu_input_handler_deactivate(vhid->hs); 182 } 183 } 184 185 static void virtio_input_hid_handle_status(VirtIOInput *vinput, 186 virtio_input_event *event) 187 { 188 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput); 189 int ledbit = 0; 190 191 switch (le16_to_cpu(event->type)) { 192 case EV_LED: 193 if (event->code == LED_NUML) { 194 ledbit = QEMU_NUM_LOCK_LED; 195 } else if (event->code == LED_CAPSL) { 196 ledbit = QEMU_CAPS_LOCK_LED; 197 } else if (event->code == LED_SCROLLL) { 198 ledbit = QEMU_SCROLL_LOCK_LED; 199 } 200 if (event->value) { 201 vhid->ledstate |= ledbit; 202 } else { 203 vhid->ledstate &= ~ledbit; 204 } 205 kbd_put_ledstate(vhid->ledstate); 206 break; 207 default: 208 fprintf(stderr, "%s: unknown type %d\n", __func__, 209 le16_to_cpu(event->type)); 210 break; 211 } 212 } 213 214 static Property virtio_input_hid_properties[] = { 215 DEFINE_PROP_STRING("display", VirtIOInputHID, display), 216 DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0), 217 DEFINE_PROP_END_OF_LIST(), 218 }; 219 220 static void virtio_input_hid_class_init(ObjectClass *klass, void *data) 221 { 222 DeviceClass *dc = DEVICE_CLASS(klass); 223 VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass); 224 225 device_class_set_props(dc, virtio_input_hid_properties); 226 vic->realize = virtio_input_hid_realize; 227 vic->unrealize = virtio_input_hid_unrealize; 228 vic->change_active = virtio_input_hid_change_active; 229 vic->handle_status = virtio_input_hid_handle_status; 230 } 231 232 static const TypeInfo virtio_input_hid_info = { 233 .name = TYPE_VIRTIO_INPUT_HID, 234 .parent = TYPE_VIRTIO_INPUT, 235 .instance_size = sizeof(VirtIOInputHID), 236 .class_init = virtio_input_hid_class_init, 237 .abstract = true, 238 }; 239 240 /* ----------------------------------------------------------------- */ 241 242 static QemuInputHandler virtio_keyboard_handler = { 243 .name = VIRTIO_ID_NAME_KEYBOARD, 244 .mask = INPUT_EVENT_MASK_KEY, 245 .event = virtio_input_handle_event, 246 .sync = virtio_input_handle_sync, 247 }; 248 249 static struct virtio_input_config virtio_keyboard_config[] = { 250 { 251 .select = VIRTIO_INPUT_CFG_ID_NAME, 252 .size = sizeof(VIRTIO_ID_NAME_KEYBOARD), 253 .u.string = VIRTIO_ID_NAME_KEYBOARD, 254 },{ 255 .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 256 .size = sizeof(struct virtio_input_devids), 257 .u.ids = { 258 .bustype = const_le16(BUS_VIRTUAL), 259 .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 260 .product = const_le16(0x0001), 261 .version = const_le16(0x0001), 262 }, 263 },{ 264 .select = VIRTIO_INPUT_CFG_EV_BITS, 265 .subsel = EV_REP, 266 .size = 1, 267 },{ 268 .select = VIRTIO_INPUT_CFG_EV_BITS, 269 .subsel = EV_LED, 270 .size = 1, 271 .u.bitmap = { 272 (1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL), 273 }, 274 }, 275 { /* end of list */ }, 276 }; 277 278 static void virtio_keyboard_init(Object *obj) 279 { 280 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj); 281 VirtIOInput *vinput = VIRTIO_INPUT(obj); 282 283 vhid->handler = &virtio_keyboard_handler; 284 virtio_input_init_config(vinput, virtio_keyboard_config); 285 virtio_input_key_config(vinput, qemu_input_map_qcode_to_linux, 286 qemu_input_map_qcode_to_linux_len); 287 } 288 289 static const TypeInfo virtio_keyboard_info = { 290 .name = TYPE_VIRTIO_KEYBOARD, 291 .parent = TYPE_VIRTIO_INPUT_HID, 292 .instance_size = sizeof(VirtIOInputHID), 293 .instance_init = virtio_keyboard_init, 294 }; 295 296 /* ----------------------------------------------------------------- */ 297 298 static QemuInputHandler virtio_mouse_handler = { 299 .name = VIRTIO_ID_NAME_MOUSE, 300 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, 301 .event = virtio_input_handle_event, 302 .sync = virtio_input_handle_sync, 303 }; 304 305 static struct virtio_input_config virtio_mouse_config_v1[] = { 306 { 307 .select = VIRTIO_INPUT_CFG_ID_NAME, 308 .size = sizeof(VIRTIO_ID_NAME_MOUSE), 309 .u.string = VIRTIO_ID_NAME_MOUSE, 310 },{ 311 .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 312 .size = sizeof(struct virtio_input_devids), 313 .u.ids = { 314 .bustype = const_le16(BUS_VIRTUAL), 315 .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 316 .product = const_le16(0x0002), 317 .version = const_le16(0x0001), 318 }, 319 },{ 320 .select = VIRTIO_INPUT_CFG_EV_BITS, 321 .subsel = EV_REL, 322 .size = 1, 323 .u.bitmap = { 324 (1 << REL_X) | (1 << REL_Y), 325 }, 326 }, 327 { /* end of list */ }, 328 }; 329 330 static struct virtio_input_config virtio_mouse_config_v2[] = { 331 { 332 .select = VIRTIO_INPUT_CFG_ID_NAME, 333 .size = sizeof(VIRTIO_ID_NAME_MOUSE), 334 .u.string = VIRTIO_ID_NAME_MOUSE, 335 },{ 336 .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 337 .size = sizeof(struct virtio_input_devids), 338 .u.ids = { 339 .bustype = const_le16(BUS_VIRTUAL), 340 .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 341 .product = const_le16(0x0002), 342 .version = const_le16(0x0002), 343 }, 344 },{ 345 .select = VIRTIO_INPUT_CFG_EV_BITS, 346 .subsel = EV_REL, 347 .size = 2, 348 .u.bitmap = { 349 (1 << REL_X) | (1 << REL_Y), 350 (1 << (REL_WHEEL - 8)) 351 }, 352 }, 353 { /* end of list */ }, 354 }; 355 356 static Property virtio_mouse_properties[] = { 357 DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true), 358 DEFINE_PROP_END_OF_LIST(), 359 }; 360 361 static void virtio_mouse_class_init(ObjectClass *klass, void *data) 362 { 363 DeviceClass *dc = DEVICE_CLASS(klass); 364 365 device_class_set_props(dc, virtio_mouse_properties); 366 } 367 368 static void virtio_mouse_init(Object *obj) 369 { 370 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj); 371 VirtIOInput *vinput = VIRTIO_INPUT(obj); 372 373 vhid->handler = &virtio_mouse_handler; 374 virtio_input_init_config(vinput, vhid->wheel_axis 375 ? virtio_mouse_config_v2 376 : virtio_mouse_config_v1); 377 virtio_input_key_config(vinput, keymap_button, 378 ARRAY_SIZE(keymap_button)); 379 } 380 381 static const TypeInfo virtio_mouse_info = { 382 .name = TYPE_VIRTIO_MOUSE, 383 .parent = TYPE_VIRTIO_INPUT_HID, 384 .instance_size = sizeof(VirtIOInputHID), 385 .instance_init = virtio_mouse_init, 386 .class_init = virtio_mouse_class_init, 387 }; 388 389 /* ----------------------------------------------------------------- */ 390 391 static QemuInputHandler virtio_tablet_handler = { 392 .name = VIRTIO_ID_NAME_TABLET, 393 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS, 394 .event = virtio_input_handle_event, 395 .sync = virtio_input_handle_sync, 396 }; 397 398 static struct virtio_input_config virtio_tablet_config_v1[] = { 399 { 400 .select = VIRTIO_INPUT_CFG_ID_NAME, 401 .size = sizeof(VIRTIO_ID_NAME_TABLET), 402 .u.string = VIRTIO_ID_NAME_TABLET, 403 },{ 404 .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 405 .size = sizeof(struct virtio_input_devids), 406 .u.ids = { 407 .bustype = const_le16(BUS_VIRTUAL), 408 .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 409 .product = const_le16(0x0003), 410 .version = const_le16(0x0001), 411 }, 412 },{ 413 .select = VIRTIO_INPUT_CFG_EV_BITS, 414 .subsel = EV_ABS, 415 .size = 1, 416 .u.bitmap = { 417 (1 << ABS_X) | (1 << ABS_Y), 418 }, 419 },{ 420 .select = VIRTIO_INPUT_CFG_ABS_INFO, 421 .subsel = ABS_X, 422 .size = sizeof(virtio_input_absinfo), 423 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 424 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 425 },{ 426 .select = VIRTIO_INPUT_CFG_ABS_INFO, 427 .subsel = ABS_Y, 428 .size = sizeof(virtio_input_absinfo), 429 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 430 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 431 }, 432 { /* end of list */ }, 433 }; 434 435 static struct virtio_input_config virtio_tablet_config_v2[] = { 436 { 437 .select = VIRTIO_INPUT_CFG_ID_NAME, 438 .size = sizeof(VIRTIO_ID_NAME_TABLET), 439 .u.string = VIRTIO_ID_NAME_TABLET, 440 },{ 441 .select = VIRTIO_INPUT_CFG_ID_DEVIDS, 442 .size = sizeof(struct virtio_input_devids), 443 .u.ids = { 444 .bustype = const_le16(BUS_VIRTUAL), 445 .vendor = const_le16(0x0627), /* same we use for usb hid devices */ 446 .product = const_le16(0x0003), 447 .version = const_le16(0x0002), 448 }, 449 },{ 450 .select = VIRTIO_INPUT_CFG_EV_BITS, 451 .subsel = EV_ABS, 452 .size = 1, 453 .u.bitmap = { 454 (1 << ABS_X) | (1 << ABS_Y), 455 }, 456 },{ 457 .select = VIRTIO_INPUT_CFG_EV_BITS, 458 .subsel = EV_REL, 459 .size = 2, 460 .u.bitmap = { 461 0, 462 (1 << (REL_WHEEL - 8)) 463 }, 464 },{ 465 .select = VIRTIO_INPUT_CFG_ABS_INFO, 466 .subsel = ABS_X, 467 .size = sizeof(virtio_input_absinfo), 468 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 469 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 470 },{ 471 .select = VIRTIO_INPUT_CFG_ABS_INFO, 472 .subsel = ABS_Y, 473 .size = sizeof(virtio_input_absinfo), 474 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), 475 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), 476 }, 477 { /* end of list */ }, 478 }; 479 480 static Property virtio_tablet_properties[] = { 481 DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true), 482 DEFINE_PROP_END_OF_LIST(), 483 }; 484 485 static void virtio_tablet_class_init(ObjectClass *klass, void *data) 486 { 487 DeviceClass *dc = DEVICE_CLASS(klass); 488 489 device_class_set_props(dc, virtio_tablet_properties); 490 } 491 492 static void virtio_tablet_init(Object *obj) 493 { 494 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj); 495 VirtIOInput *vinput = VIRTIO_INPUT(obj); 496 497 vhid->handler = &virtio_tablet_handler; 498 virtio_input_init_config(vinput, vhid->wheel_axis 499 ? virtio_tablet_config_v2 500 : virtio_tablet_config_v1); 501 virtio_input_key_config(vinput, keymap_button, 502 ARRAY_SIZE(keymap_button)); 503 } 504 505 static const TypeInfo virtio_tablet_info = { 506 .name = TYPE_VIRTIO_TABLET, 507 .parent = TYPE_VIRTIO_INPUT_HID, 508 .instance_size = sizeof(VirtIOInputHID), 509 .instance_init = virtio_tablet_init, 510 .class_init = virtio_tablet_class_init, 511 }; 512 513 /* ----------------------------------------------------------------- */ 514 515 static void virtio_register_types(void) 516 { 517 type_register_static(&virtio_input_hid_info); 518 type_register_static(&virtio_keyboard_info); 519 type_register_static(&virtio_mouse_info); 520 type_register_static(&virtio_tablet_info); 521 } 522 523 type_init(virtio_register_types) 524