xref: /openbmc/qemu/ui/input-legacy.c (revision 134b443512825bed401b6e141447b8cdc22d2efe)
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"
26*17f6315eSDmitry 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_mouse_event(DeviceState * dev,QemuConsole * src,InputEvent * evt)112edd85a3dSGerd Hoffmann static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
113edd85a3dSGerd Hoffmann                                InputEvent *evt)
114edd85a3dSGerd Hoffmann {
1157fb1cf16SEric Blake     static const int bmap[INPUT_BUTTON__MAX] = {
116edd85a3dSGerd Hoffmann         [INPUT_BUTTON_LEFT]   = MOUSE_EVENT_LBUTTON,
117edd85a3dSGerd Hoffmann         [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
118edd85a3dSGerd Hoffmann         [INPUT_BUTTON_RIGHT]  = MOUSE_EVENT_RBUTTON,
119edd85a3dSGerd Hoffmann     };
120edd85a3dSGerd Hoffmann     QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
121b5a1b443SEric Blake     InputBtnEvent *btn;
122b5a1b443SEric Blake     InputMoveEvent *move;
123edd85a3dSGerd Hoffmann 
124568c73a4SEric Blake     switch (evt->type) {
125edd85a3dSGerd Hoffmann     case INPUT_EVENT_KIND_BTN:
12632bafa8fSEric Blake         btn = evt->u.btn.data;
127b5a1b443SEric Blake         if (btn->down) {
128b5a1b443SEric Blake             s->buttons |= bmap[btn->button];
129edd85a3dSGerd Hoffmann         } else {
130b5a1b443SEric Blake             s->buttons &= ~bmap[btn->button];
131edd85a3dSGerd Hoffmann         }
132b5a1b443SEric Blake         if (btn->down && btn->button == INPUT_BUTTON_WHEEL_UP) {
133dbb2a132SGerd Hoffmann             s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
134dbb2a132SGerd Hoffmann                                     s->axis[INPUT_AXIS_X],
135dbb2a132SGerd Hoffmann                                     s->axis[INPUT_AXIS_Y],
136dbb2a132SGerd Hoffmann                                     -1,
137dbb2a132SGerd Hoffmann                                     s->buttons);
138dbb2a132SGerd Hoffmann         }
139b5a1b443SEric Blake         if (btn->down && btn->button == INPUT_BUTTON_WHEEL_DOWN) {
140dbb2a132SGerd Hoffmann             s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
141dbb2a132SGerd Hoffmann                                     s->axis[INPUT_AXIS_X],
142dbb2a132SGerd Hoffmann                                     s->axis[INPUT_AXIS_Y],
143dbb2a132SGerd Hoffmann                                     1,
144dbb2a132SGerd Hoffmann                                     s->buttons);
145dbb2a132SGerd Hoffmann         }
146*17f6315eSDmitry Petrov         if (btn->down && btn->button == INPUT_BUTTON_WHEEL_RIGHT) {
147*17f6315eSDmitry Petrov             s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
148*17f6315eSDmitry Petrov                                     s->axis[INPUT_AXIS_X],
149*17f6315eSDmitry Petrov                                     s->axis[INPUT_AXIS_Y],
150*17f6315eSDmitry Petrov                                     -2,
151*17f6315eSDmitry Petrov                                     s->buttons);
152*17f6315eSDmitry Petrov         }
153*17f6315eSDmitry Petrov         if (btn->down && btn->button == INPUT_BUTTON_WHEEL_LEFT) {
154*17f6315eSDmitry Petrov             s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
155*17f6315eSDmitry Petrov                                     s->axis[INPUT_AXIS_X],
156*17f6315eSDmitry Petrov                                     s->axis[INPUT_AXIS_Y],
157*17f6315eSDmitry Petrov                                     2,
158*17f6315eSDmitry Petrov                                     s->buttons);
159*17f6315eSDmitry Petrov         }
160edd85a3dSGerd Hoffmann         break;
161edd85a3dSGerd Hoffmann     case INPUT_EVENT_KIND_ABS:
16232bafa8fSEric Blake         move = evt->u.abs.data;
163b5a1b443SEric Blake         s->axis[move->axis] = move->value;
164edd85a3dSGerd Hoffmann         break;
165edd85a3dSGerd Hoffmann     case INPUT_EVENT_KIND_REL:
16632bafa8fSEric Blake         move = evt->u.rel.data;
167b5a1b443SEric Blake         s->axis[move->axis] += move->value;
168edd85a3dSGerd Hoffmann         break;
169edd85a3dSGerd Hoffmann     default:
170edd85a3dSGerd Hoffmann         break;
171edd85a3dSGerd Hoffmann     }
172edd85a3dSGerd Hoffmann }
173edd85a3dSGerd Hoffmann 
legacy_mouse_sync(DeviceState * dev)174edd85a3dSGerd Hoffmann static void legacy_mouse_sync(DeviceState *dev)
175edd85a3dSGerd Hoffmann {
176edd85a3dSGerd Hoffmann     QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
177edd85a3dSGerd Hoffmann 
178edd85a3dSGerd Hoffmann     s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
179edd85a3dSGerd Hoffmann                             s->axis[INPUT_AXIS_X],
180edd85a3dSGerd Hoffmann                             s->axis[INPUT_AXIS_Y],
181edd85a3dSGerd Hoffmann                             0,
182edd85a3dSGerd Hoffmann                             s->buttons);
183edd85a3dSGerd Hoffmann 
184edd85a3dSGerd Hoffmann     if (!s->qemu_put_mouse_event_absolute) {
185edd85a3dSGerd Hoffmann         s->axis[INPUT_AXIS_X] = 0;
186edd85a3dSGerd Hoffmann         s->axis[INPUT_AXIS_Y] = 0;
187edd85a3dSGerd Hoffmann     }
188edd85a3dSGerd Hoffmann }
189edd85a3dSGerd Hoffmann 
qemu_add_mouse_event_handler(QEMUPutMouseEvent * func,void * opaque,int absolute,const char * name)1907ad95ff7SGerd Hoffmann QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
1917ad95ff7SGerd Hoffmann                                                 void *opaque, int absolute,
1927ad95ff7SGerd Hoffmann                                                 const char *name)
1937ad95ff7SGerd Hoffmann {
1947ad95ff7SGerd Hoffmann     QEMUPutMouseEntry *s;
1957ad95ff7SGerd Hoffmann 
196fedf0d35SMarkus Armbruster     s = g_new0(QEMUPutMouseEntry, 1);
1977ad95ff7SGerd Hoffmann 
1987ad95ff7SGerd Hoffmann     s->qemu_put_mouse_event = func;
1997ad95ff7SGerd Hoffmann     s->qemu_put_mouse_event_opaque = opaque;
2007ad95ff7SGerd Hoffmann     s->qemu_put_mouse_event_absolute = absolute;
2017ad95ff7SGerd Hoffmann 
202edd85a3dSGerd Hoffmann     s->h.name = name;
203edd85a3dSGerd Hoffmann     s->h.mask = INPUT_EVENT_MASK_BTN |
204edd85a3dSGerd Hoffmann         (absolute ? INPUT_EVENT_MASK_ABS : INPUT_EVENT_MASK_REL);
205edd85a3dSGerd Hoffmann     s->h.event = legacy_mouse_event;
206edd85a3dSGerd Hoffmann     s->h.sync = legacy_mouse_sync;
207edd85a3dSGerd Hoffmann     s->s = qemu_input_handler_register((DeviceState *)s,
208edd85a3dSGerd Hoffmann                                        &s->h);
209edd85a3dSGerd Hoffmann 
2107ad95ff7SGerd Hoffmann     return s;
2117ad95ff7SGerd Hoffmann }
2127ad95ff7SGerd Hoffmann 
qemu_activate_mouse_event_handler(QEMUPutMouseEntry * entry)2137ad95ff7SGerd Hoffmann void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
2147ad95ff7SGerd Hoffmann {
215edd85a3dSGerd Hoffmann     qemu_input_handler_activate(entry->s);
2167ad95ff7SGerd Hoffmann }
2177ad95ff7SGerd Hoffmann 
qemu_remove_mouse_event_handler(QEMUPutMouseEntry * entry)2187ad95ff7SGerd Hoffmann void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
2197ad95ff7SGerd Hoffmann {
220edd85a3dSGerd Hoffmann     qemu_input_handler_unregister(entry->s);
221edd85a3dSGerd Hoffmann 
2227ad95ff7SGerd Hoffmann     g_free(entry);
2237ad95ff7SGerd Hoffmann }
2247ad95ff7SGerd Hoffmann 
qemu_add_led_event_handler(QEMUPutLEDEvent * func,void * opaque)2257ad95ff7SGerd Hoffmann QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
2267ad95ff7SGerd Hoffmann                                             void *opaque)
2277ad95ff7SGerd Hoffmann {
2287ad95ff7SGerd Hoffmann     QEMUPutLEDEntry *s;
2297ad95ff7SGerd Hoffmann 
230fedf0d35SMarkus Armbruster     s = g_new0(QEMUPutLEDEntry, 1);
2317ad95ff7SGerd Hoffmann 
2327ad95ff7SGerd Hoffmann     s->put_led = func;
2337ad95ff7SGerd Hoffmann     s->opaque = opaque;
2347ad95ff7SGerd Hoffmann     QTAILQ_INSERT_TAIL(&led_handlers, s, next);
2357ad95ff7SGerd Hoffmann     return s;
2367ad95ff7SGerd Hoffmann }
2377ad95ff7SGerd Hoffmann 
qemu_remove_led_event_handler(QEMUPutLEDEntry * entry)2387ad95ff7SGerd Hoffmann void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
2397ad95ff7SGerd Hoffmann {
2407ad95ff7SGerd Hoffmann     if (entry == NULL)
2417ad95ff7SGerd Hoffmann         return;
2427ad95ff7SGerd Hoffmann     QTAILQ_REMOVE(&led_handlers, entry, next);
2437ad95ff7SGerd Hoffmann     g_free(entry);
2447ad95ff7SGerd Hoffmann }
2457ad95ff7SGerd Hoffmann 
kbd_put_ledstate(int ledstate)2467ad95ff7SGerd Hoffmann void kbd_put_ledstate(int ledstate)
2477ad95ff7SGerd Hoffmann {
2487ad95ff7SGerd Hoffmann     QEMUPutLEDEntry *cursor;
2497ad95ff7SGerd Hoffmann 
2507ad95ff7SGerd Hoffmann     QTAILQ_FOREACH(cursor, &led_handlers, next) {
2517ad95ff7SGerd Hoffmann         cursor->put_led(cursor->opaque, ledstate);
2527ad95ff7SGerd Hoffmann     }
2537ad95ff7SGerd Hoffmann }
254