mirror of https://gitee.com/openkylin/qemu.git
Input code update:
- add keycode mapping helpers to core. - start switching devices to new input api. - misc bugfixes. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJTdbOhAAoJEEy22O7T6HE4cbsP/RanYDHsykxfgrDpz5FRPtBl qRLJbHYNHicD9jzRyp4LoEpgT78An4OHMsnSWDxyglnJAY3wO8UxzjmSc6Si3bNb Yiy137u2lwhm7THX0wsR+PclLqzHxFatfSLttYomuTGBJmxAW9M3ivd2LNKd1S9/ 3sDXlZSE+nl4btyXLtHAgVPbD/l4Vpi0F3/0cV3v8DDeH4p0Wpgboxf9Kby3KXIa rvsLZyJ9Ast4bDP4JLHYLnU9SN4V26TY5maSg5ka8D5Ha1T8YNW8qHq7BKA2vbAY Ic2X9piHq2VAH9XB4wIpY7Vc4B8ZDJJflWplAZrt1D5FgHqyskGXPuHfELvPt1gW sNkMIB848oxplX+p6g8kE+ZvGGIn9IEUScu7gxfEHRNqkaGVLPd2fZaacTd/6yxZ mTMZ1t69TXrXv35NP5AJRfLg3mJEcY3+nfvKZCN1OZwjh8n91kKvND4eN0Smmg9R ntqQfNuFMucHpMFoaiCabzARmCl63iKZ1cis14pEKdfsWaAK3rAbZmf9E181ewSE Z4ns8Yhw2S7WGb+EhDuKODiDTqUG2doiEMsVDcofOpE9vI25Hb/QQ+5AaiHGrKa1 Hh5rl3NJn0//AnVsgS5qu65X7/1KkZD93i4aCY09h46BEb0kzqKLr+Si6l92a3hn PrWY+YL8jiVEgNr94lOj =DqKI -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/pull-input-8' into staging Input code update: - add keycode mapping helpers to core. - start switching devices to new input api. - misc bugfixes. # gpg: Signature made Fri 16 May 2014 07:43:45 BST using RSA key ID D3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" * remotes/kraxel/tags/pull-input-8: input: sparc32 kbd: claim en-us layout input: sparc32 kbd: fix some key mappings input: remove sparc keymap hack input: switch sparc32 kbd to new input api input: switch ps/2 mouse to new input api input: switch ps/2 kbd to new input api input: use KeyValue directly in sendkey monitor command input: add qemu_input_handler_deactivate input: key mapping helpers ps2: set ps/2 output buffer size as the same as kernel Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5bc8f026dd
231
hw/char/escc.c
231
hw/char/escc.c
|
@ -27,6 +27,7 @@
|
|||
#include "hw/char/escc.h"
|
||||
#include "sysemu/char.h"
|
||||
#include "ui/console.h"
|
||||
#include "ui/input.h"
|
||||
#include "trace.h"
|
||||
|
||||
/*
|
||||
|
@ -94,6 +95,7 @@ typedef struct ChannelState {
|
|||
ChnID chn; // this channel, A (base+4) or B (base+0)
|
||||
ChnType type;
|
||||
uint8_t rx, tx;
|
||||
QemuInputHandlerState *hs;
|
||||
} ChannelState;
|
||||
|
||||
#define ESCC(obj) OBJECT_CHECK(ESCCState, (obj), TYPE_ESCC)
|
||||
|
@ -714,71 +716,181 @@ MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB,
|
|||
return &d->mmio;
|
||||
}
|
||||
|
||||
static const uint8_t keycodes[128] = {
|
||||
127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
|
||||
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
|
||||
79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
|
||||
104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
|
||||
14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
|
||||
113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
|
||||
90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
|
||||
0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
|
||||
static const uint8_t qcode_to_keycode[Q_KEY_CODE_MAX] = {
|
||||
[Q_KEY_CODE_SHIFT] = 99,
|
||||
[Q_KEY_CODE_SHIFT_R] = 110,
|
||||
[Q_KEY_CODE_ALT] = 19,
|
||||
[Q_KEY_CODE_ALT_R] = 13,
|
||||
[Q_KEY_CODE_ALTGR] = 13,
|
||||
[Q_KEY_CODE_CTRL] = 76,
|
||||
[Q_KEY_CODE_CTRL_R] = 76,
|
||||
[Q_KEY_CODE_ESC] = 29,
|
||||
[Q_KEY_CODE_1] = 30,
|
||||
[Q_KEY_CODE_2] = 31,
|
||||
[Q_KEY_CODE_3] = 32,
|
||||
[Q_KEY_CODE_4] = 33,
|
||||
[Q_KEY_CODE_5] = 34,
|
||||
[Q_KEY_CODE_6] = 35,
|
||||
[Q_KEY_CODE_7] = 36,
|
||||
[Q_KEY_CODE_8] = 37,
|
||||
[Q_KEY_CODE_9] = 38,
|
||||
[Q_KEY_CODE_0] = 39,
|
||||
[Q_KEY_CODE_MINUS] = 40,
|
||||
[Q_KEY_CODE_EQUAL] = 41,
|
||||
[Q_KEY_CODE_BACKSPACE] = 43,
|
||||
[Q_KEY_CODE_TAB] = 53,
|
||||
[Q_KEY_CODE_Q] = 54,
|
||||
[Q_KEY_CODE_W] = 55,
|
||||
[Q_KEY_CODE_E] = 56,
|
||||
[Q_KEY_CODE_R] = 57,
|
||||
[Q_KEY_CODE_T] = 58,
|
||||
[Q_KEY_CODE_Y] = 59,
|
||||
[Q_KEY_CODE_U] = 60,
|
||||
[Q_KEY_CODE_I] = 61,
|
||||
[Q_KEY_CODE_O] = 62,
|
||||
[Q_KEY_CODE_P] = 63,
|
||||
[Q_KEY_CODE_BRACKET_LEFT] = 64,
|
||||
[Q_KEY_CODE_BRACKET_RIGHT] = 65,
|
||||
[Q_KEY_CODE_RET] = 89,
|
||||
[Q_KEY_CODE_A] = 77,
|
||||
[Q_KEY_CODE_S] = 78,
|
||||
[Q_KEY_CODE_D] = 79,
|
||||
[Q_KEY_CODE_F] = 80,
|
||||
[Q_KEY_CODE_G] = 81,
|
||||
[Q_KEY_CODE_H] = 82,
|
||||
[Q_KEY_CODE_J] = 83,
|
||||
[Q_KEY_CODE_K] = 84,
|
||||
[Q_KEY_CODE_L] = 85,
|
||||
[Q_KEY_CODE_SEMICOLON] = 86,
|
||||
[Q_KEY_CODE_APOSTROPHE] = 87,
|
||||
[Q_KEY_CODE_GRAVE_ACCENT] = 42,
|
||||
[Q_KEY_CODE_BACKSLASH] = 88,
|
||||
[Q_KEY_CODE_Z] = 100,
|
||||
[Q_KEY_CODE_X] = 101,
|
||||
[Q_KEY_CODE_C] = 102,
|
||||
[Q_KEY_CODE_V] = 103,
|
||||
[Q_KEY_CODE_B] = 104,
|
||||
[Q_KEY_CODE_N] = 105,
|
||||
[Q_KEY_CODE_M] = 106,
|
||||
[Q_KEY_CODE_COMMA] = 107,
|
||||
[Q_KEY_CODE_DOT] = 108,
|
||||
[Q_KEY_CODE_SLASH] = 109,
|
||||
[Q_KEY_CODE_ASTERISK] = 47,
|
||||
[Q_KEY_CODE_SPC] = 121,
|
||||
[Q_KEY_CODE_CAPS_LOCK] = 119,
|
||||
[Q_KEY_CODE_F1] = 5,
|
||||
[Q_KEY_CODE_F2] = 6,
|
||||
[Q_KEY_CODE_F3] = 8,
|
||||
[Q_KEY_CODE_F4] = 10,
|
||||
[Q_KEY_CODE_F5] = 12,
|
||||
[Q_KEY_CODE_F6] = 14,
|
||||
[Q_KEY_CODE_F7] = 16,
|
||||
[Q_KEY_CODE_F8] = 17,
|
||||
[Q_KEY_CODE_F9] = 18,
|
||||
[Q_KEY_CODE_F10] = 7,
|
||||
[Q_KEY_CODE_NUM_LOCK] = 98,
|
||||
[Q_KEY_CODE_SCROLL_LOCK] = 23,
|
||||
[Q_KEY_CODE_KP_DIVIDE] = 46,
|
||||
[Q_KEY_CODE_KP_MULTIPLY] = 47,
|
||||
[Q_KEY_CODE_KP_SUBTRACT] = 71,
|
||||
[Q_KEY_CODE_KP_ADD] = 125,
|
||||
[Q_KEY_CODE_KP_ENTER] = 90,
|
||||
[Q_KEY_CODE_KP_DECIMAL] = 50,
|
||||
[Q_KEY_CODE_KP_0] = 94,
|
||||
[Q_KEY_CODE_KP_1] = 112,
|
||||
[Q_KEY_CODE_KP_2] = 113,
|
||||
[Q_KEY_CODE_KP_3] = 114,
|
||||
[Q_KEY_CODE_KP_4] = 91,
|
||||
[Q_KEY_CODE_KP_5] = 92,
|
||||
[Q_KEY_CODE_KP_6] = 93,
|
||||
[Q_KEY_CODE_KP_7] = 68,
|
||||
[Q_KEY_CODE_KP_8] = 69,
|
||||
[Q_KEY_CODE_KP_9] = 70,
|
||||
[Q_KEY_CODE_LESS] = 124,
|
||||
[Q_KEY_CODE_F11] = 9,
|
||||
[Q_KEY_CODE_F12] = 11,
|
||||
[Q_KEY_CODE_HOME] = 52,
|
||||
[Q_KEY_CODE_PGUP] = 96,
|
||||
[Q_KEY_CODE_PGDN] = 123,
|
||||
[Q_KEY_CODE_END] = 74,
|
||||
[Q_KEY_CODE_LEFT] = 24,
|
||||
[Q_KEY_CODE_UP] = 20,
|
||||
[Q_KEY_CODE_DOWN] = 27,
|
||||
[Q_KEY_CODE_RIGHT] = 28,
|
||||
[Q_KEY_CODE_INSERT] = 44,
|
||||
[Q_KEY_CODE_DELETE] = 66,
|
||||
[Q_KEY_CODE_STOP] = 1,
|
||||
[Q_KEY_CODE_AGAIN] = 3,
|
||||
[Q_KEY_CODE_PROPS] = 25,
|
||||
[Q_KEY_CODE_UNDO] = 26,
|
||||
[Q_KEY_CODE_FRONT] = 49,
|
||||
[Q_KEY_CODE_COPY] = 51,
|
||||
[Q_KEY_CODE_OPEN] = 72,
|
||||
[Q_KEY_CODE_PASTE] = 73,
|
||||
[Q_KEY_CODE_FIND] = 95,
|
||||
[Q_KEY_CODE_CUT] = 97,
|
||||
[Q_KEY_CODE_LF] = 111,
|
||||
[Q_KEY_CODE_HELP] = 118,
|
||||
[Q_KEY_CODE_META_L] = 120,
|
||||
[Q_KEY_CODE_META_R] = 122,
|
||||
[Q_KEY_CODE_COMPOSE] = 67,
|
||||
[Q_KEY_CODE_PRINT] = 22,
|
||||
[Q_KEY_CODE_SYSRQ] = 21,
|
||||
};
|
||||
|
||||
static const uint8_t e0_keycodes[128] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112,
|
||||
113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 3, 25, 26, 49, 52, 72, 73, 97, 99, 111, 118, 120, 122, 67, 0,
|
||||
};
|
||||
|
||||
static void sunkbd_event(void *opaque, int ch)
|
||||
static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
InputEvent *evt)
|
||||
{
|
||||
ChannelState *s = opaque;
|
||||
int release = ch & 0x80;
|
||||
ChannelState *s = (ChannelState *)dev;
|
||||
int qcode, keycode;
|
||||
|
||||
trace_escc_sunkbd_event_in(ch);
|
||||
switch (ch) {
|
||||
case 58: // Caps lock press
|
||||
s->caps_lock_mode ^= 1;
|
||||
if (s->caps_lock_mode == 2)
|
||||
return; // Drop second press
|
||||
break;
|
||||
case 69: // Num lock press
|
||||
s->num_lock_mode ^= 1;
|
||||
if (s->num_lock_mode == 2)
|
||||
return; // Drop second press
|
||||
break;
|
||||
case 186: // Caps lock release
|
||||
s->caps_lock_mode ^= 2;
|
||||
if (s->caps_lock_mode == 3)
|
||||
return; // Drop first release
|
||||
break;
|
||||
case 197: // Num lock release
|
||||
s->num_lock_mode ^= 2;
|
||||
if (s->num_lock_mode == 3)
|
||||
return; // Drop first release
|
||||
break;
|
||||
case 0xe0:
|
||||
s->e0_mode = 1;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
assert(evt->kind == INPUT_EVENT_KIND_KEY);
|
||||
qcode = qemu_input_key_value_to_qcode(evt->key->key);
|
||||
trace_escc_sunkbd_event_in(qcode, QKeyCode_lookup[qcode],
|
||||
evt->key->down);
|
||||
|
||||
if (qcode == Q_KEY_CODE_CAPS_LOCK) {
|
||||
if (evt->key->down) {
|
||||
s->caps_lock_mode ^= 1;
|
||||
if (s->caps_lock_mode == 2) {
|
||||
return; /* Drop second press */
|
||||
}
|
||||
} else {
|
||||
s->caps_lock_mode ^= 2;
|
||||
if (s->caps_lock_mode == 3) {
|
||||
return; /* Drop first release */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s->e0_mode) {
|
||||
s->e0_mode = 0;
|
||||
ch = e0_keycodes[ch & 0x7f];
|
||||
} else {
|
||||
ch = keycodes[ch & 0x7f];
|
||||
|
||||
if (qcode == Q_KEY_CODE_NUM_LOCK) {
|
||||
if (evt->key->down) {
|
||||
s->num_lock_mode ^= 1;
|
||||
if (s->num_lock_mode == 2) {
|
||||
return; /* Drop second press */
|
||||
}
|
||||
} else {
|
||||
s->num_lock_mode ^= 2;
|
||||
if (s->num_lock_mode == 3) {
|
||||
return; /* Drop first release */
|
||||
}
|
||||
}
|
||||
}
|
||||
trace_escc_sunkbd_event_out(ch);
|
||||
put_queue(s, ch | release);
|
||||
|
||||
keycode = qcode_to_keycode[qcode];
|
||||
if (!evt->key->down) {
|
||||
keycode |= 0x80;
|
||||
}
|
||||
trace_escc_sunkbd_event_out(keycode);
|
||||
put_queue(s, keycode);
|
||||
}
|
||||
|
||||
static QemuInputHandler sunkbd_handler = {
|
||||
.name = "sun keyboard",
|
||||
.mask = INPUT_EVENT_MASK_KEY,
|
||||
.event = sunkbd_handle_event,
|
||||
};
|
||||
|
||||
static void handle_kbd_command(ChannelState *s, int val)
|
||||
{
|
||||
trace_escc_kbd_command(val);
|
||||
|
@ -800,7 +912,7 @@ static void handle_kbd_command(ChannelState *s, int val)
|
|||
case 0xf:
|
||||
clear_queue(s);
|
||||
put_queue(s, 0xfe);
|
||||
put_queue(s, 0); // XXX, layout?
|
||||
put_queue(s, 0x21); /* en-us layout */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -898,7 +1010,8 @@ static int escc_init1(SysBusDevice *dev)
|
|||
"QEMU Sun Mouse");
|
||||
}
|
||||
if (s->chn[1].type == kbd) {
|
||||
qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
|
||||
s->chn[1].hs = qemu_input_handler_register((DeviceState *)(&s->chn[1]),
|
||||
&sunkbd_handler);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
166
hw/input/ps2.c
166
hw/input/ps2.c
|
@ -24,6 +24,7 @@
|
|||
#include "hw/hw.h"
|
||||
#include "hw/input/ps2.h"
|
||||
#include "ui/console.h"
|
||||
#include "ui/input.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
/* debug PC keyboard */
|
||||
|
@ -71,10 +72,12 @@
|
|||
#define MOUSE_STATUS_ENABLED 0x20
|
||||
#define MOUSE_STATUS_SCALE21 0x10
|
||||
|
||||
#define PS2_QUEUE_SIZE 256
|
||||
#define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */
|
||||
|
||||
typedef struct {
|
||||
uint8_t data[PS2_QUEUE_SIZE];
|
||||
/* Keep the data array 256 bytes long, which compatibility
|
||||
with older qemu versions. */
|
||||
uint8_t data[256];
|
||||
int rptr, wptr, count;
|
||||
} PS2Queue;
|
||||
|
||||
|
@ -137,7 +140,7 @@ void ps2_queue(void *opaque, int b)
|
|||
PS2State *s = (PS2State *)opaque;
|
||||
PS2Queue *q = &s->queue;
|
||||
|
||||
if (q->count >= PS2_QUEUE_SIZE)
|
||||
if (q->count >= PS2_QUEUE_SIZE - 1)
|
||||
return;
|
||||
q->data[q->wptr] = b;
|
||||
if (++q->wptr == PS2_QUEUE_SIZE)
|
||||
|
@ -170,6 +173,21 @@ static void ps2_put_keycode(void *opaque, int keycode)
|
|||
ps2_queue(&s->common, keycode);
|
||||
}
|
||||
|
||||
static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
|
||||
InputEvent *evt)
|
||||
{
|
||||
PS2KbdState *s = (PS2KbdState *)dev;
|
||||
int scancodes[3], i, count;
|
||||
|
||||
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
|
||||
count = qemu_input_key_value_to_scancode(evt->key->key,
|
||||
evt->key->down,
|
||||
scancodes);
|
||||
for (i = 0; i < count; i++) {
|
||||
ps2_put_keycode(s, scancodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ps2_read_data(void *opaque)
|
||||
{
|
||||
PS2State *s = (PS2State *)opaque;
|
||||
|
@ -352,31 +370,57 @@ static void ps2_mouse_send_packet(PS2MouseState *s)
|
|||
s->mouse_dz -= dz1;
|
||||
}
|
||||
|
||||
static void ps2_mouse_event(void *opaque,
|
||||
int dx, int dy, int dz, int buttons_state)
|
||||
static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
|
||||
InputEvent *evt)
|
||||
{
|
||||
PS2MouseState *s = opaque;
|
||||
static const int bmap[INPUT_BUTTON_MAX] = {
|
||||
[INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
|
||||
[INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
|
||||
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
|
||||
};
|
||||
PS2MouseState *s = (PS2MouseState *)dev;
|
||||
|
||||
/* check if deltas are recorded when disabled */
|
||||
if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
|
||||
return;
|
||||
|
||||
s->mouse_dx += dx;
|
||||
s->mouse_dy -= dy;
|
||||
s->mouse_dz += dz;
|
||||
/* XXX: SDL sometimes generates nul events: we delete them */
|
||||
if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
|
||||
s->mouse_buttons == buttons_state)
|
||||
return;
|
||||
s->mouse_buttons = buttons_state;
|
||||
switch (evt->kind) {
|
||||
case INPUT_EVENT_KIND_REL:
|
||||
if (evt->rel->axis == INPUT_AXIS_X) {
|
||||
s->mouse_dx += evt->rel->value;
|
||||
} else if (evt->rel->axis == INPUT_AXIS_Y) {
|
||||
s->mouse_dy -= evt->rel->value;
|
||||
}
|
||||
break;
|
||||
|
||||
if (buttons_state) {
|
||||
case INPUT_EVENT_KIND_BTN:
|
||||
if (evt->btn->down) {
|
||||
s->mouse_buttons |= bmap[evt->btn->button];
|
||||
if (evt->btn->button == INPUT_BUTTON_WHEEL_UP) {
|
||||
s->mouse_dz--;
|
||||
} else if (evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||
s->mouse_dz++;
|
||||
}
|
||||
} else {
|
||||
s->mouse_buttons &= ~bmap[evt->btn->button];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ps2_mouse_sync(DeviceState *dev)
|
||||
{
|
||||
PS2MouseState *s = (PS2MouseState *)dev;
|
||||
|
||||
if (s->mouse_buttons) {
|
||||
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
|
||||
}
|
||||
|
||||
if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
|
||||
(s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
|
||||
for(;;) {
|
||||
if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
|
||||
while (s->common.queue.count < PS2_QUEUE_SIZE - 4) {
|
||||
/* if not remote, send event. Multiple events are sent if
|
||||
too big deltas */
|
||||
ps2_mouse_send_packet(s);
|
||||
|
@ -388,7 +432,9 @@ static void ps2_mouse_event(void *opaque,
|
|||
|
||||
void ps2_mouse_fake_event(void *opaque)
|
||||
{
|
||||
ps2_mouse_event(opaque, 1, 0, 0, 0);
|
||||
PS2MouseState *s = opaque;
|
||||
s->mouse_dx++;
|
||||
ps2_mouse_sync(opaque);
|
||||
}
|
||||
|
||||
void ps2_write_mouse(void *opaque, int val)
|
||||
|
@ -528,6 +574,34 @@ static void ps2_common_reset(PS2State *s)
|
|||
s->update_irq(s->update_arg, 0);
|
||||
}
|
||||
|
||||
static void ps2_common_post_load(PS2State *s)
|
||||
{
|
||||
PS2Queue *q = &s->queue;
|
||||
int size;
|
||||
int i;
|
||||
int tmp_data[PS2_QUEUE_SIZE];
|
||||
|
||||
/* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
|
||||
size = q->count > PS2_QUEUE_SIZE ? 0 : q->count;
|
||||
|
||||
/* move the queue elements to the start of data array */
|
||||
if (size > 0) {
|
||||
for (i = 0; i < size; i++) {
|
||||
/* move the queue elements to the temporary buffer */
|
||||
tmp_data[i] = q->data[q->rptr];
|
||||
if (++q->rptr == 256) {
|
||||
q->rptr = 0;
|
||||
}
|
||||
}
|
||||
memcpy(q->data, tmp_data, size);
|
||||
}
|
||||
/* reset rptr/wptr/count */
|
||||
q->rptr = 0;
|
||||
q->wptr = size;
|
||||
q->count = size;
|
||||
s->update_irq(s->update_arg, q->count != 0);
|
||||
}
|
||||
|
||||
static void ps2_kbd_reset(void *opaque)
|
||||
{
|
||||
PS2KbdState *s = (PS2KbdState *) opaque;
|
||||
|
@ -600,18 +674,31 @@ static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
|
|||
static int ps2_kbd_post_load(void* opaque, int version_id)
|
||||
{
|
||||
PS2KbdState *s = (PS2KbdState*)opaque;
|
||||
PS2State *ps2 = &s->common;
|
||||
|
||||
if (version_id == 2)
|
||||
s->scancode_set=2;
|
||||
|
||||
ps2_common_post_load(ps2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ps2_kbd_pre_save(void *opaque)
|
||||
{
|
||||
PS2KbdState *s = (PS2KbdState *)opaque;
|
||||
PS2State *ps2 = &s->common;
|
||||
|
||||
ps2_common_post_load(ps2);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_ps2_keyboard = {
|
||||
.name = "ps2kbd",
|
||||
.version_id = 3,
|
||||
.minimum_version_id = 2,
|
||||
.minimum_version_id_old = 2,
|
||||
.post_load = ps2_kbd_post_load,
|
||||
.pre_save = ps2_kbd_pre_save,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
|
||||
VMSTATE_INT32(scan_enabled, PS2KbdState),
|
||||
|
@ -629,11 +716,31 @@ static const VMStateDescription vmstate_ps2_keyboard = {
|
|||
}
|
||||
};
|
||||
|
||||
static int ps2_mouse_post_load(void *opaque, int version_id)
|
||||
{
|
||||
PS2MouseState *s = (PS2MouseState *)opaque;
|
||||
PS2State *ps2 = &s->common;
|
||||
|
||||
ps2_common_post_load(ps2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ps2_mouse_pre_save(void *opaque)
|
||||
{
|
||||
PS2MouseState *s = (PS2MouseState *)opaque;
|
||||
PS2State *ps2 = &s->common;
|
||||
|
||||
ps2_common_post_load(ps2);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_ps2_mouse = {
|
||||
.name = "ps2mouse",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.minimum_version_id_old = 2,
|
||||
.post_load = ps2_mouse_post_load,
|
||||
.pre_save = ps2_mouse_pre_save,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
|
||||
VMSTATE_UINT8(mouse_status, PS2MouseState),
|
||||
|
@ -650,6 +757,12 @@ static const VMStateDescription vmstate_ps2_mouse = {
|
|||
}
|
||||
};
|
||||
|
||||
static QemuInputHandler ps2_keyboard_handler = {
|
||||
.name = "QEMU PS/2 Keyboard",
|
||||
.mask = INPUT_EVENT_MASK_KEY,
|
||||
.event = ps2_keyboard_event,
|
||||
};
|
||||
|
||||
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
|
||||
{
|
||||
PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
|
||||
|
@ -658,11 +771,19 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
|
|||
s->common.update_arg = update_arg;
|
||||
s->scancode_set = 2;
|
||||
vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
|
||||
qemu_add_kbd_event_handler(ps2_put_keycode, s);
|
||||
qemu_input_handler_register((DeviceState *)s,
|
||||
&ps2_keyboard_handler);
|
||||
qemu_register_reset(ps2_kbd_reset, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
static QemuInputHandler ps2_mouse_handler = {
|
||||
.name = "QEMU PS/2 Mouse",
|
||||
.mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
|
||||
.event = ps2_mouse_event,
|
||||
.sync = ps2_mouse_sync,
|
||||
};
|
||||
|
||||
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
|
||||
{
|
||||
PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
|
||||
|
@ -670,7 +791,8 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
|
|||
s->common.update_irq = update_irq;
|
||||
s->common.update_arg = update_arg;
|
||||
vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
|
||||
qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
|
||||
qemu_input_handler_register((DeviceState *)s,
|
||||
&ps2_mouse_handler);
|
||||
qemu_register_reset(ps2_mouse_reset, s);
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ struct QemuInputHandler {
|
|||
QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
|
||||
QemuInputHandler *handler);
|
||||
void qemu_input_handler_activate(QemuInputHandlerState *s);
|
||||
void qemu_input_handler_deactivate(QemuInputHandlerState *s);
|
||||
void qemu_input_handler_unregister(QemuInputHandlerState *s);
|
||||
void qemu_input_event_send(QemuConsole *src, InputEvent *evt);
|
||||
void qemu_input_event_sync(void);
|
||||
|
@ -35,6 +36,10 @@ InputEvent *qemu_input_event_new_key(KeyValue *key, bool down);
|
|||
void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down);
|
||||
void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down);
|
||||
void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down);
|
||||
int qemu_input_key_value_to_number(const KeyValue *value);
|
||||
int qemu_input_key_value_to_qcode(const KeyValue *value);
|
||||
int qemu_input_key_value_to_scancode(const KeyValue *value, bool down,
|
||||
int *codes);
|
||||
|
||||
InputEvent *qemu_input_event_new_btn(InputButton btn, bool down);
|
||||
void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down);
|
||||
|
|
|
@ -866,8 +866,8 @@ escc_mem_writeb_data(char channel, uint32_t val) "Write channel %c, ch %d"
|
|||
escc_mem_readb_ctrl(char channel, uint32_t reg, uint8_t val) "Read channel %c, reg[%d] = %2.2x"
|
||||
escc_mem_readb_data(char channel, uint32_t ret) "Read channel %c, ch %d"
|
||||
escc_serial_receive_byte(char channel, int ch) "channel %c put ch %d"
|
||||
escc_sunkbd_event_in(int ch) "Untranslated keycode %2.2x"
|
||||
escc_sunkbd_event_out(int ch) "Translated keycode %2.2x"
|
||||
escc_sunkbd_event_in(int ch, const char *name, int down) "QKeyCode 0x%2.2x [%s], down %d"
|
||||
escc_sunkbd_event_out(int ch) "Translated keycode 0x%2.2x"
|
||||
escc_kbd_command(int val) "Command %d"
|
||||
escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x"
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
|
|||
vnc-obj-$(CONFIG_VNC_WS) += vnc-ws.o
|
||||
vnc-obj-y += vnc-jobs.o
|
||||
|
||||
common-obj-y += keymaps.o console.o cursor.o input.o input-legacy.o qemu-pixman.o
|
||||
common-obj-y += keymaps.o console.o cursor.o qemu-pixman.o
|
||||
common-obj-y += input.o input-keymap.o input-legacy.o
|
||||
common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o
|
||||
common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o sdl2.o
|
||||
common-obj-$(CONFIG_COCOA) += cocoa.o
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
#include "sysemu/sysemu.h"
|
||||
#include "ui/keymaps.h"
|
||||
#include "ui/input.h"
|
||||
|
||||
static const int qcode_to_number[] = {
|
||||
[Q_KEY_CODE_SHIFT] = 0x2a,
|
||||
[Q_KEY_CODE_SHIFT_R] = 0x36,
|
||||
|
||||
[Q_KEY_CODE_ALT] = 0x38,
|
||||
[Q_KEY_CODE_ALT_R] = 0xb8,
|
||||
[Q_KEY_CODE_ALTGR] = 0x64,
|
||||
[Q_KEY_CODE_ALTGR_R] = 0xe4,
|
||||
[Q_KEY_CODE_CTRL] = 0x1d,
|
||||
[Q_KEY_CODE_CTRL_R] = 0x9d,
|
||||
|
||||
[Q_KEY_CODE_MENU] = 0xdd,
|
||||
|
||||
[Q_KEY_CODE_ESC] = 0x01,
|
||||
|
||||
[Q_KEY_CODE_1] = 0x02,
|
||||
[Q_KEY_CODE_2] = 0x03,
|
||||
[Q_KEY_CODE_3] = 0x04,
|
||||
[Q_KEY_CODE_4] = 0x05,
|
||||
[Q_KEY_CODE_5] = 0x06,
|
||||
[Q_KEY_CODE_6] = 0x07,
|
||||
[Q_KEY_CODE_7] = 0x08,
|
||||
[Q_KEY_CODE_8] = 0x09,
|
||||
[Q_KEY_CODE_9] = 0x0a,
|
||||
[Q_KEY_CODE_0] = 0x0b,
|
||||
[Q_KEY_CODE_MINUS] = 0x0c,
|
||||
[Q_KEY_CODE_EQUAL] = 0x0d,
|
||||
[Q_KEY_CODE_BACKSPACE] = 0x0e,
|
||||
|
||||
[Q_KEY_CODE_TAB] = 0x0f,
|
||||
[Q_KEY_CODE_Q] = 0x10,
|
||||
[Q_KEY_CODE_W] = 0x11,
|
||||
[Q_KEY_CODE_E] = 0x12,
|
||||
[Q_KEY_CODE_R] = 0x13,
|
||||
[Q_KEY_CODE_T] = 0x14,
|
||||
[Q_KEY_CODE_Y] = 0x15,
|
||||
[Q_KEY_CODE_U] = 0x16,
|
||||
[Q_KEY_CODE_I] = 0x17,
|
||||
[Q_KEY_CODE_O] = 0x18,
|
||||
[Q_KEY_CODE_P] = 0x19,
|
||||
[Q_KEY_CODE_BRACKET_LEFT] = 0x1a,
|
||||
[Q_KEY_CODE_BRACKET_RIGHT] = 0x1b,
|
||||
[Q_KEY_CODE_RET] = 0x1c,
|
||||
|
||||
[Q_KEY_CODE_A] = 0x1e,
|
||||
[Q_KEY_CODE_S] = 0x1f,
|
||||
[Q_KEY_CODE_D] = 0x20,
|
||||
[Q_KEY_CODE_F] = 0x21,
|
||||
[Q_KEY_CODE_G] = 0x22,
|
||||
[Q_KEY_CODE_H] = 0x23,
|
||||
[Q_KEY_CODE_J] = 0x24,
|
||||
[Q_KEY_CODE_K] = 0x25,
|
||||
[Q_KEY_CODE_L] = 0x26,
|
||||
[Q_KEY_CODE_SEMICOLON] = 0x27,
|
||||
[Q_KEY_CODE_APOSTROPHE] = 0x28,
|
||||
[Q_KEY_CODE_GRAVE_ACCENT] = 0x29,
|
||||
|
||||
[Q_KEY_CODE_BACKSLASH] = 0x2b,
|
||||
[Q_KEY_CODE_Z] = 0x2c,
|
||||
[Q_KEY_CODE_X] = 0x2d,
|
||||
[Q_KEY_CODE_C] = 0x2e,
|
||||
[Q_KEY_CODE_V] = 0x2f,
|
||||
[Q_KEY_CODE_B] = 0x30,
|
||||
[Q_KEY_CODE_N] = 0x31,
|
||||
[Q_KEY_CODE_M] = 0x32,
|
||||
[Q_KEY_CODE_COMMA] = 0x33,
|
||||
[Q_KEY_CODE_DOT] = 0x34,
|
||||
[Q_KEY_CODE_SLASH] = 0x35,
|
||||
|
||||
[Q_KEY_CODE_ASTERISK] = 0x37,
|
||||
|
||||
[Q_KEY_CODE_SPC] = 0x39,
|
||||
[Q_KEY_CODE_CAPS_LOCK] = 0x3a,
|
||||
[Q_KEY_CODE_F1] = 0x3b,
|
||||
[Q_KEY_CODE_F2] = 0x3c,
|
||||
[Q_KEY_CODE_F3] = 0x3d,
|
||||
[Q_KEY_CODE_F4] = 0x3e,
|
||||
[Q_KEY_CODE_F5] = 0x3f,
|
||||
[Q_KEY_CODE_F6] = 0x40,
|
||||
[Q_KEY_CODE_F7] = 0x41,
|
||||
[Q_KEY_CODE_F8] = 0x42,
|
||||
[Q_KEY_CODE_F9] = 0x43,
|
||||
[Q_KEY_CODE_F10] = 0x44,
|
||||
[Q_KEY_CODE_NUM_LOCK] = 0x45,
|
||||
[Q_KEY_CODE_SCROLL_LOCK] = 0x46,
|
||||
|
||||
[Q_KEY_CODE_KP_DIVIDE] = 0xb5,
|
||||
[Q_KEY_CODE_KP_MULTIPLY] = 0x37,
|
||||
[Q_KEY_CODE_KP_SUBTRACT] = 0x4a,
|
||||
[Q_KEY_CODE_KP_ADD] = 0x4e,
|
||||
[Q_KEY_CODE_KP_ENTER] = 0x9c,
|
||||
[Q_KEY_CODE_KP_DECIMAL] = 0x53,
|
||||
[Q_KEY_CODE_SYSRQ] = 0x54,
|
||||
|
||||
[Q_KEY_CODE_KP_0] = 0x52,
|
||||
[Q_KEY_CODE_KP_1] = 0x4f,
|
||||
[Q_KEY_CODE_KP_2] = 0x50,
|
||||
[Q_KEY_CODE_KP_3] = 0x51,
|
||||
[Q_KEY_CODE_KP_4] = 0x4b,
|
||||
[Q_KEY_CODE_KP_5] = 0x4c,
|
||||
[Q_KEY_CODE_KP_6] = 0x4d,
|
||||
[Q_KEY_CODE_KP_7] = 0x47,
|
||||
[Q_KEY_CODE_KP_8] = 0x48,
|
||||
[Q_KEY_CODE_KP_9] = 0x49,
|
||||
|
||||
[Q_KEY_CODE_LESS] = 0x56,
|
||||
|
||||
[Q_KEY_CODE_F11] = 0x57,
|
||||
[Q_KEY_CODE_F12] = 0x58,
|
||||
|
||||
[Q_KEY_CODE_PRINT] = 0xb7,
|
||||
|
||||
[Q_KEY_CODE_HOME] = 0xc7,
|
||||
[Q_KEY_CODE_PGUP] = 0xc9,
|
||||
[Q_KEY_CODE_PGDN] = 0xd1,
|
||||
[Q_KEY_CODE_END] = 0xcf,
|
||||
|
||||
[Q_KEY_CODE_LEFT] = 0xcb,
|
||||
[Q_KEY_CODE_UP] = 0xc8,
|
||||
[Q_KEY_CODE_DOWN] = 0xd0,
|
||||
[Q_KEY_CODE_RIGHT] = 0xcd,
|
||||
|
||||
[Q_KEY_CODE_INSERT] = 0xd2,
|
||||
[Q_KEY_CODE_DELETE] = 0xd3,
|
||||
[Q_KEY_CODE_MAX] = 0,
|
||||
};
|
||||
|
||||
static int number_to_qcode[0xff];
|
||||
|
||||
int qemu_input_key_value_to_number(const KeyValue *value)
|
||||
{
|
||||
if (value->kind == KEY_VALUE_KIND_QCODE) {
|
||||
return qcode_to_number[value->qcode];
|
||||
} else {
|
||||
assert(value->kind == KEY_VALUE_KIND_NUMBER);
|
||||
return value->number;
|
||||
}
|
||||
}
|
||||
|
||||
int qemu_input_key_value_to_qcode(const KeyValue *value)
|
||||
{
|
||||
static int first = true;
|
||||
|
||||
if (first) {
|
||||
int qcode, number;
|
||||
first = false;
|
||||
for (qcode = 0; qcode < Q_KEY_CODE_MAX; qcode++) {
|
||||
number = qcode_to_number[qcode];
|
||||
assert(number < ARRAY_SIZE(number_to_qcode));
|
||||
number_to_qcode[number] = qcode;
|
||||
}
|
||||
}
|
||||
|
||||
if (value->kind == KEY_VALUE_KIND_QCODE) {
|
||||
return value->qcode;
|
||||
} else {
|
||||
assert(value->kind == KEY_VALUE_KIND_NUMBER);
|
||||
return number_to_qcode[value->number];
|
||||
}
|
||||
}
|
||||
|
||||
int qemu_input_key_value_to_scancode(const KeyValue *value, bool down,
|
||||
int *codes)
|
||||
{
|
||||
int keycode = qemu_input_key_value_to_number(value);
|
||||
int count = 0;
|
||||
|
||||
if (value->kind == KEY_VALUE_KIND_QCODE &&
|
||||
value->qcode == Q_KEY_CODE_PAUSE) {
|
||||
/* specific case */
|
||||
int v = down ? 0 : 0x80;
|
||||
codes[count++] = 0xe1;
|
||||
codes[count++] = 0x1d | v;
|
||||
codes[count++] = 0x45 | v;
|
||||
return count;
|
||||
}
|
||||
if (keycode & SCANCODE_GREY) {
|
||||
codes[count++] = SCANCODE_EMUL0;
|
||||
keycode &= ~SCANCODE_GREY;
|
||||
}
|
||||
if (!down) {
|
||||
keycode |= SCANCODE_UP;
|
||||
}
|
||||
codes[count++] = keycode;
|
||||
|
||||
return count;
|
||||
}
|
|
@ -60,152 +60,6 @@ static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
|
|||
static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
|
||||
QTAILQ_HEAD_INITIALIZER(mouse_handlers);
|
||||
|
||||
static const int key_defs[] = {
|
||||
[Q_KEY_CODE_SHIFT] = 0x2a,
|
||||
[Q_KEY_CODE_SHIFT_R] = 0x36,
|
||||
|
||||
[Q_KEY_CODE_ALT] = 0x38,
|
||||
[Q_KEY_CODE_ALT_R] = 0xb8,
|
||||
[Q_KEY_CODE_ALTGR] = 0x64,
|
||||
[Q_KEY_CODE_ALTGR_R] = 0xe4,
|
||||
[Q_KEY_CODE_CTRL] = 0x1d,
|
||||
[Q_KEY_CODE_CTRL_R] = 0x9d,
|
||||
|
||||
[Q_KEY_CODE_MENU] = 0xdd,
|
||||
|
||||
[Q_KEY_CODE_ESC] = 0x01,
|
||||
|
||||
[Q_KEY_CODE_1] = 0x02,
|
||||
[Q_KEY_CODE_2] = 0x03,
|
||||
[Q_KEY_CODE_3] = 0x04,
|
||||
[Q_KEY_CODE_4] = 0x05,
|
||||
[Q_KEY_CODE_5] = 0x06,
|
||||
[Q_KEY_CODE_6] = 0x07,
|
||||
[Q_KEY_CODE_7] = 0x08,
|
||||
[Q_KEY_CODE_8] = 0x09,
|
||||
[Q_KEY_CODE_9] = 0x0a,
|
||||
[Q_KEY_CODE_0] = 0x0b,
|
||||
[Q_KEY_CODE_MINUS] = 0x0c,
|
||||
[Q_KEY_CODE_EQUAL] = 0x0d,
|
||||
[Q_KEY_CODE_BACKSPACE] = 0x0e,
|
||||
|
||||
[Q_KEY_CODE_TAB] = 0x0f,
|
||||
[Q_KEY_CODE_Q] = 0x10,
|
||||
[Q_KEY_CODE_W] = 0x11,
|
||||
[Q_KEY_CODE_E] = 0x12,
|
||||
[Q_KEY_CODE_R] = 0x13,
|
||||
[Q_KEY_CODE_T] = 0x14,
|
||||
[Q_KEY_CODE_Y] = 0x15,
|
||||
[Q_KEY_CODE_U] = 0x16,
|
||||
[Q_KEY_CODE_I] = 0x17,
|
||||
[Q_KEY_CODE_O] = 0x18,
|
||||
[Q_KEY_CODE_P] = 0x19,
|
||||
[Q_KEY_CODE_BRACKET_LEFT] = 0x1a,
|
||||
[Q_KEY_CODE_BRACKET_RIGHT] = 0x1b,
|
||||
[Q_KEY_CODE_RET] = 0x1c,
|
||||
|
||||
[Q_KEY_CODE_A] = 0x1e,
|
||||
[Q_KEY_CODE_S] = 0x1f,
|
||||
[Q_KEY_CODE_D] = 0x20,
|
||||
[Q_KEY_CODE_F] = 0x21,
|
||||
[Q_KEY_CODE_G] = 0x22,
|
||||
[Q_KEY_CODE_H] = 0x23,
|
||||
[Q_KEY_CODE_J] = 0x24,
|
||||
[Q_KEY_CODE_K] = 0x25,
|
||||
[Q_KEY_CODE_L] = 0x26,
|
||||
[Q_KEY_CODE_SEMICOLON] = 0x27,
|
||||
[Q_KEY_CODE_APOSTROPHE] = 0x28,
|
||||
[Q_KEY_CODE_GRAVE_ACCENT] = 0x29,
|
||||
|
||||
[Q_KEY_CODE_BACKSLASH] = 0x2b,
|
||||
[Q_KEY_CODE_Z] = 0x2c,
|
||||
[Q_KEY_CODE_X] = 0x2d,
|
||||
[Q_KEY_CODE_C] = 0x2e,
|
||||
[Q_KEY_CODE_V] = 0x2f,
|
||||
[Q_KEY_CODE_B] = 0x30,
|
||||
[Q_KEY_CODE_N] = 0x31,
|
||||
[Q_KEY_CODE_M] = 0x32,
|
||||
[Q_KEY_CODE_COMMA] = 0x33,
|
||||
[Q_KEY_CODE_DOT] = 0x34,
|
||||
[Q_KEY_CODE_SLASH] = 0x35,
|
||||
|
||||
[Q_KEY_CODE_ASTERISK] = 0x37,
|
||||
|
||||
[Q_KEY_CODE_SPC] = 0x39,
|
||||
[Q_KEY_CODE_CAPS_LOCK] = 0x3a,
|
||||
[Q_KEY_CODE_F1] = 0x3b,
|
||||
[Q_KEY_CODE_F2] = 0x3c,
|
||||
[Q_KEY_CODE_F3] = 0x3d,
|
||||
[Q_KEY_CODE_F4] = 0x3e,
|
||||
[Q_KEY_CODE_F5] = 0x3f,
|
||||
[Q_KEY_CODE_F6] = 0x40,
|
||||
[Q_KEY_CODE_F7] = 0x41,
|
||||
[Q_KEY_CODE_F8] = 0x42,
|
||||
[Q_KEY_CODE_F9] = 0x43,
|
||||
[Q_KEY_CODE_F10] = 0x44,
|
||||
[Q_KEY_CODE_NUM_LOCK] = 0x45,
|
||||
[Q_KEY_CODE_SCROLL_LOCK] = 0x46,
|
||||
|
||||
[Q_KEY_CODE_KP_DIVIDE] = 0xb5,
|
||||
[Q_KEY_CODE_KP_MULTIPLY] = 0x37,
|
||||
[Q_KEY_CODE_KP_SUBTRACT] = 0x4a,
|
||||
[Q_KEY_CODE_KP_ADD] = 0x4e,
|
||||
[Q_KEY_CODE_KP_ENTER] = 0x9c,
|
||||
[Q_KEY_CODE_KP_DECIMAL] = 0x53,
|
||||
[Q_KEY_CODE_SYSRQ] = 0x54,
|
||||
|
||||
[Q_KEY_CODE_KP_0] = 0x52,
|
||||
[Q_KEY_CODE_KP_1] = 0x4f,
|
||||
[Q_KEY_CODE_KP_2] = 0x50,
|
||||
[Q_KEY_CODE_KP_3] = 0x51,
|
||||
[Q_KEY_CODE_KP_4] = 0x4b,
|
||||
[Q_KEY_CODE_KP_5] = 0x4c,
|
||||
[Q_KEY_CODE_KP_6] = 0x4d,
|
||||
[Q_KEY_CODE_KP_7] = 0x47,
|
||||
[Q_KEY_CODE_KP_8] = 0x48,
|
||||
[Q_KEY_CODE_KP_9] = 0x49,
|
||||
|
||||
[Q_KEY_CODE_LESS] = 0x56,
|
||||
|
||||
[Q_KEY_CODE_F11] = 0x57,
|
||||
[Q_KEY_CODE_F12] = 0x58,
|
||||
|
||||
[Q_KEY_CODE_PRINT] = 0xb7,
|
||||
|
||||
[Q_KEY_CODE_HOME] = 0xc7,
|
||||
[Q_KEY_CODE_PGUP] = 0xc9,
|
||||
[Q_KEY_CODE_PGDN] = 0xd1,
|
||||
[Q_KEY_CODE_END] = 0xcf,
|
||||
|
||||
[Q_KEY_CODE_LEFT] = 0xcb,
|
||||
[Q_KEY_CODE_UP] = 0xc8,
|
||||
[Q_KEY_CODE_DOWN] = 0xd0,
|
||||
[Q_KEY_CODE_RIGHT] = 0xcd,
|
||||
|
||||
[Q_KEY_CODE_INSERT] = 0xd2,
|
||||
[Q_KEY_CODE_DELETE] = 0xd3,
|
||||
#ifdef NEED_CPU_H
|
||||
#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64)
|
||||
[Q_KEY_CODE_STOP] = 0xf0,
|
||||
[Q_KEY_CODE_AGAIN] = 0xf1,
|
||||
[Q_KEY_CODE_PROPS] = 0xf2,
|
||||
[Q_KEY_CODE_UNDO] = 0xf3,
|
||||
[Q_KEY_CODE_FRONT] = 0xf4,
|
||||
[Q_KEY_CODE_COPY] = 0xf5,
|
||||
[Q_KEY_CODE_OPEN] = 0xf6,
|
||||
[Q_KEY_CODE_PASTE] = 0xf7,
|
||||
[Q_KEY_CODE_FIND] = 0xf8,
|
||||
[Q_KEY_CODE_CUT] = 0xf9,
|
||||
[Q_KEY_CODE_LF] = 0xfa,
|
||||
[Q_KEY_CODE_HELP] = 0xfb,
|
||||
[Q_KEY_CODE_META_L] = 0xfc,
|
||||
[Q_KEY_CODE_META_R] = 0xfd,
|
||||
[Q_KEY_CODE_COMPOSE] = 0xfe,
|
||||
#endif
|
||||
#endif
|
||||
[Q_KEY_CODE_MAX] = 0,
|
||||
};
|
||||
|
||||
int index_from_key(const char *key)
|
||||
{
|
||||
int i;
|
||||
|
@ -220,48 +74,44 @@ int index_from_key(const char *key)
|
|||
return i;
|
||||
}
|
||||
|
||||
static int *keycodes;
|
||||
static int keycodes_size;
|
||||
static KeyValue **keyvalues;
|
||||
static int keyvalues_size;
|
||||
static QEMUTimer *key_timer;
|
||||
|
||||
static int keycode_from_keyvalue(const KeyValue *value)
|
||||
static void free_keyvalues(void)
|
||||
{
|
||||
if (value->kind == KEY_VALUE_KIND_QCODE) {
|
||||
return key_defs[value->qcode];
|
||||
} else {
|
||||
assert(value->kind == KEY_VALUE_KIND_NUMBER);
|
||||
return value->number;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_keycodes(void)
|
||||
{
|
||||
g_free(keycodes);
|
||||
keycodes = NULL;
|
||||
keycodes_size = 0;
|
||||
g_free(keyvalues);
|
||||
keyvalues = NULL;
|
||||
keyvalues_size = 0;
|
||||
}
|
||||
|
||||
static void release_keys(void *opaque)
|
||||
{
|
||||
while (keycodes_size > 0) {
|
||||
qemu_input_event_send_key_number(NULL, keycodes[--keycodes_size],
|
||||
false);
|
||||
while (keyvalues_size > 0) {
|
||||
qemu_input_event_send_key(NULL, keyvalues[--keyvalues_size],
|
||||
false);
|
||||
}
|
||||
|
||||
free_keycodes();
|
||||
free_keyvalues();
|
||||
}
|
||||
|
||||
static KeyValue *copy_key_value(KeyValue *src)
|
||||
{
|
||||
KeyValue *dst = g_new(KeyValue, 1);
|
||||
memcpy(dst, src, sizeof(*src));
|
||||
return dst;
|
||||
}
|
||||
|
||||
void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
|
||||
Error **errp)
|
||||
{
|
||||
int keycode;
|
||||
KeyValueList *p;
|
||||
|
||||
if (!key_timer) {
|
||||
key_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, release_keys, NULL);
|
||||
}
|
||||
|
||||
if (keycodes != NULL) {
|
||||
if (keyvalues != NULL) {
|
||||
timer_del(key_timer);
|
||||
release_keys(NULL);
|
||||
}
|
||||
|
@ -271,51 +121,33 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
|
|||
}
|
||||
|
||||
for (p = keys; p != NULL; p = p->next) {
|
||||
/* key down events */
|
||||
keycode = keycode_from_keyvalue(p->value);
|
||||
if (keycode < 0x01 || keycode > 0xff) {
|
||||
error_setg(errp, "invalid hex keycode 0x%x", keycode);
|
||||
free_keycodes();
|
||||
return;
|
||||
}
|
||||
qemu_input_event_send_key(NULL, copy_key_value(p->value), true);
|
||||
|
||||
qemu_input_event_send_key_number(NULL, keycode, true);
|
||||
|
||||
keycodes = g_realloc(keycodes, sizeof(int) * (keycodes_size + 1));
|
||||
keycodes[keycodes_size++] = keycode;
|
||||
keyvalues = g_realloc(keyvalues, sizeof(KeyValue *) *
|
||||
(keyvalues_size + 1));
|
||||
keyvalues[keyvalues_size++] = copy_key_value(p->value);
|
||||
}
|
||||
|
||||
/* delayed key up events */
|
||||
timer_mod(key_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
||||
muldiv64(get_ticks_per_sec(), hold_time, 1000));
|
||||
muldiv64(get_ticks_per_sec(), hold_time, 1000));
|
||||
}
|
||||
|
||||
static void legacy_kbd_event(DeviceState *dev, QemuConsole *src,
|
||||
InputEvent *evt)
|
||||
{
|
||||
QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev;
|
||||
int keycode = keycode_from_keyvalue(evt->key->key);
|
||||
int scancodes[3], i, count;
|
||||
|
||||
if (!entry || !entry->put_kbd) {
|
||||
return;
|
||||
}
|
||||
if (evt->key->key->kind == KEY_VALUE_KIND_QCODE &&
|
||||
evt->key->key->qcode == Q_KEY_CODE_PAUSE) {
|
||||
/* specific case */
|
||||
int v = evt->key->down ? 0 : 0x80;
|
||||
entry->put_kbd(entry->opaque, 0xe1);
|
||||
entry->put_kbd(entry->opaque, 0x1d | v);
|
||||
entry->put_kbd(entry->opaque, 0x45 | v);
|
||||
return;
|
||||
count = qemu_input_key_value_to_scancode(evt->key->key,
|
||||
evt->key->down,
|
||||
scancodes);
|
||||
for (i = 0; i < count; i++) {
|
||||
entry->put_kbd(entry->opaque, scancodes[i]);
|
||||
}
|
||||
if (keycode & SCANCODE_GREY) {
|
||||
entry->put_kbd(entry->opaque, SCANCODE_EMUL0);
|
||||
keycode &= ~SCANCODE_GREY;
|
||||
}
|
||||
if (!evt->key->down) {
|
||||
keycode |= SCANCODE_UP;
|
||||
}
|
||||
entry->put_kbd(entry->opaque, keycode);
|
||||
}
|
||||
|
||||
static QemuInputHandler legacy_kbd_handler = {
|
||||
|
|
|
@ -39,6 +39,13 @@ void qemu_input_handler_activate(QemuInputHandlerState *s)
|
|||
qemu_input_check_mode_change();
|
||||
}
|
||||
|
||||
void qemu_input_handler_deactivate(QemuInputHandlerState *s)
|
||||
{
|
||||
QTAILQ_REMOVE(&handlers, s, node);
|
||||
QTAILQ_INSERT_TAIL(&handlers, s, node);
|
||||
qemu_input_check_mode_change();
|
||||
}
|
||||
|
||||
void qemu_input_handler_unregister(QemuInputHandlerState *s)
|
||||
{
|
||||
QTAILQ_REMOVE(&handlers, s, node);
|
||||
|
|
Loading…
Reference in New Issue