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:
Peter Maydell 2014-05-19 12:53:07 +01:00
commit 5bc8f026dd
8 changed files with 552 additions and 281 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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"

View File

@ -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

191
ui/input-keymap.c Normal file
View File

@ -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;
}

View File

@ -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 = {

View File

@ -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);