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 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
virtio_input_hid_class_init(ObjectClass * klass,void * data)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
virtio_keyboard_init(Object * obj)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
virtio_mouse_class_init(ObjectClass * klass,void * data)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
virtio_mouse_init(Object * obj)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
virtio_tablet_class_init(ObjectClass * klass,void * data)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
virtio_tablet_init(Object * obj)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
virtio_multitouch_init(Object * obj)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
virtio_register_types(void)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