blob: 45e4d4c75d90283bf8a877d41671750a6b37e531 [file] [log] [blame]
Gerd Hoffmann55a1d802014-04-01 10:06:29 +02001/*
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
Peter Maydell9b8bfe22016-01-26 18:17:07 +00007#include "qemu/osdep.h"
Gerd Hoffmann55a1d802014-04-01 10:06:29 +02008#include "qemu/iov.h"
Markus Armbruster0b8fa322019-05-23 16:35:07 +02009#include "qemu/module.h"
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020010
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020011#include "hw/virtio/virtio.h"
Markus Armbrustera27bd6c2019-08-12 07:23:51 +020012#include "hw/qdev-properties.h"
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020013#include "hw/virtio/virtio-input.h"
14
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020015#include "ui/console.h"
16
17#include "standard-headers/linux/input.h"
18
Sergio Lopez8e9ebd72023-05-26 13:29:22 +020019#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"
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020023
24/* ----------------------------------------------------------------- */
25
Daniel P. Berrangeae6b06a2018-01-17 16:41:18 +000026static const unsigned short keymap_button[INPUT_BUTTON__MAX] = {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020027 [INPUT_BUTTON_LEFT] = BTN_LEFT,
28 [INPUT_BUTTON_RIGHT] = BTN_RIGHT,
29 [INPUT_BUTTON_MIDDLE] = BTN_MIDDLE,
Gerd Hoffmannf22d0af2016-01-12 12:14:12 +010030 [INPUT_BUTTON_WHEEL_UP] = BTN_GEAR_UP,
31 [INPUT_BUTTON_WHEEL_DOWN] = BTN_GEAR_DOWN,
Miika S24167602017-12-22 17:25:30 +020032 [INPUT_BUTTON_SIDE] = BTN_SIDE,
33 [INPUT_BUTTON_EXTRA] = BTN_EXTRA,
Sergio Lopez8e9ebd72023-05-26 13:29:22 +020034 [INPUT_BUTTON_TOUCH] = BTN_TOUCH,
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020035};
36
Daniel P. Berrangeae6b06a2018-01-17 16:41:18 +000037static const unsigned short axismap_rel[INPUT_AXIS__MAX] = {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020038 [INPUT_AXIS_X] = REL_X,
39 [INPUT_AXIS_Y] = REL_Y,
40};
41
Daniel P. Berrangeae6b06a2018-01-17 16:41:18 +000042static const unsigned short axismap_abs[INPUT_AXIS__MAX] = {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020043 [INPUT_AXIS_X] = ABS_X,
44 [INPUT_AXIS_Y] = ABS_Y,
45};
46
Sergio Lopez8e9ebd72023-05-26 13:29:22 +020047static 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
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020052/* ----------------------------------------------------------------- */
53
Sergio Lopez944ae6d2023-05-26 13:29:20 +020054static void virtio_input_extend_config(VirtIOInput *vinput,
55 const unsigned short *map,
56 size_t mapsize,
57 uint8_t select, uint8_t subsel)
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020058{
Sergio Lopez944ae6d2023-05-26 13:29:20 +020059 virtio_input_config ext;
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020060 int i, bit, byte, bmax = 0;
61
Sergio Lopez944ae6d2023-05-26 13:29:20 +020062 memset(&ext, 0, sizeof(ext));
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020063 for (i = 0; i < mapsize; i++) {
Sergio Lopez944ae6d2023-05-26 13:29:20 +020064 bit = map[i];
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020065 if (!bit) {
66 continue;
67 }
68 byte = bit / 8;
69 bit = bit % 8;
Sergio Lopez944ae6d2023-05-26 13:29:20 +020070 ext.u.bitmap[byte] |= (1 << bit);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020071 if (bmax < byte+1) {
72 bmax = byte+1;
73 }
74 }
Sergio Lopez944ae6d2023-05-26 13:29:20 +020075 ext.select = select;
76 ext.subsel = subsel;
77 ext.size = bmax;
78 virtio_input_add_config(vinput, &ext);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020079}
80
81static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
82 InputEvent *evt)
83{
Gerd Hoffmannf4924972017-09-26 13:32:43 +020084 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020085 VirtIOInput *vinput = VIRTIO_INPUT(dev);
86 virtio_input_event event;
87 int qcode;
Eric Blakeb5a1b442016-03-03 09:16:49 -070088 InputKeyEvent *key;
89 InputMoveEvent *move;
90 InputBtnEvent *btn;
Sergio Lopez8e9ebd72023-05-26 13:29:22 +020091 InputMultiTouchEvent *mtt;
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020092
Eric Blake568c73a2015-10-26 16:34:58 -060093 switch (evt->type) {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020094 case INPUT_EVENT_KIND_KEY:
Eric Blake32bafa82016-03-17 16:48:37 -060095 key = evt->u.key.data;
Eric Blakeb5a1b442016-03-03 09:16:49 -070096 qcode = qemu_input_key_value_to_qcode(key->key);
Daniel P. Berrangeae6b06a2018-01-17 16:41:18 +000097 if (qcode < qemu_input_map_qcode_to_linux_len &&
98 qemu_input_map_qcode_to_linux[qcode]) {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +020099 event.type = cpu_to_le16(EV_KEY);
Daniel P. Berrangeae6b06a2018-01-17 16:41:18 +0000100 event.code = cpu_to_le16(qemu_input_map_qcode_to_linux[qcode]);
Eric Blakeb5a1b442016-03-03 09:16:49 -0700101 event.value = cpu_to_le32(key->down ? 1 : 0);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200102 virtio_input_send(vinput, &event);
103 } else {
Eric Blakeb5a1b442016-03-03 09:16:49 -0700104 if (key->down) {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200105 fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
Markus Armbruster977c7362017-08-24 10:46:08 +0200106 qcode, QKeyCode_str(qcode));
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200107 }
108 }
109 break;
110 case INPUT_EVENT_KIND_BTN:
Eric Blake32bafa82016-03-17 16:48:37 -0600111 btn = evt->u.btn.data;
Miika Sa5f99be2017-12-22 17:25:31 +0200112 if (vhid->wheel_axis &&
113 (btn->button == INPUT_BUTTON_WHEEL_UP ||
114 btn->button == INPUT_BUTTON_WHEEL_DOWN) &&
115 btn->down) {
Gerd Hoffmannf4924972017-09-26 13:32:43 +0200116 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]) {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200122 event.type = cpu_to_le16(EV_KEY);
Eric Blakeb5a1b442016-03-03 09:16:49 -0700123 event.code = cpu_to_le16(keymap_button[btn->button]);
124 event.value = cpu_to_le32(btn->down ? 1 : 0);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200125 virtio_input_send(vinput, &event);
126 } else {
Eric Blakeb5a1b442016-03-03 09:16:49 -0700127 if (btn->down) {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200128 fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
Eric Blakeb5a1b442016-03-03 09:16:49 -0700129 btn->button,
Markus Armbruster977c7362017-08-24 10:46:08 +0200130 InputButton_str(btn->button));
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200131 }
132 }
133 break;
134 case INPUT_EVENT_KIND_REL:
Eric Blake32bafa82016-03-17 16:48:37 -0600135 move = evt->u.rel.data;
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200136 event.type = cpu_to_le16(EV_REL);
Eric Blakeb5a1b442016-03-03 09:16:49 -0700137 event.code = cpu_to_le16(axismap_rel[move->axis]);
138 event.value = cpu_to_le32(move->value);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200139 virtio_input_send(vinput, &event);
140 break;
141 case INPUT_EVENT_KIND_ABS:
Eric Blake32bafa82016-03-17 16:48:37 -0600142 move = evt->u.abs.data;
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200143 event.type = cpu_to_le16(EV_ABS);
Eric Blakeb5a1b442016-03-03 09:16:49 -0700144 event.code = cpu_to_le16(axismap_abs[move->axis]);
145 event.value = cpu_to_le32(move->value);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200146 virtio_input_send(vinput, &event);
147 break;
Sergio Lopez8e9ebd72023-05-26 13:29:22 +0200148 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;
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200166 default:
167 /* keep gcc happy */
168 break;
169 }
170}
171
172static 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
184static void virtio_input_hid_realize(DeviceState *dev, Error **errp)
185{
186 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
Gerd Hoffmann5cce1732015-06-24 11:59:16 +0200187
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200188 vhid->hs = qemu_input_handler_register(dev, vhid->handler);
Gerd Hoffmann5cce1732015-06-24 11:59:16 +0200189 if (vhid->display && vhid->hs) {
190 qemu_input_handler_bind(vhid->hs, vhid->display, vhid->head, NULL);
191 }
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200192}
193
Markus Armbrusterb69c3c22020-05-05 17:29:24 +0200194static void virtio_input_hid_unrealize(DeviceState *dev)
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200195{
196 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
197 qemu_input_handler_unregister(vhid->hs);
198}
199
200static 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
211static 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
Gerd Hoffmann5cce1732015-06-24 11:59:16 +0200240static Property virtio_input_hid_properties[] = {
241 DEFINE_PROP_STRING("display", VirtIOInputHID, display),
242 DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0),
Lin Ma2a19b222015-07-14 19:27:30 +0800243 DEFINE_PROP_END_OF_LIST(),
Gerd Hoffmann5cce1732015-06-24 11:59:16 +0200244};
245
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200246static void virtio_input_hid_class_init(ObjectClass *klass, void *data)
247{
Gerd Hoffmann5cce1732015-06-24 11:59:16 +0200248 DeviceClass *dc = DEVICE_CLASS(klass);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200249 VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
250
Marc-André Lureau4f67d302020-01-10 19:30:32 +0400251 device_class_set_props(dc, virtio_input_hid_properties);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200252 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
258static 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
Philippe Mathieu-Daudéb1be65f2023-10-17 15:05:00 +0200268static const QemuInputHandler virtio_keyboard_handler = {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200269 .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
275static 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
304static 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);
Sergio Lopez944ae6d2023-05-26 13:29:20 +0200311 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);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200314}
315
316static 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
Philippe Mathieu-Daudéb1be65f2023-10-17 15:05:00 +0200325static const QemuInputHandler virtio_mouse_handler = {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200326 .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
Gerd Hoffmannf4924972017-09-26 13:32:43 +0200332static struct virtio_input_config virtio_mouse_config_v1[] = {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200333 {
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
Gerd Hoffmannf4924972017-09-26 13:32:43 +0200357static 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
383static Property virtio_mouse_properties[] = {
384 DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
385 DEFINE_PROP_END_OF_LIST(),
386};
387
388static void virtio_mouse_class_init(ObjectClass *klass, void *data)
389{
390 DeviceClass *dc = DEVICE_CLASS(klass);
391
Marc-André Lureau4f67d302020-01-10 19:30:32 +0400392 device_class_set_props(dc, virtio_mouse_properties);
Gerd Hoffmannf4924972017-09-26 13:32:43 +0200393}
394
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200395static 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;
Gerd Hoffmannf4924972017-09-26 13:32:43 +0200401 virtio_input_init_config(vinput, vhid->wheel_axis
402 ? virtio_mouse_config_v2
403 : virtio_mouse_config_v1);
Sergio Lopez944ae6d2023-05-26 13:29:20 +0200404 virtio_input_extend_config(vinput, keymap_button,
405 ARRAY_SIZE(keymap_button),
406 VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200407}
408
409static 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,
Gerd Hoffmannf4924972017-09-26 13:32:43 +0200414 .class_init = virtio_mouse_class_init,
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200415};
416
417/* ----------------------------------------------------------------- */
418
Philippe Mathieu-Daudéb1be65f2023-10-17 15:05:00 +0200419static const QemuInputHandler virtio_tablet_handler = {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200420 .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
Gerd Hoffmannf4924972017-09-26 13:32:43 +0200426static struct virtio_input_config virtio_tablet_config_v1[] = {
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200427 {
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),
Philippe Voinov9cfa7ab2017-05-05 15:39:52 +0200451 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
452 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200453 },{
454 .select = VIRTIO_INPUT_CFG_ABS_INFO,
455 .subsel = ABS_Y,
456 .size = sizeof(virtio_input_absinfo),
Philippe Voinov9cfa7ab2017-05-05 15:39:52 +0200457 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
458 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200459 },
460 { /* end of list */ },
461};
462
Gerd Hoffmannf4924972017-09-26 13:32:43 +0200463static 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
508static Property virtio_tablet_properties[] = {
509 DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
510 DEFINE_PROP_END_OF_LIST(),
511};
512
513static void virtio_tablet_class_init(ObjectClass *klass, void *data)
514{
515 DeviceClass *dc = DEVICE_CLASS(klass);
516
Marc-André Lureau4f67d302020-01-10 19:30:32 +0400517 device_class_set_props(dc, virtio_tablet_properties);
Gerd Hoffmannf4924972017-09-26 13:32:43 +0200518}
519
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200520static 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;
Gerd Hoffmannf4924972017-09-26 13:32:43 +0200526 virtio_input_init_config(vinput, vhid->wheel_axis
527 ? virtio_tablet_config_v2
528 : virtio_tablet_config_v1);
Sergio Lopez944ae6d2023-05-26 13:29:20 +0200529 virtio_input_extend_config(vinput, keymap_button,
530 ARRAY_SIZE(keymap_button),
531 VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200532}
533
534static 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,
Gerd Hoffmannf4924972017-09-26 13:32:43 +0200539 .class_init = virtio_tablet_class_init,
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200540};
541
542/* ----------------------------------------------------------------- */
543
Philippe Mathieu-Daudéb1be65f2023-10-17 15:05:00 +0200544static const QemuInputHandler virtio_multitouch_handler = {
Sergio Lopez8e9ebd72023-05-26 13:29:22 +0200545 .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
551static 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
593static 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
620static 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
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200629static 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);
Sergio Lopez8e9ebd72023-05-26 13:29:22 +0200635 type_register_static(&virtio_multitouch_info);
Gerd Hoffmann55a1d802014-04-01 10:06:29 +0200636}
637
638type_init(virtio_register_types)