On 03/09/2011 02:24 AM, Lai Jiangshan wrote:
sendkey is a very good command for human using it in their monitor, but it is not a good idea to port it to qmp, because qmp is a machine protocol. So we introduce keydown and keyup command for qmp, they simulate the events that keyboard send to the system. Example, simulates ctrl+alt+f1: { "execute": "keydown", "arguments": { "keycode": 29 } } #press down ctrl { "execute": "keydown", "arguments": { "keycode": 56 } } #press down alt { "execute": "keydown", "arguments": { "keycode": 59 } } #press down f1 { "execute": "keyup", "arguments": { "keycode": 59 } } #release f1 { "execute": "keyup", "arguments": { "keycode": 56 } } #release alt { "execute": "keyup", "arguments": { "keycode": 29 } } #release ctrl Signed-off-by: Lai Jiangshan<laijs@xxxxxxxxxxxxxx>
--- diff --git a/monitor.c b/monitor.c index 22ae3bb..725df83 100644 --- a/monitor.c +++ b/monitor.c @@ -1810,16 +1810,25 @@ static uint8_t keycodes[MAX_KEYCODES]; static int nb_pending_keycodes; static QEMUTimer *key_timer; -static void release_keys(void *opaque) +static void keydown(uint8_t keycode) { - int keycode; + if (keycode& 0x80) + kbd_put_keycode(0xe0); + kbd_put_keycode(keycode& 0x7f); +} +static void keyup(uint8_t keycode) +{ + if (keycode& 0x80) + kbd_put_keycode(0xe0); + kbd_put_keycode(keycode | 0x80); +} + +static void release_keys(void *opaque) +{ while (nb_pending_keycodes> 0) { nb_pending_keycodes--; - keycode = keycodes[nb_pending_keycodes]; - if (keycode& 0x80) - kbd_put_keycode(0xe0); - kbd_put_keycode(keycode | 0x80); + keyup(keycodes[nb_pending_keycodes]); } } @@ -1866,17 +1875,41 @@ static void do_sendkey(Monitor *mon, const QDict *qdict) } nb_pending_keycodes = i; /* key down events */ - for (i = 0; i< nb_pending_keycodes; i++) { - keycode = keycodes[i]; - if (keycode& 0x80) - kbd_put_keycode(0xe0); - kbd_put_keycode(keycode& 0x7f); - } + for (i = 0; i< nb_pending_keycodes; i++) + keydown(keycodes[i]); /* delayed key up events */ qemu_mod_timer(key_timer, qemu_get_clock(vm_clock) + muldiv64(get_ticks_per_sec(), hold_time, 1000)); } +static int qmp_keyaction(const QDict *qdict, int down) +{ + int keycode = qdict_get_int(qdict, "keycode"); + + if (keycode< 0 || keycode>= 256) { + qerror_report(QERR_INVALID_PARAMETER_VALUE, "keycode", + "a valid keycode"); + return -1; + } + + if (down) + keydown(keycode); + else + keyup(keycode); + + return 0; +} + +static int qmp_keydown(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + return qmp_keyaction(qdict, 1); +} + +static int qmp_keyup(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + return qmp_keyaction(qdict, 0); +} + static int mouse_button_state; static void do_mouse_move(Monitor *mon, const QDict *qdict) diff --git a/qmp-commands.hx b/qmp-commands.hx index df40a3d..4c449bb 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -338,6 +338,58 @@ Example: EQMP { + .name = "keydown", + .args_type = "keycode:i", + .params = "keycode", + .help = "press down a key", + .user_print = monitor_user_noop, + .mhandler.cmd_new = qmp_keydown, + }, + +SQMP +keydown +--- + +Press down a key. + +Arguments: + +- "keycode": the code of the key to press down (json-int) + +Example: + +-> { "execute": "keydown", "arguments": { "keycode": 16 } } +<- { "return": {} } + +EQMP + + { + .name = "keyup", + .args_type = "keycode:i", + .params = "keycode", + .help = "release a key", + .user_print = monitor_user_noop, + .mhandler.cmd_new = qmp_keyup, + }, + +SQMP +keyup +--- + +Release a key. + +Arguments: + +- "keycode": the code of the key to release (json-int)
What is the value of "keycode" and what happens if you pass an invalid keycode?
This interface uses QEMU-style compressed XT scan codes. I'd suggest making the interface take two optional arguments one being the an integer keycode and then another being a symbolic name where the symbolic name used the current keymap to translate the keycode.
For the XT scan code, I wouldn't use the one-byte encoding. I'd use a 32-bit encoding.
Regards, Anthony Liguori
+Example: + +-> { "execute": "keyup", "arguments": { "keycode": 16 } } +<- { "return": {} } + +EQMP + + { .name = "cpu", .args_type = "index:i", .params = "index",
-- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html