X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=hw%2Fps2.c;h=5367df10ce4ec4b89589766dd19b929d7ee9005f;hb=cd346349b45ef056f138a184f660b8c34c3213cc;hp=e7c66f648f3e43a1ba46b77cd88628029f9638cf;hpb=0e43e99c045eb22415a7e52e2f88dbdb8e2d96f5;p=qemu diff --git a/hw/ps2.c b/hw/ps2.c index e7c66f6..5367df1 100644 --- a/hw/ps2.c +++ b/hw/ps2.c @@ -1,8 +1,8 @@ /* * QEMU PS/2 keyboard/mouse emulation - * + * * Copyright (c) 2003 Fabrice Bellard - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -83,6 +83,10 @@ typedef struct { typedef struct { PS2State common; int scan_enabled; + /* Qemu uses translated PC scancodes internally. To avoid multiple + conversions we do the translation (if any) in the PS/2 emulation + not the keyboard controller. */ + int translate; } PS2KbdState; typedef struct { @@ -99,6 +103,18 @@ typedef struct { uint8_t mouse_buttons; } PS2MouseState; +/* Table to convert from PC scancodes to raw scancodes. */ +static const unsigned char ps2_raw_keycode[128] = { + 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13, + 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27, + 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42, + 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3, + 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105, + 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63, + 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111, + 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110 +}; + void ps2_queue(void *opaque, int b) { PS2State *s = (PS2State *)opaque; @@ -115,7 +131,13 @@ void ps2_queue(void *opaque, int b) static void ps2_put_keycode(void *opaque, int keycode) { - PS2MouseState *s = opaque; + PS2KbdState *s = opaque; + if (!s->translate && keycode < 0xe0) + { + if (keycode & 0x80) + ps2_queue(&s->common, 0xf0); + keycode = ps2_raw_keycode[keycode & 0x7f]; + } ps2_queue(&s->common, keycode); } @@ -124,7 +146,7 @@ uint32_t ps2_read_data(void *opaque) PS2State *s = (PS2State *)opaque; PS2Queue *q; int val, index; - + q = &s->queue; if (q->count == 0) { /* NOTE: if no data left, we return the last keyboard one @@ -214,6 +236,16 @@ void ps2_write_keyboard(void *opaque, int val) } } +/* Set the scancode translation mode. + 0 = raw scancodes. + 1 = translated scancodes (used by qemu internally). */ + +void ps2_keyboard_set_translation(void *opaque, int mode) +{ + PS2KbdState *s = (PS2KbdState *)opaque; + s->translate = mode; +} + static void ps2_mouse_send_packet(PS2MouseState *s) { unsigned int b; @@ -262,7 +294,7 @@ static void ps2_mouse_send_packet(PS2MouseState *s) s->mouse_dz -= dz1; } -static void ps2_mouse_event(void *opaque, +static void ps2_mouse_event(void *opaque, int dx, int dy, int dz, int buttons_state) { PS2MouseState *s = opaque; @@ -279,7 +311,7 @@ static void ps2_mouse_event(void *opaque, s->mouse_buttons == buttons_state) return; s->mouse_buttons = buttons_state; - + if (!(s->mouse_status & MOUSE_STATUS_REMOTE) && (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) { for(;;) { @@ -292,6 +324,11 @@ static void ps2_mouse_event(void *opaque, } } +void ps2_mouse_fake_event(void *opaque) +{ + ps2_mouse_event(opaque, 1, 0, 0, 0); +} + void ps2_write_mouse(void *opaque, int val) { PS2MouseState *s = (PS2MouseState *)opaque; @@ -397,12 +434,12 @@ void ps2_write_mouse(void *opaque, int val) s->mouse_detect_state = 0; break; case 2: - if (val == 80) + if (val == 80) s->mouse_type = 3; /* IMPS/2 */ s->mouse_detect_state = 0; break; case 3: - if (val == 80) + if (val == 80) s->mouse_type = 4; /* IMEX */ s->mouse_detect_state = 0; break; @@ -429,19 +466,38 @@ static void ps2_reset(void *opaque) q->count = 0; } +static void ps2_common_save (QEMUFile *f, PS2State *s) +{ + qemu_put_be32s (f, &s->write_cmd); + qemu_put_be32s (f, &s->queue.rptr); + qemu_put_be32s (f, &s->queue.wptr); + qemu_put_be32s (f, &s->queue.count); + qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data)); +} + +static void ps2_common_load (QEMUFile *f, PS2State *s) +{ + qemu_get_be32s (f, &s->write_cmd); + qemu_get_be32s (f, &s->queue.rptr); + qemu_get_be32s (f, &s->queue.wptr); + qemu_get_be32s (f, &s->queue.count); + qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data)); +} + static void ps2_kbd_save(QEMUFile* f, void* opaque) { PS2KbdState *s = (PS2KbdState*)opaque; - - qemu_put_be32s(f, &s->common.write_cmd); + + ps2_common_save (f, &s->common); qemu_put_be32s(f, &s->scan_enabled); + qemu_put_be32s(f, &s->translate); } static void ps2_mouse_save(QEMUFile* f, void* opaque) { PS2MouseState *s = (PS2MouseState*)opaque; - - qemu_put_be32s(f, &s->common.write_cmd); + + ps2_common_save (f, &s->common); qemu_put_8s(f, &s->mouse_status); qemu_put_8s(f, &s->mouse_resolution); qemu_put_8s(f, &s->mouse_sample_rate); @@ -457,21 +513,24 @@ static void ps2_mouse_save(QEMUFile* f, void* opaque) static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id) { PS2KbdState *s = (PS2KbdState*)opaque; - - if (version_id != 1) + + if (version_id != 2) return -EINVAL; - qemu_get_be32s(f, &s->common.write_cmd); + + ps2_common_load (f, &s->common); qemu_get_be32s(f, &s->scan_enabled); + qemu_get_be32s(f, &s->translate); return 0; } static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id) { PS2MouseState *s = (PS2MouseState*)opaque; - - if (version_id != 1) + + if (version_id != 2) return -EINVAL; - qemu_get_be32s(f, &s->common.write_cmd); + + ps2_common_load (f, &s->common); qemu_get_8s(f, &s->mouse_status); qemu_get_8s(f, &s->mouse_resolution); qemu_get_8s(f, &s->mouse_sample_rate); @@ -492,7 +551,7 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) s->common.update_irq = update_irq; s->common.update_arg = update_arg; ps2_reset(&s->common); - register_savevm("ps2kbd", 0, 1, ps2_kbd_save, ps2_kbd_load, s); + register_savevm("ps2kbd", 0, 2, ps2_kbd_save, ps2_kbd_load, s); qemu_add_kbd_event_handler(ps2_put_keycode, s); qemu_register_reset(ps2_reset, &s->common); return s; @@ -505,8 +564,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; ps2_reset(&s->common); - register_savevm("ps2mouse", 0, 1, ps2_mouse_save, ps2_mouse_load, s); - qemu_add_mouse_event_handler(ps2_mouse_event, s); + register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s); + qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse"); qemu_register_reset(ps2_reset, &s->common); return s; }