xref: /openbmc/qemu/ui/input-legacy.c (revision 9f1b1002)
17ad95ff7SGerd Hoffmann /*
27ad95ff7SGerd Hoffmann  * QEMU System Emulator
37ad95ff7SGerd Hoffmann  *
47ad95ff7SGerd Hoffmann  * Copyright (c) 2003-2008 Fabrice Bellard
57ad95ff7SGerd Hoffmann  *
67ad95ff7SGerd Hoffmann  * Permission is hereby granted, free of charge, to any person obtaining a copy
77ad95ff7SGerd Hoffmann  * of this software and associated documentation files (the "Software"), to deal
87ad95ff7SGerd Hoffmann  * in the Software without restriction, including without limitation the rights
97ad95ff7SGerd Hoffmann  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
107ad95ff7SGerd Hoffmann  * copies of the Software, and to permit persons to whom the Software is
117ad95ff7SGerd Hoffmann  * furnished to do so, subject to the following conditions:
127ad95ff7SGerd Hoffmann  *
137ad95ff7SGerd Hoffmann  * The above copyright notice and this permission notice shall be included in
147ad95ff7SGerd Hoffmann  * all copies or substantial portions of the Software.
157ad95ff7SGerd Hoffmann  *
167ad95ff7SGerd Hoffmann  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
177ad95ff7SGerd Hoffmann  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187ad95ff7SGerd Hoffmann  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
197ad95ff7SGerd Hoffmann  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
207ad95ff7SGerd Hoffmann  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
217ad95ff7SGerd Hoffmann  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
227ad95ff7SGerd Hoffmann  * THE SOFTWARE.
237ad95ff7SGerd Hoffmann  */
247ad95ff7SGerd Hoffmann 
25e16f4c87SPeter Maydell #include "qemu/osdep.h"
2617f6315eSDmitry Petrov #include "qemu/log.h"
279af23989SMarkus Armbruster #include "qapi/qapi-commands-ui.h"
287ad95ff7SGerd Hoffmann #include "ui/console.h"
290041e9a0SMichael S. Tsirkin #include "keymaps.h"
309784e579SGerd Hoffmann #include "ui/input.h"
317ad95ff7SGerd Hoffmann 
327ad95ff7SGerd Hoffmann struct QEMUPutMouseEntry {
337ad95ff7SGerd Hoffmann     QEMUPutMouseEvent *qemu_put_mouse_event;
347ad95ff7SGerd Hoffmann     void *qemu_put_mouse_event_opaque;
357ad95ff7SGerd Hoffmann     int qemu_put_mouse_event_absolute;
36edd85a3dSGerd Hoffmann 
37edd85a3dSGerd Hoffmann     /* new input core */
38edd85a3dSGerd Hoffmann     QemuInputHandler h;
39edd85a3dSGerd Hoffmann     QemuInputHandlerState *s;
407fb1cf16SEric Blake     int axis[INPUT_AXIS__MAX];
41edd85a3dSGerd Hoffmann     int buttons;
427ad95ff7SGerd Hoffmann };
437ad95ff7SGerd Hoffmann 
447ad95ff7SGerd Hoffmann struct QEMUPutKbdEntry {
457ad95ff7SGerd Hoffmann     QEMUPutKBDEvent *put_kbd;
467ad95ff7SGerd Hoffmann     void *opaque;
479784e579SGerd Hoffmann     QemuInputHandlerState *s;
487ad95ff7SGerd Hoffmann };
497ad95ff7SGerd Hoffmann 
507ad95ff7SGerd Hoffmann struct QEMUPutLEDEntry {
517ad95ff7SGerd Hoffmann     QEMUPutLEDEvent *put_led;
527ad95ff7SGerd Hoffmann     void *opaque;
537ad95ff7SGerd Hoffmann     QTAILQ_ENTRY(QEMUPutLEDEntry) next;
547ad95ff7SGerd Hoffmann };
557ad95ff7SGerd Hoffmann 
567ad95ff7SGerd Hoffmann static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
577ad95ff7SGerd Hoffmann     QTAILQ_HEAD_INITIALIZER(led_handlers);
587ad95ff7SGerd Hoffmann 
index_from_key(const char * key,size_t key_length)5964ffbe04SWolfgang Bumiller int index_from_key(const char *key, size_t key_length)
607ad95ff7SGerd Hoffmann {
617ad95ff7SGerd Hoffmann     int i;
627ad95ff7SGerd Hoffmann 
631c236ba5SMarkus Armbruster     for (i = 0; i < Q_KEY_CODE__MAX; i++) {
64977c736fSMarkus Armbruster         if (!strncmp(key, QKeyCode_str(i), key_length) &&
65977c736fSMarkus Armbruster             !QKeyCode_str(i)[key_length]) {
667ad95ff7SGerd Hoffmann             break;
677ad95ff7SGerd Hoffmann         }
687ad95ff7SGerd Hoffmann     }
697ad95ff7SGerd Hoffmann 
707fb1cf16SEric Blake     /* Return Q_KEY_CODE__MAX if the key is invalid */
717ad95ff7SGerd Hoffmann     return i;
727ad95ff7SGerd Hoffmann }
737ad95ff7SGerd Hoffmann 
copy_key_value(KeyValue * src)74ce53f2f9SGerd Hoffmann static KeyValue *copy_key_value(KeyValue *src)
75ce53f2f9SGerd Hoffmann {
76ce53f2f9SGerd Hoffmann     KeyValue *dst = g_new(KeyValue, 1);
77ce53f2f9SGerd Hoffmann     memcpy(dst, src, sizeof(*src));
781d5b8d77SDaniel P. Berrange     if (dst->type == KEY_VALUE_KIND_NUMBER) {
791d5b8d77SDaniel P. Berrange         QKeyCode code = qemu_input_key_number_to_qcode(dst->u.number.data);
801d5b8d77SDaniel P. Berrange         dst->type = KEY_VALUE_KIND_QCODE;
811d5b8d77SDaniel P. Berrange         dst->u.qcode.data = code;
821d5b8d77SDaniel P. Berrange     }
83ce53f2f9SGerd Hoffmann     return dst;
847ad95ff7SGerd Hoffmann }
857ad95ff7SGerd Hoffmann 
qmp_send_key(KeyValueList * keys,bool has_hold_time,int64_t hold_time,Error ** errp)867ad95ff7SGerd Hoffmann void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
877ad95ff7SGerd Hoffmann                   Error **errp)
887ad95ff7SGerd Hoffmann {
897ad95ff7SGerd Hoffmann     KeyValueList *p;
90e37f2024SGerd Hoffmann     KeyValue **up = NULL;
91e37f2024SGerd Hoffmann     int count = 0;
927ad95ff7SGerd Hoffmann 
937ad95ff7SGerd Hoffmann     if (!has_hold_time) {
942e377f17SGerd Hoffmann         hold_time = 0; /* use default */
957ad95ff7SGerd Hoffmann     }
967ad95ff7SGerd Hoffmann 
977ad95ff7SGerd Hoffmann     for (p = keys; p != NULL; p = p->next) {
98ce53f2f9SGerd Hoffmann         qemu_input_event_send_key(NULL, copy_key_value(p->value), true);
992e377f17SGerd Hoffmann         qemu_input_event_send_key_delay(hold_time);
100e37f2024SGerd Hoffmann         up = g_realloc(up, sizeof(*up) * (count+1));
101e37f2024SGerd Hoffmann         up[count] = copy_key_value(p->value);
102e37f2024SGerd Hoffmann         count++;
1037ad95ff7SGerd Hoffmann     }
104e37f2024SGerd Hoffmann     while (count) {
105e37f2024SGerd Hoffmann         count--;
106e37f2024SGerd Hoffmann         qemu_input_event_send_key(NULL, up[count], false);
1072e377f17SGerd Hoffmann         qemu_input_event_send_key_delay(hold_time);
1082e377f17SGerd Hoffmann     }
109e37f2024SGerd Hoffmann     g_free(up);
1107ad95ff7SGerd Hoffmann }
1117ad95ff7SGerd Hoffmann 
legacy_kbd_event(DeviceState * dev,QemuConsole * src,InputEvent * evt)1129784e579SGerd Hoffmann static void legacy_kbd_event(DeviceState *dev, QemuConsole *src,
1139784e579SGerd Hoffmann                              InputEvent *evt)
1149784e579SGerd Hoffmann {
1159784e579SGerd Hoffmann     QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev;
11602aa76c2SGerd Hoffmann     int scancodes[3], i, count;
11732bafa8fSEric Blake     InputKeyEvent *key = evt->u.key.data;
1189784e579SGerd Hoffmann 
1199784e579SGerd Hoffmann     if (!entry || !entry->put_kbd) {
1209784e579SGerd Hoffmann         return;
1219784e579SGerd Hoffmann     }
122b5a1b443SEric Blake     count = qemu_input_key_value_to_scancode(key->key,
123b5a1b443SEric Blake                                              key->down,
12402aa76c2SGerd Hoffmann                                              scancodes);
12502aa76c2SGerd Hoffmann     for (i = 0; i < count; i++) {
12602aa76c2SGerd Hoffmann         entry->put_kbd(entry->opaque, scancodes[i]);
1279784e579SGerd Hoffmann     }
1289784e579SGerd Hoffmann }
1299784e579SGerd Hoffmann 
130*9f1b1002SPhilippe Mathieu-Daudé static const QemuInputHandler legacy_kbd_handler = {
1319784e579SGerd Hoffmann     .name  = "legacy-kbd",
1329784e579SGerd Hoffmann     .mask  = INPUT_EVENT_MASK_KEY,
1339784e579SGerd Hoffmann     .event = legacy_kbd_event,
1349784e579SGerd Hoffmann };
1359784e579SGerd Hoffmann 
qemu_add_kbd_event_handler(QEMUPutKBDEvent * func,void * opaque)1367ad95ff7SGerd Hoffmann QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
1377ad95ff7SGerd Hoffmann {
1387ad95ff7SGerd Hoffmann     QEMUPutKbdEntry *entry;
1397ad95ff7SGerd Hoffmann 
1409784e579SGerd Hoffmann     entry = g_new0(QEMUPutKbdEntry, 1);
1417ad95ff7SGerd Hoffmann     entry->put_kbd = func;
1427ad95ff7SGerd Hoffmann     entry->opaque = opaque;
1439784e579SGerd Hoffmann     entry->s = qemu_input_handler_register((DeviceState *)entry,
1449784e579SGerd Hoffmann                                            &legacy_kbd_handler);
1457f5e07d9SGerd Hoffmann     qemu_input_handler_activate(entry->s);
1467ad95ff7SGerd Hoffmann     return entry;
1477ad95ff7SGerd Hoffmann }
1487ad95ff7SGerd Hoffmann 
legacy_mouse_event(DeviceState * dev,QemuConsole * src,InputEvent * evt)149edd85a3dSGerd Hoffmann static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
150edd85a3dSGerd Hoffmann                                InputEvent *evt)
151edd85a3dSGerd Hoffmann {
1527fb1cf16SEric Blake     static const int bmap[INPUT_BUTTON__MAX] = {
153edd85a3dSGerd Hoffmann         [INPUT_BUTTON_LEFT]   = MOUSE_EVENT_LBUTTON,
154edd85a3dSGerd Hoffmann         [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
155edd85a3dSGerd Hoffmann         [INPUT_BUTTON_RIGHT]  = MOUSE_EVENT_RBUTTON,
156edd85a3dSGerd Hoffmann     };
157edd85a3dSGerd Hoffmann     QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
158b5a1b443SEric Blake     InputBtnEvent *btn;
159b5a1b443SEric Blake     InputMoveEvent *move;
160edd85a3dSGerd Hoffmann 
161568c73a4SEric Blake     switch (evt->type) {
162edd85a3dSGerd Hoffmann     case INPUT_EVENT_KIND_BTN:
16332bafa8fSEric Blake         btn = evt->u.btn.data;
164b5a1b443SEric Blake         if (btn->down) {
165b5a1b443SEric Blake             s->buttons |= bmap[btn->button];
166edd85a3dSGerd Hoffmann         } else {
167b5a1b443SEric Blake             s->buttons &= ~bmap[btn->button];
168edd85a3dSGerd Hoffmann         }
169b5a1b443SEric Blake         if (btn->down && btn->button == INPUT_BUTTON_WHEEL_UP) {
170dbb2a132SGerd Hoffmann             s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
171dbb2a132SGerd Hoffmann                                     s->axis[INPUT_AXIS_X],
172dbb2a132SGerd Hoffmann                                     s->axis[INPUT_AXIS_Y],
173dbb2a132SGerd Hoffmann                                     -1,
174dbb2a132SGerd Hoffmann                                     s->buttons);
175dbb2a132SGerd Hoffmann         }
176b5a1b443SEric Blake         if (btn->down && btn->button == INPUT_BUTTON_WHEEL_DOWN) {
177dbb2a132SGerd Hoffmann             s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
178dbb2a132SGerd Hoffmann                                     s->axis[INPUT_AXIS_X],
179dbb2a132SGerd Hoffmann                                     s->axis[INPUT_AXIS_Y],
180dbb2a132SGerd Hoffmann                                     1,
181dbb2a132SGerd Hoffmann                                     s->buttons);
182dbb2a132SGerd Hoffmann         }
18317f6315eSDmitry Petrov         if (btn->down && btn->button == INPUT_BUTTON_WHEEL_RIGHT) {
18417f6315eSDmitry Petrov             s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
18517f6315eSDmitry Petrov                                     s->axis[INPUT_AXIS_X],
18617f6315eSDmitry Petrov                                     s->axis[INPUT_AXIS_Y],
18717f6315eSDmitry Petrov                                     -2,
18817f6315eSDmitry Petrov                                     s->buttons);
18917f6315eSDmitry Petrov         }
19017f6315eSDmitry Petrov         if (btn->down && btn->button == INPUT_BUTTON_WHEEL_LEFT) {
19117f6315eSDmitry Petrov             s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
19217f6315eSDmitry Petrov                                     s->axis[INPUT_AXIS_X],
19317f6315eSDmitry Petrov                                     s->axis[INPUT_AXIS_Y],
19417f6315eSDmitry Petrov                                     2,
19517f6315eSDmitry Petrov                                     s->buttons);
19617f6315eSDmitry Petrov         }
197edd85a3dSGerd Hoffmann         break;
198edd85a3dSGerd Hoffmann     case INPUT_EVENT_KIND_ABS:
19932bafa8fSEric Blake         move = evt->u.abs.data;
200b5a1b443SEric Blake         s->axis[move->axis] = move->value;
201edd85a3dSGerd Hoffmann         break;
202edd85a3dSGerd Hoffmann     case INPUT_EVENT_KIND_REL:
20332bafa8fSEric Blake         move = evt->u.rel.data;
204b5a1b443SEric Blake         s->axis[move->axis] += move->value;
205edd85a3dSGerd Hoffmann         break;
206edd85a3dSGerd Hoffmann     default:
207edd85a3dSGerd Hoffmann         break;
208edd85a3dSGerd Hoffmann     }
209edd85a3dSGerd Hoffmann }
210edd85a3dSGerd Hoffmann 
legacy_mouse_sync(DeviceState * dev)211edd85a3dSGerd Hoffmann static void legacy_mouse_sync(DeviceState *dev)
212edd85a3dSGerd Hoffmann {
213edd85a3dSGerd Hoffmann     QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
214edd85a3dSGerd Hoffmann 
215edd85a3dSGerd Hoffmann     s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
216edd85a3dSGerd Hoffmann                             s->axis[INPUT_AXIS_X],
217edd85a3dSGerd Hoffmann                             s->axis[INPUT_AXIS_Y],
218edd85a3dSGerd Hoffmann                             0,
219edd85a3dSGerd Hoffmann                             s->buttons);
220edd85a3dSGerd Hoffmann 
221edd85a3dSGerd Hoffmann     if (!s->qemu_put_mouse_event_absolute) {
222edd85a3dSGerd Hoffmann         s->axis[INPUT_AXIS_X] = 0;
223edd85a3dSGerd Hoffmann         s->axis[INPUT_AXIS_Y] = 0;
224edd85a3dSGerd Hoffmann     }
225edd85a3dSGerd Hoffmann }
226edd85a3dSGerd Hoffmann 
qemu_add_mouse_event_handler(QEMUPutMouseEvent * func,void * opaque,int absolute,const char * name)2277ad95ff7SGerd Hoffmann QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
2287ad95ff7SGerd Hoffmann                                                 void *opaque, int absolute,
2297ad95ff7SGerd Hoffmann                                                 const char *name)
2307ad95ff7SGerd Hoffmann {
2317ad95ff7SGerd Hoffmann     QEMUPutMouseEntry *s;
2327ad95ff7SGerd Hoffmann 
233fedf0d35SMarkus Armbruster     s = g_new0(QEMUPutMouseEntry, 1);
2347ad95ff7SGerd Hoffmann 
2357ad95ff7SGerd Hoffmann     s->qemu_put_mouse_event = func;
2367ad95ff7SGerd Hoffmann     s->qemu_put_mouse_event_opaque = opaque;
2377ad95ff7SGerd Hoffmann     s->qemu_put_mouse_event_absolute = absolute;
2387ad95ff7SGerd Hoffmann 
239edd85a3dSGerd Hoffmann     s->h.name = name;
240edd85a3dSGerd Hoffmann     s->h.mask = INPUT_EVENT_MASK_BTN |
241edd85a3dSGerd Hoffmann         (absolute ? INPUT_EVENT_MASK_ABS : INPUT_EVENT_MASK_REL);
242edd85a3dSGerd Hoffmann     s->h.event = legacy_mouse_event;
243edd85a3dSGerd Hoffmann     s->h.sync = legacy_mouse_sync;
244edd85a3dSGerd Hoffmann     s->s = qemu_input_handler_register((DeviceState *)s,
245edd85a3dSGerd Hoffmann                                        &s->h);
246edd85a3dSGerd Hoffmann 
2477ad95ff7SGerd Hoffmann     return s;
2487ad95ff7SGerd Hoffmann }
2497ad95ff7SGerd Hoffmann 
qemu_activate_mouse_event_handler(QEMUPutMouseEntry * entry)2507ad95ff7SGerd Hoffmann void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
2517ad95ff7SGerd Hoffmann {
252edd85a3dSGerd Hoffmann     qemu_input_handler_activate(entry->s);
2537ad95ff7SGerd Hoffmann }
2547ad95ff7SGerd Hoffmann 
qemu_remove_mouse_event_handler(QEMUPutMouseEntry * entry)2557ad95ff7SGerd Hoffmann void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
2567ad95ff7SGerd Hoffmann {
257edd85a3dSGerd Hoffmann     qemu_input_handler_unregister(entry->s);
258edd85a3dSGerd Hoffmann 
2597ad95ff7SGerd Hoffmann     g_free(entry);
2607ad95ff7SGerd Hoffmann }
2617ad95ff7SGerd Hoffmann 
qemu_add_led_event_handler(QEMUPutLEDEvent * func,void * opaque)2627ad95ff7SGerd Hoffmann QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
2637ad95ff7SGerd Hoffmann                                             void *opaque)
2647ad95ff7SGerd Hoffmann {
2657ad95ff7SGerd Hoffmann     QEMUPutLEDEntry *s;
2667ad95ff7SGerd Hoffmann 
267fedf0d35SMarkus Armbruster     s = g_new0(QEMUPutLEDEntry, 1);
2687ad95ff7SGerd Hoffmann 
2697ad95ff7SGerd Hoffmann     s->put_led = func;
2707ad95ff7SGerd Hoffmann     s->opaque = opaque;
2717ad95ff7SGerd Hoffmann     QTAILQ_INSERT_TAIL(&led_handlers, s, next);
2727ad95ff7SGerd Hoffmann     return s;
2737ad95ff7SGerd Hoffmann }
2747ad95ff7SGerd Hoffmann 
qemu_remove_led_event_handler(QEMUPutLEDEntry * entry)2757ad95ff7SGerd Hoffmann void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
2767ad95ff7SGerd Hoffmann {
2777ad95ff7SGerd Hoffmann     if (entry == NULL)
2787ad95ff7SGerd Hoffmann         return;
2797ad95ff7SGerd Hoffmann     QTAILQ_REMOVE(&led_handlers, entry, next);
2807ad95ff7SGerd Hoffmann     g_free(entry);
2817ad95ff7SGerd Hoffmann }
2827ad95ff7SGerd Hoffmann 
kbd_put_ledstate(int ledstate)2837ad95ff7SGerd Hoffmann void kbd_put_ledstate(int ledstate)
2847ad95ff7SGerd Hoffmann {
2857ad95ff7SGerd Hoffmann     QEMUPutLEDEntry *cursor;
2867ad95ff7SGerd Hoffmann 
2877ad95ff7SGerd Hoffmann     QTAILQ_FOREACH(cursor, &led_handlers, next) {
2887ad95ff7SGerd Hoffmann         cursor->put_led(cursor->opaque, ledstate);
2897ad95ff7SGerd Hoffmann     }
2907ad95ff7SGerd Hoffmann }
291