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