Merge tag 'qemu-macppc-20230206' of https://github.com/mcayland/qemu into staging
[qemu.git] / hw / input / virtio-input-hid.c
bloba7a244a95dbb50dc0cc182a9a6b4af2e55a38723
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 */
7 #include "qemu/osdep.h"
8 #include "qemu/iov.h"
9 #include "qemu/module.h"
11 #include "hw/virtio/virtio.h"
12 #include "hw/qdev-properties.h"
13 #include "hw/virtio/virtio-input.h"
15 #include "ui/console.h"
17 #include "standard-headers/linux/input.h"
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"
23 /* ----------------------------------------------------------------- */
25 static const unsigned short keymap_button[INPUT_BUTTON__MAX] = {
26 [INPUT_BUTTON_LEFT] = BTN_LEFT,
27 [INPUT_BUTTON_RIGHT] = BTN_RIGHT,
28 [INPUT_BUTTON_MIDDLE] = BTN_MIDDLE,
29 [INPUT_BUTTON_WHEEL_UP] = BTN_GEAR_UP,
30 [INPUT_BUTTON_WHEEL_DOWN] = BTN_GEAR_DOWN,
31 [INPUT_BUTTON_SIDE] = BTN_SIDE,
32 [INPUT_BUTTON_EXTRA] = BTN_EXTRA,
35 static const unsigned short axismap_rel[INPUT_AXIS__MAX] = {
36 [INPUT_AXIS_X] = REL_X,
37 [INPUT_AXIS_Y] = REL_Y,
40 static const unsigned short axismap_abs[INPUT_AXIS__MAX] = {
41 [INPUT_AXIS_X] = ABS_X,
42 [INPUT_AXIS_Y] = ABS_Y,
45 /* ----------------------------------------------------------------- */
47 static void virtio_input_key_config(VirtIOInput *vinput,
48 const unsigned short *keymap,
49 size_t mapsize)
51 virtio_input_config keys;
52 int i, bit, byte, bmax = 0;
54 memset(&keys, 0, sizeof(keys));
55 for (i = 0; i < mapsize; i++) {
56 bit = keymap[i];
57 if (!bit) {
58 continue;
60 byte = bit / 8;
61 bit = bit % 8;
62 keys.u.bitmap[byte] |= (1 << bit);
63 if (bmax < byte+1) {
64 bmax = byte+1;
67 keys.select = VIRTIO_INPUT_CFG_EV_BITS;
68 keys.subsel = EV_KEY;
69 keys.size = bmax;
70 virtio_input_add_config(vinput, &keys);
73 static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
74 InputEvent *evt)
76 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
77 VirtIOInput *vinput = VIRTIO_INPUT(dev);
78 virtio_input_event event;
79 int qcode;
80 InputKeyEvent *key;
81 InputMoveEvent *move;
82 InputBtnEvent *btn;
84 switch (evt->type) {
85 case INPUT_EVENT_KIND_KEY:
86 key = evt->u.key.data;
87 qcode = qemu_input_key_value_to_qcode(key->key);
88 if (qcode < qemu_input_map_qcode_to_linux_len &&
89 qemu_input_map_qcode_to_linux[qcode]) {
90 event.type = cpu_to_le16(EV_KEY);
91 event.code = cpu_to_le16(qemu_input_map_qcode_to_linux[qcode]);
92 event.value = cpu_to_le32(key->down ? 1 : 0);
93 virtio_input_send(vinput, &event);
94 } else {
95 if (key->down) {
96 fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
97 qcode, QKeyCode_str(qcode));
100 break;
101 case INPUT_EVENT_KIND_BTN:
102 btn = evt->u.btn.data;
103 if (vhid->wheel_axis &&
104 (btn->button == INPUT_BUTTON_WHEEL_UP ||
105 btn->button == INPUT_BUTTON_WHEEL_DOWN) &&
106 btn->down) {
107 event.type = cpu_to_le16(EV_REL);
108 event.code = cpu_to_le16(REL_WHEEL);
109 event.value = cpu_to_le32(btn->button == INPUT_BUTTON_WHEEL_UP
110 ? 1 : -1);
111 virtio_input_send(vinput, &event);
112 } else if (keymap_button[btn->button]) {
113 event.type = cpu_to_le16(EV_KEY);
114 event.code = cpu_to_le16(keymap_button[btn->button]);
115 event.value = cpu_to_le32(btn->down ? 1 : 0);
116 virtio_input_send(vinput, &event);
117 } else {
118 if (btn->down) {
119 fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
120 btn->button,
121 InputButton_str(btn->button));
124 break;
125 case INPUT_EVENT_KIND_REL:
126 move = evt->u.rel.data;
127 event.type = cpu_to_le16(EV_REL);
128 event.code = cpu_to_le16(axismap_rel[move->axis]);
129 event.value = cpu_to_le32(move->value);
130 virtio_input_send(vinput, &event);
131 break;
132 case INPUT_EVENT_KIND_ABS:
133 move = evt->u.abs.data;
134 event.type = cpu_to_le16(EV_ABS);
135 event.code = cpu_to_le16(axismap_abs[move->axis]);
136 event.value = cpu_to_le32(move->value);
137 virtio_input_send(vinput, &event);
138 break;
139 default:
140 /* keep gcc happy */
141 break;
145 static void virtio_input_handle_sync(DeviceState *dev)
147 VirtIOInput *vinput = VIRTIO_INPUT(dev);
148 virtio_input_event event = {
149 .type = cpu_to_le16(EV_SYN),
150 .code = cpu_to_le16(SYN_REPORT),
151 .value = 0,
154 virtio_input_send(vinput, &event);
157 static void virtio_input_hid_realize(DeviceState *dev, Error **errp)
159 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
161 vhid->hs = qemu_input_handler_register(dev, vhid->handler);
162 if (vhid->display && vhid->hs) {
163 qemu_input_handler_bind(vhid->hs, vhid->display, vhid->head, NULL);
167 static void virtio_input_hid_unrealize(DeviceState *dev)
169 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
170 qemu_input_handler_unregister(vhid->hs);
173 static void virtio_input_hid_change_active(VirtIOInput *vinput)
175 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
177 if (vinput->active) {
178 qemu_input_handler_activate(vhid->hs);
179 } else {
180 qemu_input_handler_deactivate(vhid->hs);
184 static void virtio_input_hid_handle_status(VirtIOInput *vinput,
185 virtio_input_event *event)
187 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
188 int ledbit = 0;
190 switch (le16_to_cpu(event->type)) {
191 case EV_LED:
192 if (event->code == LED_NUML) {
193 ledbit = QEMU_NUM_LOCK_LED;
194 } else if (event->code == LED_CAPSL) {
195 ledbit = QEMU_CAPS_LOCK_LED;
196 } else if (event->code == LED_SCROLLL) {
197 ledbit = QEMU_SCROLL_LOCK_LED;
199 if (event->value) {
200 vhid->ledstate |= ledbit;
201 } else {
202 vhid->ledstate &= ~ledbit;
204 kbd_put_ledstate(vhid->ledstate);
205 break;
206 default:
207 fprintf(stderr, "%s: unknown type %d\n", __func__,
208 le16_to_cpu(event->type));
209 break;
213 static Property virtio_input_hid_properties[] = {
214 DEFINE_PROP_STRING("display", VirtIOInputHID, display),
215 DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0),
216 DEFINE_PROP_END_OF_LIST(),
219 static void virtio_input_hid_class_init(ObjectClass *klass, void *data)
221 DeviceClass *dc = DEVICE_CLASS(klass);
222 VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
224 device_class_set_props(dc, virtio_input_hid_properties);
225 vic->realize = virtio_input_hid_realize;
226 vic->unrealize = virtio_input_hid_unrealize;
227 vic->change_active = virtio_input_hid_change_active;
228 vic->handle_status = virtio_input_hid_handle_status;
231 static const TypeInfo virtio_input_hid_info = {
232 .name = TYPE_VIRTIO_INPUT_HID,
233 .parent = TYPE_VIRTIO_INPUT,
234 .instance_size = sizeof(VirtIOInputHID),
235 .class_init = virtio_input_hid_class_init,
236 .abstract = true,
239 /* ----------------------------------------------------------------- */
241 static QemuInputHandler virtio_keyboard_handler = {
242 .name = VIRTIO_ID_NAME_KEYBOARD,
243 .mask = INPUT_EVENT_MASK_KEY,
244 .event = virtio_input_handle_event,
245 .sync = virtio_input_handle_sync,
248 static struct virtio_input_config virtio_keyboard_config[] = {
250 .select = VIRTIO_INPUT_CFG_ID_NAME,
251 .size = sizeof(VIRTIO_ID_NAME_KEYBOARD),
252 .u.string = VIRTIO_ID_NAME_KEYBOARD,
254 .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
255 .size = sizeof(struct virtio_input_devids),
256 .u.ids = {
257 .bustype = const_le16(BUS_VIRTUAL),
258 .vendor = const_le16(0x0627), /* same we use for usb hid devices */
259 .product = const_le16(0x0001),
260 .version = const_le16(0x0001),
263 .select = VIRTIO_INPUT_CFG_EV_BITS,
264 .subsel = EV_REP,
265 .size = 1,
267 .select = VIRTIO_INPUT_CFG_EV_BITS,
268 .subsel = EV_LED,
269 .size = 1,
270 .u.bitmap = {
271 (1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL),
274 { /* end of list */ },
277 static void virtio_keyboard_init(Object *obj)
279 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
280 VirtIOInput *vinput = VIRTIO_INPUT(obj);
282 vhid->handler = &virtio_keyboard_handler;
283 virtio_input_init_config(vinput, virtio_keyboard_config);
284 virtio_input_key_config(vinput, qemu_input_map_qcode_to_linux,
285 qemu_input_map_qcode_to_linux_len);
288 static const TypeInfo virtio_keyboard_info = {
289 .name = TYPE_VIRTIO_KEYBOARD,
290 .parent = TYPE_VIRTIO_INPUT_HID,
291 .instance_size = sizeof(VirtIOInputHID),
292 .instance_init = virtio_keyboard_init,
295 /* ----------------------------------------------------------------- */
297 static QemuInputHandler virtio_mouse_handler = {
298 .name = VIRTIO_ID_NAME_MOUSE,
299 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
300 .event = virtio_input_handle_event,
301 .sync = virtio_input_handle_sync,
304 static struct virtio_input_config virtio_mouse_config_v1[] = {
306 .select = VIRTIO_INPUT_CFG_ID_NAME,
307 .size = sizeof(VIRTIO_ID_NAME_MOUSE),
308 .u.string = VIRTIO_ID_NAME_MOUSE,
310 .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
311 .size = sizeof(struct virtio_input_devids),
312 .u.ids = {
313 .bustype = const_le16(BUS_VIRTUAL),
314 .vendor = const_le16(0x0627), /* same we use for usb hid devices */
315 .product = const_le16(0x0002),
316 .version = const_le16(0x0001),
319 .select = VIRTIO_INPUT_CFG_EV_BITS,
320 .subsel = EV_REL,
321 .size = 1,
322 .u.bitmap = {
323 (1 << REL_X) | (1 << REL_Y),
326 { /* end of list */ },
329 static struct virtio_input_config virtio_mouse_config_v2[] = {
331 .select = VIRTIO_INPUT_CFG_ID_NAME,
332 .size = sizeof(VIRTIO_ID_NAME_MOUSE),
333 .u.string = VIRTIO_ID_NAME_MOUSE,
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),
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))
352 { /* end of list */ },
355 static Property virtio_mouse_properties[] = {
356 DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
357 DEFINE_PROP_END_OF_LIST(),
360 static void virtio_mouse_class_init(ObjectClass *klass, void *data)
362 DeviceClass *dc = DEVICE_CLASS(klass);
364 device_class_set_props(dc, virtio_mouse_properties);
367 static void virtio_mouse_init(Object *obj)
369 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
370 VirtIOInput *vinput = VIRTIO_INPUT(obj);
372 vhid->handler = &virtio_mouse_handler;
373 virtio_input_init_config(vinput, vhid->wheel_axis
374 ? virtio_mouse_config_v2
375 : virtio_mouse_config_v1);
376 virtio_input_key_config(vinput, keymap_button,
377 ARRAY_SIZE(keymap_button));
380 static const TypeInfo virtio_mouse_info = {
381 .name = TYPE_VIRTIO_MOUSE,
382 .parent = TYPE_VIRTIO_INPUT_HID,
383 .instance_size = sizeof(VirtIOInputHID),
384 .instance_init = virtio_mouse_init,
385 .class_init = virtio_mouse_class_init,
388 /* ----------------------------------------------------------------- */
390 static QemuInputHandler virtio_tablet_handler = {
391 .name = VIRTIO_ID_NAME_TABLET,
392 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
393 .event = virtio_input_handle_event,
394 .sync = virtio_input_handle_sync,
397 static struct virtio_input_config virtio_tablet_config_v1[] = {
399 .select = VIRTIO_INPUT_CFG_ID_NAME,
400 .size = sizeof(VIRTIO_ID_NAME_TABLET),
401 .u.string = VIRTIO_ID_NAME_TABLET,
403 .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
404 .size = sizeof(struct virtio_input_devids),
405 .u.ids = {
406 .bustype = const_le16(BUS_VIRTUAL),
407 .vendor = const_le16(0x0627), /* same we use for usb hid devices */
408 .product = const_le16(0x0003),
409 .version = const_le16(0x0001),
412 .select = VIRTIO_INPUT_CFG_EV_BITS,
413 .subsel = EV_ABS,
414 .size = 1,
415 .u.bitmap = {
416 (1 << ABS_X) | (1 << ABS_Y),
419 .select = VIRTIO_INPUT_CFG_ABS_INFO,
420 .subsel = ABS_X,
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),
425 .select = VIRTIO_INPUT_CFG_ABS_INFO,
426 .subsel = ABS_Y,
427 .size = sizeof(virtio_input_absinfo),
428 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
429 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
431 { /* end of list */ },
434 static struct virtio_input_config virtio_tablet_config_v2[] = {
436 .select = VIRTIO_INPUT_CFG_ID_NAME,
437 .size = sizeof(VIRTIO_ID_NAME_TABLET),
438 .u.string = VIRTIO_ID_NAME_TABLET,
440 .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
441 .size = sizeof(struct virtio_input_devids),
442 .u.ids = {
443 .bustype = const_le16(BUS_VIRTUAL),
444 .vendor = const_le16(0x0627), /* same we use for usb hid devices */
445 .product = const_le16(0x0003),
446 .version = const_le16(0x0002),
449 .select = VIRTIO_INPUT_CFG_EV_BITS,
450 .subsel = EV_ABS,
451 .size = 1,
452 .u.bitmap = {
453 (1 << ABS_X) | (1 << ABS_Y),
456 .select = VIRTIO_INPUT_CFG_EV_BITS,
457 .subsel = EV_REL,
458 .size = 2,
459 .u.bitmap = {
461 (1 << (REL_WHEEL - 8))
464 .select = VIRTIO_INPUT_CFG_ABS_INFO,
465 .subsel = ABS_X,
466 .size = sizeof(virtio_input_absinfo),
467 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
468 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
470 .select = VIRTIO_INPUT_CFG_ABS_INFO,
471 .subsel = ABS_Y,
472 .size = sizeof(virtio_input_absinfo),
473 .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
474 .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
476 { /* end of list */ },
479 static Property virtio_tablet_properties[] = {
480 DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
481 DEFINE_PROP_END_OF_LIST(),
484 static void virtio_tablet_class_init(ObjectClass *klass, void *data)
486 DeviceClass *dc = DEVICE_CLASS(klass);
488 device_class_set_props(dc, virtio_tablet_properties);
491 static void virtio_tablet_init(Object *obj)
493 VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
494 VirtIOInput *vinput = VIRTIO_INPUT(obj);
496 vhid->handler = &virtio_tablet_handler;
497 virtio_input_init_config(vinput, vhid->wheel_axis
498 ? virtio_tablet_config_v2
499 : virtio_tablet_config_v1);
500 virtio_input_key_config(vinput, keymap_button,
501 ARRAY_SIZE(keymap_button));
504 static const TypeInfo virtio_tablet_info = {
505 .name = TYPE_VIRTIO_TABLET,
506 .parent = TYPE_VIRTIO_INPUT_HID,
507 .instance_size = sizeof(VirtIOInputHID),
508 .instance_init = virtio_tablet_init,
509 .class_init = virtio_tablet_class_init,
512 /* ----------------------------------------------------------------- */
514 static void virtio_register_types(void)
516 type_register_static(&virtio_input_hid_info);
517 type_register_static(&virtio_keyboard_info);
518 type_register_static(&virtio_mouse_info);
519 type_register_static(&virtio_tablet_info);
522 type_init(virtio_register_types)