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
virtio_input_extend_config(VirtIOInput * vinput,const unsigned short * map,size_t mapsize,uint8_t select,uint8_t subsel)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
virtio_input_handle_event(DeviceState * dev,QemuConsole * src,InputEvent * evt)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
virtio_input_handle_sync(DeviceState * dev)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
virtio_input_hid_realize(DeviceState * dev,Error ** errp)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
virtio_input_hid_unrealize(DeviceState * dev)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
virtio_input_hid_change_active(VirtIOInput * vinput)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
virtio_input_hid_handle_status(VirtIOInput * vinput,virtio_input_event * event)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 const Property virtio_input_hid_properties[] = {
241 DEFINE_PROP_STRING("display", VirtIOInputHID, display),
242 DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0),
243 };
244
virtio_input_hid_class_init(ObjectClass * klass,const void * data)245 static void virtio_input_hid_class_init(ObjectClass *klass, const void *data)
246 {
247 DeviceClass *dc = DEVICE_CLASS(klass);
248 VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
249
250 device_class_set_props(dc, virtio_input_hid_properties);
251 vic->realize = virtio_input_hid_realize;
252 vic->unrealize = virtio_input_hid_unrealize;
253 vic->change_active = virtio_input_hid_change_active;
254 vic->handle_status = virtio_input_hid_handle_status;
255 }
256
257 static const TypeInfo virtio_input_hid_info = {
258 .name = TYPE_VIRTIO_INPUT_HID,
259 .parent = TYPE_VIRTIO_INPUT,
260 .instance_size = sizeof(VirtIOInputHID),
261 .class_init = virtio_input_hid_class_init,
262 .abstract = true,
263 };
264
265 /* ----------------------------------------------------------------- */
266
267 static const QemuInputHandler virtio_keyboard_handler = {
268 .name = VIRTIO_ID_NAME_KEYBOARD,
269 .mask = INPUT_EVENT_MASK_KEY,
270 .event = virtio_input_handle_event,
271 .sync = virtio_input_handle_sync,
272 };
273
274 static struct virtio_input_config virtio_keyboard_config[] = {
275 {
276 .select = VIRTIO_INPUT_CFG_ID_NAME,
277 .size = sizeof(VIRTIO_ID_NAME_KEYBOARD),
278 .u.string = VIRTIO_ID_NAME_KEYBOARD,
279 },{
280 .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
281 .size = sizeof(struct virtio_input_devids),
282 .u.ids = {
283 .bustype = const_le16(BUS_VIRTUAL),
284 .vendor = const_le16(0x0627), /* same we use for usb hid devices */
285 .product = const_le16(0x0001),
286 .version = const_le16(0x0001),
287 },
288 },{
289 .select = VIRTIO_INPUT_CFG_EV_BITS,
290 .subsel = EV_REP,
291 .size = 1,
292 },{
293 .select = VIRTIO_INPUT_CFG_EV_BITS,
294 .subsel = EV_LED,
295 .size = 1,
296 .u.bitmap = {
297 (1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL),
298 },
299 },
300 { /* end of list */ },
301 };
302
virtio_keyboard_init(Object * obj)303 static void virtio_keyboard_init(Object *obj)
304 {
305 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
306 VirtIOInput *vinput = VIRTIO_INPUT(obj);
307
308 vhid->handler = &virtio_keyboard_handler;
309 virtio_input_init_config(vinput, virtio_keyboard_config);
310 virtio_input_extend_config(vinput, qemu_input_map_qcode_to_linux,
311 qemu_input_map_qcode_to_linux_len,
312 VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
313 }
314
315 static const TypeInfo virtio_keyboard_info = {
316 .name = TYPE_VIRTIO_KEYBOARD,
317 .parent = TYPE_VIRTIO_INPUT_HID,
318 .instance_size = sizeof(VirtIOInputHID),
319 .instance_init = virtio_keyboard_init,
320 };
321
322 /* ----------------------------------------------------------------- */
323
324 static const QemuInputHandler virtio_mouse_handler = {
325 .name = VIRTIO_ID_NAME_MOUSE,
326 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
327 .event = virtio_input_handle_event,
328 .sync = virtio_input_handle_sync,
329 };
330
331 static struct virtio_input_config virtio_mouse_config_v1[] = {
332 {
333 .select = VIRTIO_INPUT_CFG_ID_NAME,
334 .size = sizeof(VIRTIO_ID_NAME_MOUSE),
335 .u.string = VIRTIO_ID_NAME_MOUSE,
336 },{
337 .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
338 .size = sizeof(struct virtio_input_devids),
339 .u.ids = {
340 .bustype = const_le16(BUS_VIRTUAL),
341 .vendor = const_le16(0x0627), /* same we use for usb hid devices */
342 .product = const_le16(0x0002),
343 .version = const_le16(0x0001),
344 },
345 },{
346 .select = VIRTIO_INPUT_CFG_EV_BITS,
347 .subsel = EV_REL,
348 .size = 1,
349 .u.bitmap = {
350 (1 << REL_X) | (1 << REL_Y),
351 },
352 },
353 { /* end of list */ },
354 };
355
356 static struct virtio_input_config virtio_mouse_config_v2[] = {
357 {
358 .select = VIRTIO_INPUT_CFG_ID_NAME,
359 .size = sizeof(VIRTIO_ID_NAME_MOUSE),
360 .u.string = VIRTIO_ID_NAME_MOUSE,
361 },{
362 .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
363 .size = sizeof(struct virtio_input_devids),
364 .u.ids = {
365 .bustype = const_le16(BUS_VIRTUAL),
366 .vendor = const_le16(0x0627), /* same we use for usb hid devices */
367 .product = const_le16(0x0002),
368 .version = const_le16(0x0002),
369 },
370 },{
371 .select = VIRTIO_INPUT_CFG_EV_BITS,
372 .subsel = EV_REL,
373 .size = 2,
374 .u.bitmap = {
375 (1 << REL_X) | (1 << REL_Y),
376 (1 << (REL_WHEEL - 8))
377 },
378 },
379 { /* end of list */ },
380 };
381
382 static const Property virtio_mouse_properties[] = {
383 DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
384 };
385
virtio_mouse_class_init(ObjectClass * klass,const void * data)386 static void virtio_mouse_class_init(ObjectClass *klass, const void *data)
387 {
388 DeviceClass *dc = DEVICE_CLASS(klass);
389
390 device_class_set_props(dc, virtio_mouse_properties);
391 }
392
virtio_mouse_init(Object * obj)393 static void virtio_mouse_init(Object *obj)
394 {
395 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
396 VirtIOInput *vinput = VIRTIO_INPUT(obj);
397
398 vhid->handler = &virtio_mouse_handler;
399 virtio_input_init_config(vinput, vhid->wheel_axis
400 ? virtio_mouse_config_v2
401 : virtio_mouse_config_v1);
402 virtio_input_extend_config(vinput, keymap_button,
403 ARRAY_SIZE(keymap_button),
404 VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
405 }
406
407 static const TypeInfo virtio_mouse_info = {
408 .name = TYPE_VIRTIO_MOUSE,
409 .parent = TYPE_VIRTIO_INPUT_HID,
410 .instance_size = sizeof(VirtIOInputHID),
411 .instance_init = virtio_mouse_init,
412 .class_init = virtio_mouse_class_init,
413 };
414
415 /* ----------------------------------------------------------------- */
416
417 static const QemuInputHandler virtio_tablet_handler = {
418 .name = VIRTIO_ID_NAME_TABLET,
419 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
420 .event = virtio_input_handle_event,
421 .sync = virtio_input_handle_sync,
422 };
423
424 static struct virtio_input_config virtio_tablet_config_v1[] = {
425 {
426 .select = VIRTIO_INPUT_CFG_ID_NAME,
427 .size = sizeof(VIRTIO_ID_NAME_TABLET),
428 .u.string = VIRTIO_ID_NAME_TABLET,
429 },{
430 .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
431 .size = sizeof(struct virtio_input_devids),
432 .u.ids = {
433 .bustype = const_le16(BUS_VIRTUAL),
434 .vendor = const_le16(0x0627), /* same we use for usb hid devices */
435 .product = const_le16(0x0003),
436 .version = const_le16(0x0001),
437 },
438 },{
439 .select = VIRTIO_INPUT_CFG_EV_BITS,
440 .subsel = EV_ABS,
441 .size = 1,
442 .u.bitmap = {
443 (1 << ABS_X) | (1 << ABS_Y),
444 },
445 },{
446 .select = VIRTIO_INPUT_CFG_ABS_INFO,
447 .subsel = ABS_X,
448 .size = sizeof(virtio_input_absinfo),
449 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
450 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
451 },{
452 .select = VIRTIO_INPUT_CFG_ABS_INFO,
453 .subsel = ABS_Y,
454 .size = sizeof(virtio_input_absinfo),
455 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
456 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
457 },
458 { /* end of list */ },
459 };
460
461 static struct virtio_input_config virtio_tablet_config_v2[] = {
462 {
463 .select = VIRTIO_INPUT_CFG_ID_NAME,
464 .size = sizeof(VIRTIO_ID_NAME_TABLET),
465 .u.string = VIRTIO_ID_NAME_TABLET,
466 },{
467 .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
468 .size = sizeof(struct virtio_input_devids),
469 .u.ids = {
470 .bustype = const_le16(BUS_VIRTUAL),
471 .vendor = const_le16(0x0627), /* same we use for usb hid devices */
472 .product = const_le16(0x0003),
473 .version = const_le16(0x0002),
474 },
475 },{
476 .select = VIRTIO_INPUT_CFG_EV_BITS,
477 .subsel = EV_ABS,
478 .size = 1,
479 .u.bitmap = {
480 (1 << ABS_X) | (1 << ABS_Y),
481 },
482 },{
483 .select = VIRTIO_INPUT_CFG_EV_BITS,
484 .subsel = EV_REL,
485 .size = 2,
486 .u.bitmap = {
487 0,
488 (1 << (REL_WHEEL - 8))
489 },
490 },{
491 .select = VIRTIO_INPUT_CFG_ABS_INFO,
492 .subsel = ABS_X,
493 .size = sizeof(virtio_input_absinfo),
494 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
495 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
496 },{
497 .select = VIRTIO_INPUT_CFG_ABS_INFO,
498 .subsel = ABS_Y,
499 .size = sizeof(virtio_input_absinfo),
500 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
501 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
502 },
503 { /* end of list */ },
504 };
505
506 static const Property virtio_tablet_properties[] = {
507 DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
508 };
509
virtio_tablet_class_init(ObjectClass * klass,const void * data)510 static void virtio_tablet_class_init(ObjectClass *klass, const void *data)
511 {
512 DeviceClass *dc = DEVICE_CLASS(klass);
513
514 device_class_set_props(dc, virtio_tablet_properties);
515 }
516
virtio_tablet_init(Object * obj)517 static void virtio_tablet_init(Object *obj)
518 {
519 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
520 VirtIOInput *vinput = VIRTIO_INPUT(obj);
521
522 vhid->handler = &virtio_tablet_handler;
523 virtio_input_init_config(vinput, vhid->wheel_axis
524 ? virtio_tablet_config_v2
525 : virtio_tablet_config_v1);
526 virtio_input_extend_config(vinput, keymap_button,
527 ARRAY_SIZE(keymap_button),
528 VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
529 }
530
531 static const TypeInfo virtio_tablet_info = {
532 .name = TYPE_VIRTIO_TABLET,
533 .parent = TYPE_VIRTIO_INPUT_HID,
534 .instance_size = sizeof(VirtIOInputHID),
535 .instance_init = virtio_tablet_init,
536 .class_init = virtio_tablet_class_init,
537 };
538
539 /* ----------------------------------------------------------------- */
540
541 static const QemuInputHandler virtio_multitouch_handler = {
542 .name = VIRTIO_ID_NAME_MULTITOUCH,
543 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_MTT,
544 .event = virtio_input_handle_event,
545 .sync = virtio_input_handle_sync,
546 };
547
548 static struct virtio_input_config virtio_multitouch_config[] = {
549 {
550 .select = VIRTIO_INPUT_CFG_ID_NAME,
551 .size = sizeof(VIRTIO_ID_NAME_MULTITOUCH),
552 .u.string = VIRTIO_ID_NAME_MULTITOUCH,
553 },{
554 .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
555 .size = sizeof(struct virtio_input_devids),
556 .u.ids = {
557 .bustype = const_le16(BUS_VIRTUAL),
558 .vendor = const_le16(0x0627), /* same we use for usb hid devices */
559 .product = const_le16(0x0003),
560 .version = const_le16(0x0001),
561 },
562 },{
563 .select = VIRTIO_INPUT_CFG_ABS_INFO,
564 .subsel = ABS_MT_SLOT,
565 .size = sizeof(virtio_input_absinfo),
566 .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
567 .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
568 },{
569 .select = VIRTIO_INPUT_CFG_ABS_INFO,
570 .subsel = ABS_MT_TRACKING_ID,
571 .size = sizeof(virtio_input_absinfo),
572 .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
573 .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
574 },{
575 .select = VIRTIO_INPUT_CFG_ABS_INFO,
576 .subsel = ABS_MT_POSITION_X,
577 .size = sizeof(virtio_input_absinfo),
578 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
579 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
580 },{
581 .select = VIRTIO_INPUT_CFG_ABS_INFO,
582 .subsel = ABS_MT_POSITION_Y,
583 .size = sizeof(virtio_input_absinfo),
584 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
585 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
586 },
587 { /* end of list */ },
588 };
589
virtio_multitouch_init(Object * obj)590 static void virtio_multitouch_init(Object *obj)
591 {
592 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
593 VirtIOInput *vinput = VIRTIO_INPUT(obj);
594 unsigned short abs_props[] = {
595 INPUT_PROP_DIRECT,
596 };
597 unsigned short abs_bits[] = {
598 ABS_MT_SLOT,
599 ABS_MT_TRACKING_ID,
600 ABS_MT_POSITION_X,
601 ABS_MT_POSITION_Y,
602 };
603
604 vhid->handler = &virtio_multitouch_handler;
605 virtio_input_init_config(vinput, virtio_multitouch_config);
606 virtio_input_extend_config(vinput, keymap_button,
607 ARRAY_SIZE(keymap_button),
608 VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
609 virtio_input_extend_config(vinput, abs_props,
610 ARRAY_SIZE(abs_props),
611 VIRTIO_INPUT_CFG_PROP_BITS, 0);
612 virtio_input_extend_config(vinput, abs_bits,
613 ARRAY_SIZE(abs_bits),
614 VIRTIO_INPUT_CFG_EV_BITS, EV_ABS);
615 }
616
617 static const TypeInfo virtio_multitouch_info = {
618 .name = TYPE_VIRTIO_MULTITOUCH,
619 .parent = TYPE_VIRTIO_INPUT_HID,
620 .instance_size = sizeof(VirtIOInputHID),
621 .instance_init = virtio_multitouch_init,
622 };
623
624 /* ----------------------------------------------------------------- */
625
virtio_register_types(void)626 static void virtio_register_types(void)
627 {
628 type_register_static(&virtio_input_hid_info);
629 type_register_static(&virtio_keyboard_info);
630 type_register_static(&virtio_mouse_info);
631 type_register_static(&virtio_tablet_info);
632 type_register_static(&virtio_multitouch_info);
633 }
634
635 type_init(virtio_register_types)
636