xref: /openbmc/qemu/ui/input.c (revision 6165daa4c8431d9d60382352864b46f34dd61ab4)
1 /*
2  * QEMU System Emulator
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "sysemu/sysemu.h"
26 #include "monitor/monitor.h"
27 #include "ui/console.h"
28 #include "qapi/error.h"
29 #include "qmp-commands.h"
30 #include "qapi-types.h"
31 
32 static QEMUPutKBDEvent *qemu_put_kbd_event;
33 static void *qemu_put_kbd_event_opaque;
34 static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
35 static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
36     QTAILQ_HEAD_INITIALIZER(mouse_handlers);
37 static NotifierList mouse_mode_notifiers =
38     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
39 
40 static const int key_defs[] = {
41     [Q_KEY_CODE_SHIFT] = 0x2a,
42     [Q_KEY_CODE_SHIFT_R] = 0x36,
43 
44     [Q_KEY_CODE_ALT] = 0x38,
45     [Q_KEY_CODE_ALT_R] = 0xb8,
46     [Q_KEY_CODE_ALTGR] = 0x64,
47     [Q_KEY_CODE_ALTGR_R] = 0xe4,
48     [Q_KEY_CODE_CTRL] = 0x1d,
49     [Q_KEY_CODE_CTRL_R] = 0x9d,
50 
51     [Q_KEY_CODE_MENU] = 0xdd,
52 
53     [Q_KEY_CODE_ESC] = 0x01,
54 
55     [Q_KEY_CODE_1] = 0x02,
56     [Q_KEY_CODE_2] = 0x03,
57     [Q_KEY_CODE_3] = 0x04,
58     [Q_KEY_CODE_4] = 0x05,
59     [Q_KEY_CODE_5] = 0x06,
60     [Q_KEY_CODE_6] = 0x07,
61     [Q_KEY_CODE_7] = 0x08,
62     [Q_KEY_CODE_8] = 0x09,
63     [Q_KEY_CODE_9] = 0x0a,
64     [Q_KEY_CODE_0] = 0x0b,
65     [Q_KEY_CODE_MINUS] = 0x0c,
66     [Q_KEY_CODE_EQUAL] = 0x0d,
67     [Q_KEY_CODE_BACKSPACE] = 0x0e,
68 
69     [Q_KEY_CODE_TAB] = 0x0f,
70     [Q_KEY_CODE_Q] = 0x10,
71     [Q_KEY_CODE_W] = 0x11,
72     [Q_KEY_CODE_E] = 0x12,
73     [Q_KEY_CODE_R] = 0x13,
74     [Q_KEY_CODE_T] = 0x14,
75     [Q_KEY_CODE_Y] = 0x15,
76     [Q_KEY_CODE_U] = 0x16,
77     [Q_KEY_CODE_I] = 0x17,
78     [Q_KEY_CODE_O] = 0x18,
79     [Q_KEY_CODE_P] = 0x19,
80     [Q_KEY_CODE_BRACKET_LEFT] = 0x1a,
81     [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b,
82     [Q_KEY_CODE_RET] = 0x1c,
83 
84     [Q_KEY_CODE_A] = 0x1e,
85     [Q_KEY_CODE_S] = 0x1f,
86     [Q_KEY_CODE_D] = 0x20,
87     [Q_KEY_CODE_F] = 0x21,
88     [Q_KEY_CODE_G] = 0x22,
89     [Q_KEY_CODE_H] = 0x23,
90     [Q_KEY_CODE_J] = 0x24,
91     [Q_KEY_CODE_K] = 0x25,
92     [Q_KEY_CODE_L] = 0x26,
93     [Q_KEY_CODE_SEMICOLON] = 0x27,
94     [Q_KEY_CODE_APOSTROPHE] = 0x28,
95     [Q_KEY_CODE_GRAVE_ACCENT] = 0x29,
96 
97     [Q_KEY_CODE_BACKSLASH] = 0x2b,
98     [Q_KEY_CODE_Z] = 0x2c,
99     [Q_KEY_CODE_X] = 0x2d,
100     [Q_KEY_CODE_C] = 0x2e,
101     [Q_KEY_CODE_V] = 0x2f,
102     [Q_KEY_CODE_B] = 0x30,
103     [Q_KEY_CODE_N] = 0x31,
104     [Q_KEY_CODE_M] = 0x32,
105     [Q_KEY_CODE_COMMA] = 0x33,
106     [Q_KEY_CODE_DOT] = 0x34,
107     [Q_KEY_CODE_SLASH] = 0x35,
108 
109     [Q_KEY_CODE_ASTERISK] = 0x37,
110 
111     [Q_KEY_CODE_SPC] = 0x39,
112     [Q_KEY_CODE_CAPS_LOCK] = 0x3a,
113     [Q_KEY_CODE_F1] = 0x3b,
114     [Q_KEY_CODE_F2] = 0x3c,
115     [Q_KEY_CODE_F3] = 0x3d,
116     [Q_KEY_CODE_F4] = 0x3e,
117     [Q_KEY_CODE_F5] = 0x3f,
118     [Q_KEY_CODE_F6] = 0x40,
119     [Q_KEY_CODE_F7] = 0x41,
120     [Q_KEY_CODE_F8] = 0x42,
121     [Q_KEY_CODE_F9] = 0x43,
122     [Q_KEY_CODE_F10] = 0x44,
123     [Q_KEY_CODE_NUM_LOCK] = 0x45,
124     [Q_KEY_CODE_SCROLL_LOCK] = 0x46,
125 
126     [Q_KEY_CODE_KP_DIVIDE] = 0xb5,
127     [Q_KEY_CODE_KP_MULTIPLY] = 0x37,
128     [Q_KEY_CODE_KP_SUBTRACT] = 0x4a,
129     [Q_KEY_CODE_KP_ADD] = 0x4e,
130     [Q_KEY_CODE_KP_ENTER] = 0x9c,
131     [Q_KEY_CODE_KP_DECIMAL] = 0x53,
132     [Q_KEY_CODE_SYSRQ] = 0x54,
133 
134     [Q_KEY_CODE_KP_0] = 0x52,
135     [Q_KEY_CODE_KP_1] = 0x4f,
136     [Q_KEY_CODE_KP_2] = 0x50,
137     [Q_KEY_CODE_KP_3] = 0x51,
138     [Q_KEY_CODE_KP_4] = 0x4b,
139     [Q_KEY_CODE_KP_5] = 0x4c,
140     [Q_KEY_CODE_KP_6] = 0x4d,
141     [Q_KEY_CODE_KP_7] = 0x47,
142     [Q_KEY_CODE_KP_8] = 0x48,
143     [Q_KEY_CODE_KP_9] = 0x49,
144 
145     [Q_KEY_CODE_LESS] = 0x56,
146 
147     [Q_KEY_CODE_F11] = 0x57,
148     [Q_KEY_CODE_F12] = 0x58,
149 
150     [Q_KEY_CODE_PRINT] = 0xb7,
151 
152     [Q_KEY_CODE_HOME] = 0xc7,
153     [Q_KEY_CODE_PGUP] = 0xc9,
154     [Q_KEY_CODE_PGDN] = 0xd1,
155     [Q_KEY_CODE_END] = 0xcf,
156 
157     [Q_KEY_CODE_LEFT] = 0xcb,
158     [Q_KEY_CODE_UP] = 0xc8,
159     [Q_KEY_CODE_DOWN] = 0xd0,
160     [Q_KEY_CODE_RIGHT] = 0xcd,
161 
162     [Q_KEY_CODE_INSERT] = 0xd2,
163     [Q_KEY_CODE_DELETE] = 0xd3,
164 #ifdef NEED_CPU_H
165 #if defined(TARGET_SPARC) && !defined(TARGET_SPARC64)
166     [Q_KEY_CODE_STOP] = 0xf0,
167     [Q_KEY_CODE_AGAIN] = 0xf1,
168     [Q_KEY_CODE_PROPS] = 0xf2,
169     [Q_KEY_CODE_UNDO] = 0xf3,
170     [Q_KEY_CODE_FRONT] = 0xf4,
171     [Q_KEY_CODE_COPY] = 0xf5,
172     [Q_KEY_CODE_OPEN] = 0xf6,
173     [Q_KEY_CODE_PASTE] = 0xf7,
174     [Q_KEY_CODE_FIND] = 0xf8,
175     [Q_KEY_CODE_CUT] = 0xf9,
176     [Q_KEY_CODE_LF] = 0xfa,
177     [Q_KEY_CODE_HELP] = 0xfb,
178     [Q_KEY_CODE_META_L] = 0xfc,
179     [Q_KEY_CODE_META_R] = 0xfd,
180     [Q_KEY_CODE_COMPOSE] = 0xfe,
181 #endif
182 #endif
183     [Q_KEY_CODE_MAX] = 0,
184 };
185 
186 int index_from_key(const char *key)
187 {
188     int i;
189 
190     for (i = 0; QKeyCode_lookup[i] != NULL; i++) {
191         if (!strcmp(key, QKeyCode_lookup[i])) {
192             break;
193         }
194     }
195 
196     /* Return Q_KEY_CODE_MAX if the key is invalid */
197     return i;
198 }
199 
200 int index_from_keycode(int code)
201 {
202     int i;
203 
204     for (i = 0; i < Q_KEY_CODE_MAX; i++) {
205         if (key_defs[i] == code) {
206             break;
207         }
208     }
209 
210     /* Return Q_KEY_CODE_MAX if the code is invalid */
211     return i;
212 }
213 
214 static int *keycodes;
215 static int keycodes_size;
216 static QEMUTimer *key_timer;
217 
218 static int keycode_from_keyvalue(const KeyValue *value)
219 {
220     if (value->kind == KEY_VALUE_KIND_QCODE) {
221         return key_defs[value->qcode];
222     } else {
223         assert(value->kind == KEY_VALUE_KIND_NUMBER);
224         return value->number;
225     }
226 }
227 
228 static void free_keycodes(void)
229 {
230     g_free(keycodes);
231     keycodes = NULL;
232     keycodes_size = 0;
233 }
234 
235 static void release_keys(void *opaque)
236 {
237     while (keycodes_size > 0) {
238         if (keycodes[--keycodes_size] & 0x80) {
239             kbd_put_keycode(0xe0);
240         }
241         kbd_put_keycode(keycodes[keycodes_size] | 0x80);
242     }
243 
244     free_keycodes();
245 }
246 
247 void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
248                   Error **errp)
249 {
250     int keycode;
251     KeyValueList *p;
252 
253     if (!key_timer) {
254         key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL);
255     }
256 
257     if (keycodes != NULL) {
258         qemu_del_timer(key_timer);
259         release_keys(NULL);
260     }
261 
262     if (!has_hold_time) {
263         hold_time = 100;
264     }
265 
266     for (p = keys; p != NULL; p = p->next) {
267         /* key down events */
268         keycode = keycode_from_keyvalue(p->value);
269         if (keycode < 0x01 || keycode > 0xff) {
270             error_setg(errp, "invalid hex keycode 0x%x", keycode);
271             free_keycodes();
272             return;
273         }
274 
275         if (keycode & 0x80) {
276             kbd_put_keycode(0xe0);
277         }
278         kbd_put_keycode(keycode & 0x7f);
279 
280         keycodes = g_realloc(keycodes, sizeof(int) * (keycodes_size + 1));
281         keycodes[keycodes_size++] = keycode;
282     }
283 
284     /* delayed key up events */
285     qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) +
286                    muldiv64(get_ticks_per_sec(), hold_time, 1000));
287 }
288 
289 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
290 {
291     qemu_put_kbd_event_opaque = opaque;
292     qemu_put_kbd_event = func;
293 }
294 
295 void qemu_remove_kbd_event_handler(void)
296 {
297     qemu_put_kbd_event_opaque = NULL;
298     qemu_put_kbd_event = NULL;
299 }
300 
301 static void check_mode_change(void)
302 {
303     static int current_is_absolute, current_has_absolute;
304     int is_absolute;
305     int has_absolute;
306 
307     is_absolute = kbd_mouse_is_absolute();
308     has_absolute = kbd_mouse_has_absolute();
309 
310     if (is_absolute != current_is_absolute ||
311         has_absolute != current_has_absolute) {
312         notifier_list_notify(&mouse_mode_notifiers, NULL);
313     }
314 
315     current_is_absolute = is_absolute;
316     current_has_absolute = has_absolute;
317 }
318 
319 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
320                                                 void *opaque, int absolute,
321                                                 const char *name)
322 {
323     QEMUPutMouseEntry *s;
324     static int mouse_index = 0;
325 
326     s = g_malloc0(sizeof(QEMUPutMouseEntry));
327 
328     s->qemu_put_mouse_event = func;
329     s->qemu_put_mouse_event_opaque = opaque;
330     s->qemu_put_mouse_event_absolute = absolute;
331     s->qemu_put_mouse_event_name = g_strdup(name);
332     s->index = mouse_index++;
333 
334     QTAILQ_INSERT_TAIL(&mouse_handlers, s, node);
335 
336     check_mode_change();
337 
338     return s;
339 }
340 
341 void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
342 {
343     QTAILQ_REMOVE(&mouse_handlers, entry, node);
344     QTAILQ_INSERT_HEAD(&mouse_handlers, entry, node);
345 
346     check_mode_change();
347 }
348 
349 void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
350 {
351     QTAILQ_REMOVE(&mouse_handlers, entry, node);
352 
353     g_free(entry->qemu_put_mouse_event_name);
354     g_free(entry);
355 
356     check_mode_change();
357 }
358 
359 QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
360                                             void *opaque)
361 {
362     QEMUPutLEDEntry *s;
363 
364     s = g_malloc0(sizeof(QEMUPutLEDEntry));
365 
366     s->put_led = func;
367     s->opaque = opaque;
368     QTAILQ_INSERT_TAIL(&led_handlers, s, next);
369     return s;
370 }
371 
372 void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
373 {
374     if (entry == NULL)
375         return;
376     QTAILQ_REMOVE(&led_handlers, entry, next);
377     g_free(entry);
378 }
379 
380 void kbd_put_keycode(int keycode)
381 {
382     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
383         return;
384     }
385     if (qemu_put_kbd_event) {
386         qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
387     }
388 }
389 
390 void kbd_put_ledstate(int ledstate)
391 {
392     QEMUPutLEDEntry *cursor;
393 
394     QTAILQ_FOREACH(cursor, &led_handlers, next) {
395         cursor->put_led(cursor->opaque, ledstate);
396     }
397 }
398 
399 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
400 {
401     QEMUPutMouseEntry *entry;
402     QEMUPutMouseEvent *mouse_event;
403     void *mouse_event_opaque;
404     int width, height;
405 
406     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
407         return;
408     }
409     if (QTAILQ_EMPTY(&mouse_handlers)) {
410         return;
411     }
412 
413     entry = QTAILQ_FIRST(&mouse_handlers);
414 
415     mouse_event = entry->qemu_put_mouse_event;
416     mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
417 
418     if (mouse_event) {
419         if (entry->qemu_put_mouse_event_absolute) {
420             width = 0x7fff;
421             height = 0x7fff;
422         } else {
423             width = graphic_width - 1;
424             height = graphic_height - 1;
425         }
426 
427         switch (graphic_rotate) {
428         case 0:
429             mouse_event(mouse_event_opaque,
430                         dx, dy, dz, buttons_state);
431             break;
432         case 90:
433             mouse_event(mouse_event_opaque,
434                         width - dy, dx, dz, buttons_state);
435             break;
436         case 180:
437             mouse_event(mouse_event_opaque,
438                         width - dx, height - dy, dz, buttons_state);
439             break;
440         case 270:
441             mouse_event(mouse_event_opaque,
442                         dy, height - dx, dz, buttons_state);
443             break;
444         }
445     }
446 }
447 
448 int kbd_mouse_is_absolute(void)
449 {
450     if (QTAILQ_EMPTY(&mouse_handlers)) {
451         return 0;
452     }
453 
454     return QTAILQ_FIRST(&mouse_handlers)->qemu_put_mouse_event_absolute;
455 }
456 
457 int kbd_mouse_has_absolute(void)
458 {
459     QEMUPutMouseEntry *entry;
460 
461     QTAILQ_FOREACH(entry, &mouse_handlers, node) {
462         if (entry->qemu_put_mouse_event_absolute) {
463             return 1;
464         }
465     }
466 
467     return 0;
468 }
469 
470 MouseInfoList *qmp_query_mice(Error **errp)
471 {
472     MouseInfoList *mice_list = NULL;
473     QEMUPutMouseEntry *cursor;
474     bool current = true;
475 
476     QTAILQ_FOREACH(cursor, &mouse_handlers, node) {
477         MouseInfoList *info = g_malloc0(sizeof(*info));
478         info->value = g_malloc0(sizeof(*info->value));
479         info->value->name = g_strdup(cursor->qemu_put_mouse_event_name);
480         info->value->index = cursor->index;
481         info->value->absolute = !!cursor->qemu_put_mouse_event_absolute;
482         info->value->current = current;
483 
484         current = false;
485 
486         info->next = mice_list;
487         mice_list = info;
488     }
489 
490     return mice_list;
491 }
492 
493 void do_mouse_set(Monitor *mon, const QDict *qdict)
494 {
495     QEMUPutMouseEntry *cursor;
496     int index = qdict_get_int(qdict, "index");
497     int found = 0;
498 
499     if (QTAILQ_EMPTY(&mouse_handlers)) {
500         monitor_printf(mon, "No mouse devices connected\n");
501         return;
502     }
503 
504     QTAILQ_FOREACH(cursor, &mouse_handlers, node) {
505         if (cursor->index == index) {
506             found = 1;
507             qemu_activate_mouse_event_handler(cursor);
508             break;
509         }
510     }
511 
512     if (!found) {
513         monitor_printf(mon, "Mouse at given index not found\n");
514     }
515 
516     check_mode_change();
517 }
518 
519 void qemu_add_mouse_mode_change_notifier(Notifier *notify)
520 {
521     notifier_list_add(&mouse_mode_notifiers, notify);
522 }
523 
524 void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
525 {
526     notifier_remove(notify);
527 }
528