Commit c8256f9d23bba4fac3b0b6a9e6e3dc12362cbe0b

Authored by balrog
1 parent 7dd9e556

Enhance sendkey with key hold time (Jan Kiszka).

Current key injection via the monitor basically generates no key hold
time. This is fine for keyboard emulations that have their own queues,
but it causes troubles for those how don't (like the MusicPal - it
simply does not work with injected keys). Moreover, I would like to use
this mechanism to simulate pressed buttons during power-up.

Therefore, this patch enhances the key injection with a configurable
release delay (by default 100 virtual milliseconds).

This feature allows to get rid of the initial sleep() in musicpal_init
because one can now simply start qemu with -S and issue "sendkey m 1000"
and "continue" in the monitor to achieve the desired effect of a pressed
menu button during power-up. So there is no need for a per-musicpal or
even qemu-wide "-hold-button" switch.

Signed-off-by: Jan Kiszka <jan.kiszka@web.de>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4701 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 39 additions and 25 deletions
hw/musicpal.c
... ... @@ -1504,12 +1504,6 @@ static void musicpal_init(ram_addr_t ram_size, int vga_ram_size,
1504 1504  
1505 1505 qemu_add_kbd_event_handler(musicpal_key_event, pic[MP_GPIO_IRQ]);
1506 1506  
1507   - /*
1508   - * Wait a bit to catch menu button during U-Boot start-up
1509   - * (to trigger emergency update).
1510   - */
1511   - sleep(1);
1512   -
1513 1507 mv88w8618_eth_init(&nd_table[0], MP_ETH_BASE, pic[MP_ETH_IRQ]);
1514 1508  
1515 1509 mixer_i2c = musicpal_audio_init(MP_AUDIO_BASE, pic[MP_AUDIO_IRQ]);
... ...
monitor.c
... ... @@ -35,10 +35,7 @@
35 35 #include "audio/audio.h"
36 36 #include "disas.h"
37 37 #include <dirent.h>
38   -
39   -#ifdef CONFIG_PROFILER
40   -#include "qemu-timer.h" /* for ticks_per_sec */
41   -#endif
  38 +#include "qemu-timer.h"
42 39  
43 40 //#define DEBUG
44 41 //#define DEBUG_COMPLETION
... ... @@ -920,14 +917,37 @@ static int get_keycode(const char *key)
920 917 return -1;
921 918 }
922 919  
923   -static void do_sendkey(const char *string)
  920 +#define MAX_KEYCODES 16
  921 +static uint8_t keycodes[MAX_KEYCODES];
  922 +static int nb_pending_keycodes;
  923 +static QEMUTimer *key_timer;
  924 +
  925 +static void release_keys(void *opaque)
  926 +{
  927 + int keycode;
  928 +
  929 + while (nb_pending_keycodes > 0) {
  930 + nb_pending_keycodes--;
  931 + keycode = keycodes[nb_pending_keycodes];
  932 + if (keycode & 0x80)
  933 + kbd_put_keycode(0xe0);
  934 + kbd_put_keycode(keycode | 0x80);
  935 + }
  936 +}
  937 +
  938 +static void do_sendkey(const char *string, int has_hold_time, int hold_time)
924 939 {
925   - uint8_t keycodes[16];
926   - int nb_keycodes = 0;
927 940 char keyname_buf[16];
928 941 char *separator;
929 942 int keyname_len, keycode, i;
930 943  
  944 + if (nb_pending_keycodes > 0) {
  945 + qemu_del_timer(key_timer);
  946 + release_keys(NULL);
  947 + }
  948 + if (!has_hold_time)
  949 + hold_time = 100;
  950 + i = 0;
931 951 while (1) {
932 952 separator = strchr(string, '-');
933 953 keyname_len = separator ? separator - string : strlen(string);
... ... @@ -937,7 +957,7 @@ static void do_sendkey(const char *string)
937 957 term_printf("invalid key: '%s...'\n", keyname_buf);
938 958 return;
939 959 }
940   - if (nb_keycodes == sizeof(keycodes)) {
  960 + if (i == MAX_KEYCODES) {
941 961 term_printf("too many keys\n");
942 962 return;
943 963 }
... ... @@ -947,26 +967,23 @@ static void do_sendkey(const char *string)
947 967 term_printf("unknown key: '%s'\n", keyname_buf);
948 968 return;
949 969 }
950   - keycodes[nb_keycodes++] = keycode;
  970 + keycodes[i++] = keycode;
951 971 }
952 972 if (!separator)
953 973 break;
954 974 string = separator + 1;
955 975 }
  976 + nb_pending_keycodes = i;
956 977 /* key down events */
957   - for(i = 0; i < nb_keycodes; i++) {
  978 + for (i = 0; i < nb_pending_keycodes; i++) {
958 979 keycode = keycodes[i];
959 980 if (keycode & 0x80)
960 981 kbd_put_keycode(0xe0);
961 982 kbd_put_keycode(keycode & 0x7f);
962 983 }
963   - /* key up events */
964   - for(i = nb_keycodes - 1; i >= 0; i--) {
965   - keycode = keycodes[i];
966   - if (keycode & 0x80)
967   - kbd_put_keycode(0xe0);
968   - kbd_put_keycode(keycode | 0x80);
969   - }
  984 + /* delayed key up events */
  985 + qemu_mod_timer(key_timer,
  986 + qemu_get_clock(vm_clock) + ticks_per_sec * hold_time);
970 987 }
971 988  
972 989 static int mouse_button_state;
... ... @@ -1353,8 +1370,8 @@ static term_cmd_t term_cmds[] = {
1353 1370 { "i", "/ii.", do_ioport_read,
1354 1371 "/fmt addr", "I/O port read" },
1355 1372  
1356   - { "sendkey", "s", do_sendkey,
1357   - "keys", "send keys to the VM (e.g. 'sendkey ctrl-alt-f1')" },
  1373 + { "sendkey", "si?", do_sendkey,
  1374 + "keys [hold_ms]", "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)" },
1358 1375 { "system_reset", "", do_system_reset,
1359 1376 "", "reset the system" },
1360 1377 { "system_powerdown", "", do_system_powerdown,
... ... @@ -2638,6 +2655,9 @@ void monitor_init(CharDriverState *hd, int show_banner)
2638 2655 int i;
2639 2656  
2640 2657 if (is_first_init) {
  2658 + key_timer = qemu_new_timer(vm_clock, release_keys, NULL);
  2659 + if (!key_timer)
  2660 + return;
2641 2661 for (i = 0; i < MAX_MON; i++) {
2642 2662 monitor_hd[i] = NULL;
2643 2663 }
... ...