diff options
author | Vaporeon | 2018-05-11 01:03:57 +1200 |
---|---|---|
committer | Vaporeon | 2018-05-11 01:03:57 +1200 |
commit | 16d1021ff9917fc3a52057dbfbf6ee7759479659 (patch) | |
tree | 8e6cef1ae8bae6e7865e5d63112d5333c7e19abc | |
parent | d32abf9ef79b16fda6c3bc467b56914c3873565e (diff) | |
download | aur-16d1021ff9917fc3a52057dbfbf6ee7759479659.tar.gz |
PS/2 input patch
-rw-r--r-- | .SRCINFO | 6 | ||||
-rw-r--r-- | PKGBUILD | 9 | ||||
-rw-r--r-- | ps2-fixes-v2.patch | 315 |
3 files changed, 325 insertions, 5 deletions
@@ -1,9 +1,9 @@ # Generated by mksrcinfo v8 -# Wed May 9 08:01:07 UTC 2018 +# Thu May 10 12:57:45 UTC 2018 pkgbase = qemu-patched pkgdesc = A generic and open source machine emulator and virtualizer - Patched for extra functionality pkgver = 2.12.0 - pkgrel = 2 + pkgrel = 3 url = http://wiki.qemu.org/ arch = x86_64 license = GPL2 @@ -41,6 +41,7 @@ pkgbase = qemu-patched source = cpu-pinning.patch source = audio-improvements.patch source = amd-smt-fixes-v7.patch + source = ps2-fixes-v2.patch sha256sums = e69301f361ff65bf5dabd8a19196aeaa5613c1b5ae1678f0823bdf50e7d5c6fc sha256sums = SKIP sha256sums = c39bcde4a09165e64419fd2033b3532378bba84d509d39e2d51694d44c1f8d88 @@ -49,6 +50,7 @@ pkgbase = qemu-patched sha256sums = 5c6baf8d171a75c342ffcc5c4259570b3d8d4f34166d7bc1f694ecf571662f2d sha256sums = f54184f2eedf6e3eb1bf66f8f853df5e18cf62cad072fa4937744524d11a3f2b sha256sums = 4a06b86eaa9cde2ad5613a7cd7ac0a222b388a116f5dcf285252dddcb883108b + sha256sums = 6d83a0f70c5f57a0c0fbb657b47ecceeb79273487625f5b29639f105261c33f8 pkgname = qemu-patched optdepends = qemu-patched-arch-extra: extra architectures support @@ -8,7 +8,7 @@ pkgname=(qemu-patched qemu-patched-headless qemu-patched-arch-extra qemu-patched _pkgname=qemu pkgdesc="A generic and open source machine emulator and virtualizer - Patched for extra functionality" pkgver=2.12.0 -pkgrel=2 +pkgrel=3 arch=(x86_64) license=(GPL2 LGPL2.1) url="http://wiki.qemu.org/" @@ -22,7 +22,8 @@ source=("$url/download/${_pkgname}-${pkgver}.tar.xz"{,.sig} allow_elf64.patch cpu-pinning.patch audio-improvements.patch - amd-smt-fixes-v7.patch) + amd-smt-fixes-v7.patch + ps2-fixes-v2.patch) sha256sums=('e69301f361ff65bf5dabd8a19196aeaa5613c1b5ae1678f0823bdf50e7d5c6fc' 'SKIP' 'c39bcde4a09165e64419fd2033b3532378bba84d509d39e2d51694d44c1f8d88' @@ -30,7 +31,8 @@ sha256sums=('e69301f361ff65bf5dabd8a19196aeaa5613c1b5ae1678f0823bdf50e7d5c6fc' '59751f1ed26ea61b2a37ebee4be6979e584a450b611282138a0893aa9173e2e4' '5c6baf8d171a75c342ffcc5c4259570b3d8d4f34166d7bc1f694ecf571662f2d' 'f54184f2eedf6e3eb1bf66f8f853df5e18cf62cad072fa4937744524d11a3f2b' - '4a06b86eaa9cde2ad5613a7cd7ac0a222b388a116f5dcf285252dddcb883108b') + '4a06b86eaa9cde2ad5613a7cd7ac0a222b388a116f5dcf285252dddcb883108b' + '6d83a0f70c5f57a0c0fbb657b47ecceeb79273487625f5b29639f105261c33f8') validpgpkeys=('CEACC9E15534EBABB82D3FA03353C9CEF108B584') case $CARCH in @@ -49,6 +51,7 @@ prepare() { patch -p1 < ../cpu-pinning.patch patch -p1 < ../audio-improvements.patch patch -p1 < ../amd-smt-fixes-v7.patch + patch -p1 < ../ps2-fixes-v2.patch } build() { diff --git a/ps2-fixes-v2.patch b/ps2-fixes-v2.patch new file mode 100644 index 000000000000..3aa3f90ed5ae --- /dev/null +++ b/ps2-fixes-v2.patch @@ -0,0 +1,315 @@ +This allows guest's to correctly reinitialize and identify the mouse +should the guest decide to re-scan or reset during mouse input events. + +When the guest sends the "Identify" command, due to the PC's hardware +architecutre it is impossible to reliably determine the response from +the command amongst other streaming data, such as mouse or keyboard +events. Standard practice is for the guest to disable the device and +then issue the identify command, so this must be obeyed. + +Signed-off-by: Geoffrey McRae <address@hidden> +--- + hw/input/ps2.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/hw/input/ps2.c b/hw/input/ps2.c +index 06f5d2ac4a..f84a8f5179 100644 +--- a/hw/input/ps2.c ++++ b/hw/input/ps2.c +@@ -232,6 +232,9 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src, + uint16_t keycode = 0; + int mod; + ++ if (!s->scan_enabled) ++ return; ++ + qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); + assert(evt->type == INPUT_EVENT_KIND_KEY); + qcode = qemu_input_key_value_to_qcode(key->key); +@@ -673,6 +676,9 @@ static void ps2_mouse_sync(DeviceState *dev) + { + PS2MouseState *s = (PS2MouseState *)dev; + ++ if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) ++ return; ++ + if (s->mouse_buttons) { + qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); + } +@@ -776,6 +782,7 @@ void ps2_write_mouse(void *opaque, int val) + s->mouse_resolution = 2; + s->mouse_status = 0; + s->mouse_type = 0; ++ ps2_reset_queue(&s->common); + ps2_queue(&s->common, AUX_ACK); + ps2_queue(&s->common, 0xaa); + ps2_queue(&s->common, s->mouse_type); +-- +2.14.2 + +This fixes an issue by adding bounds checking to multi-byte packets +where the PS/2 mouse data stream may become corrupted due to data being +discarded when the PS/2 ringbuffer is full. + +Interrupts for Multi-byte responses are postponed until the final byte +has been queued. + +These changes fix a bug where windows guests drop the mouse device +entirely requring the guest to be restarted. + +Signed-off-by: Geoffrey McRae <address@hidden> +--- + hw/input/ps2.c | 120 +++++++++++++++++++++++++++++++++++++------------ + include/hw/input/ps2.h | 5 +++ + 2 files changed, 96 insertions(+), 29 deletions(-) + +diff --git a/hw/input/ps2.c b/hw/input/ps2.c +index f84a8f5179..0580ca0700 100644 +--- a/hw/input/ps2.c ++++ b/hw/input/ps2.c +@@ -188,16 +188,60 @@ static void ps2_reset_queue(PS2State *s) + q->count = 0; + } + +-void ps2_queue(PS2State *s, int b) ++void ps2_queue_noirq(PS2State *s, int b) + { + PS2Queue *q = &s->queue; + +- if (q->count >= PS2_QUEUE_SIZE - 1) ++ if (q->count == PS2_QUEUE_SIZE) + return; ++ + q->data[q->wptr] = b; + if (++q->wptr == PS2_QUEUE_SIZE) + q->wptr = 0; + q->count++; ++} ++ ++void ps2_raise_irq(PS2State *s) ++{ ++ s->update_irq(s->update_arg, 1); ++} ++ ++void ps2_queue(PS2State *s, int b) ++{ ++ ps2_queue_noirq(s, b); ++ s->update_irq(s->update_arg, 1); ++} ++ ++void ps2_queue_2(PS2State *s, int b1, int b2) ++{ ++ if (PS2_QUEUE_SIZE - s->queue.count < 2) ++ return; ++ ++ ps2_queue_noirq(s, b1); ++ ps2_queue_noirq(s, b2); ++ s->update_irq(s->update_arg, 1); ++} ++ ++void ps2_queue_3(PS2State *s, int b1, int b2, int b3) ++{ ++ if (PS2_QUEUE_SIZE - s->queue.count < 3) ++ return; ++ ++ ps2_queue_noirq(s, b1); ++ ps2_queue_noirq(s, b2); ++ ps2_queue_noirq(s, b3); ++ s->update_irq(s->update_arg, 1); ++} ++ ++void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4) ++{ ++ if (PS2_QUEUE_SIZE - s->queue.count < 4) ++ return; ++ ++ ps2_queue_noirq(s, b1); ++ ps2_queue_noirq(s, b2); ++ ps2_queue_noirq(s, b3); ++ ps2_queue_noirq(s, b4); + s->update_irq(s->update_arg, 1); + } + +@@ -499,13 +543,17 @@ void ps2_write_keyboard(void *opaque, int val) + ps2_queue(&s->common, KBD_REPLY_RESEND); + break; + case KBD_CMD_GET_ID: +- ps2_queue(&s->common, KBD_REPLY_ACK); + /* We emulate a MF2 AT keyboard here */ +- ps2_queue(&s->common, KBD_REPLY_ID); + if (s->translate) +- ps2_queue(&s->common, 0x41); ++ ps2_queue_3(&s->common, ++ KBD_REPLY_ACK, ++ KBD_REPLY_ID, ++ 0x41); + else +- ps2_queue(&s->common, 0x83); ++ ps2_queue_3(&s->common, ++ KBD_REPLY_ACK, ++ KBD_REPLY_ID, ++ 0x83); + break; + case KBD_CMD_ECHO: + ps2_queue(&s->common, KBD_CMD_ECHO); +@@ -532,8 +580,9 @@ void ps2_write_keyboard(void *opaque, int val) + break; + case KBD_CMD_RESET: + ps2_reset_keyboard(s); +- ps2_queue(&s->common, KBD_REPLY_ACK); +- ps2_queue(&s->common, KBD_REPLY_POR); ++ ps2_queue_2(&s->common, ++ KBD_REPLY_ACK, ++ KBD_REPLY_POR); + break; + default: + ps2_queue(&s->common, KBD_REPLY_RESEND); +@@ -542,8 +591,11 @@ void ps2_write_keyboard(void *opaque, int val) + break; + case KBD_CMD_SCANCODE: + if (val == 0) { +- ps2_queue(&s->common, KBD_REPLY_ACK); +- ps2_put_keycode(s, s->scancode_set); ++ if (s->common.queue.count <= PS2_QUEUE_SIZE - 2) ++ { ++ ps2_queue(&s->common, KBD_REPLY_ACK); ++ ps2_put_keycode(s, s->scancode_set); ++ } + } else if (val >= 1 && val <= 3) { + s->scancode_set = val; + ps2_queue(&s->common, KBD_REPLY_ACK); +@@ -575,11 +627,15 @@ void ps2_keyboard_set_translation(void *opaque, int mode) + s->translate = mode; + } + +-static void ps2_mouse_send_packet(PS2MouseState *s) ++static int ps2_mouse_send_packet(PS2MouseState *s) + { + unsigned int b; + int dx1, dy1, dz1; + ++ const int needed = 3 + (s->mouse_type - 2); ++ if (PS2_QUEUE_SIZE - s->common.queue.count < needed) ++ return 0; ++ + dx1 = s->mouse_dx; + dy1 = s->mouse_dy; + dz1 = s->mouse_dz; +@@ -593,9 +649,9 @@ static void ps2_mouse_send_packet(PS2MouseState *s) + else if (dy1 < -127) + dy1 = -127; + b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07); +- ps2_queue(&s->common, b); +- ps2_queue(&s->common, dx1 & 0xff); +- ps2_queue(&s->common, dy1 & 0xff); ++ ps2_queue_noirq(&s->common, b); ++ ps2_queue_noirq(&s->common, dx1 & 0xff); ++ ps2_queue_noirq(&s->common, dy1 & 0xff); + /* extra byte for IMPS/2 or IMEX */ + switch(s->mouse_type) { + default: +@@ -605,7 +661,7 @@ static void ps2_mouse_send_packet(PS2MouseState *s) + dz1 = 127; + else if (dz1 < -127) + dz1 = -127; +- ps2_queue(&s->common, dz1 & 0xff); ++ ps2_queue_noirq(&s->common, dz1 & 0xff); + break; + case 4: + if (dz1 > 7) +@@ -613,15 +669,19 @@ static void ps2_mouse_send_packet(PS2MouseState *s) + else if (dz1 < -7) + dz1 = -7; + b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); +- ps2_queue(&s->common, b); ++ ps2_queue_noirq(&s->common, b); + break; + } + ++ ps2_raise_irq(&s->common); ++ + trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b); + /* update deltas */ + s->mouse_dx -= dx1; + s->mouse_dy -= dy1; + s->mouse_dz -= dz1; ++ ++ return 1; + } + + static void ps2_mouse_event(DeviceState *dev, QemuConsole *src, +@@ -683,10 +743,9 @@ static void ps2_mouse_sync(DeviceState *dev) + qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); + } + 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); ++ /* if not remote, send event. Multiple events are sent if ++ too big deltas */ ++ while(ps2_mouse_send_packet(s)) { + if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0) + break; + } +@@ -745,8 +804,9 @@ void ps2_write_mouse(void *opaque, int val) + ps2_queue(&s->common, AUX_ACK); + break; + case AUX_GET_TYPE: +- ps2_queue(&s->common, AUX_ACK); +- ps2_queue(&s->common, s->mouse_type); ++ ps2_queue_2(&s->common, ++ AUX_ACK, ++ s->mouse_type); + break; + case AUX_SET_RES: + case AUX_SET_SAMPLE: +@@ -754,10 +814,11 @@ void ps2_write_mouse(void *opaque, int val) + ps2_queue(&s->common, AUX_ACK); + break; + case AUX_GET_SCALE: +- ps2_queue(&s->common, AUX_ACK); +- ps2_queue(&s->common, s->mouse_status); +- ps2_queue(&s->common, s->mouse_resolution); +- ps2_queue(&s->common, s->mouse_sample_rate); ++ ps2_queue_4(&s->common, ++ AUX_ACK, ++ s->mouse_status, ++ s->mouse_resolution, ++ s->mouse_sample_rate); + break; + case AUX_POLL: + ps2_queue(&s->common, AUX_ACK); +@@ -783,9 +844,10 @@ void ps2_write_mouse(void *opaque, int val) + s->mouse_status = 0; + s->mouse_type = 0; + ps2_reset_queue(&s->common); +- ps2_queue(&s->common, AUX_ACK); +- ps2_queue(&s->common, 0xaa); +- ps2_queue(&s->common, s->mouse_type); ++ ps2_queue_3(&s->common, ++ AUX_ACK, ++ 0xaa, ++ s->mouse_type); + break; + default: + break; +diff --git a/include/hw/input/ps2.h b/include/hw/input/ps2.h +index 94709b8502..213aa16aa3 100644 +--- a/include/hw/input/ps2.h ++++ b/include/hw/input/ps2.h +@@ -37,7 +37,12 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg); + void ps2_write_mouse(void *, int val); + void ps2_write_keyboard(void *, int val); + uint32_t ps2_read_data(PS2State *s); ++void ps2_queue_noirq(PS2State *s, int b); ++void ps2_raise_irq(PS2State *s); + void ps2_queue(PS2State *s, int b); ++void ps2_queue_2(PS2State *s, int b1, int b2); ++void ps2_queue_3(PS2State *s, int b1, int b2, int b3); ++void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4); + void ps2_keyboard_set_translation(void *opaque, int mode); + void ps2_mouse_fake_event(void *opaque); + +-- +2.14.2 |