From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=49951 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PhPJo-0001u6-AX for qemu-devel@nongnu.org; Mon, 24 Jan 2011 11:31:05 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PhPJm-0000SA-UE for qemu-devel@nongnu.org; Mon, 24 Jan 2011 11:31:04 -0500 Received: from mx1.redhat.com ([209.132.183.28]:14994) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PhPJm-0000Rp-Ce for qemu-devel@nongnu.org; Mon, 24 Jan 2011 11:31:02 -0500 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id p0OGV1Nh025676 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 24 Jan 2011 11:31:01 -0500 From: Gerd Hoffmann Date: Mon, 24 Jan 2011 17:30:49 +0100 Message-Id: <1295886655-32312-3-git-send-email-kraxel@redhat.com> In-Reply-To: <1295886655-32312-1-git-send-email-kraxel@redhat.com> References: <1295886655-32312-1-git-send-email-kraxel@redhat.com> Subject: [Qemu-devel] [PATCH 2/8] usb keyboard: add event event queue List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Gerd Hoffmann This patch adds a event queue to the usb keyboard. This makes sure the guest will see all key events even if they come in bursts. With this patch applied sending Ctrl-Alt-Del using vncviewer's F8 menu works. Also with autosuspend enabled the first keypress on a suspended keyboard takes a little longer to be delivered to the guest because the usb bus must be resumed first. Without event queue this easily gets lost. Signed-off-by: Gerd Hoffmann --- hw/usb-hid.c | 38 ++++++++++++++++++++++++++++++++------ 1 files changed, 32 insertions(+), 6 deletions(-) diff --git a/hw/usb-hid.c b/hw/usb-hid.c index ea49543..5f1451b 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -63,6 +63,9 @@ typedef struct USBMouseState { } USBMouseState; typedef struct USBKeyboardState { + uint32_t keycodes[QUEUE_LENGTH]; + uint32_t head; /* index into circular queue */ + uint32_t n; uint16_t modifiers; uint8_t leds; uint8_t key[16]; @@ -494,8 +497,27 @@ static void usb_keyboard_event(void *opaque, int keycode) { USBHIDState *hs = opaque; USBKeyboardState *s = &hs->kbd; + int slot; + + if (s->n == QUEUE_LENGTH) { + fprintf(stderr, "usb-kbd: warning: key event queue full\n"); + return; + } + slot = (s->head + s->n) & QUEUE_MASK; s->n++; + s->keycodes[slot] = keycode; + usb_hid_changed(hs); +} + +static void usb_keyboard_process_keycode(USBKeyboardState *s) +{ uint8_t hid_code, key; - int i; + int i, keycode, slot; + + if (s->n == 0) { + return; + } + slot = s->head & QUEUE_MASK; QUEUE_INCR(s->head); s->n--; + keycode = s->keycodes[slot]; key = keycode & 0x7f; hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))]; @@ -528,7 +550,6 @@ static void usb_keyboard_event(void *opaque, int keycode) if (s->key[i] == hid_code) { s->key[i] = s->key[-- s->keys]; s->key[s->keys] = 0x00; - usb_hid_changed(hs); break; } if (i < 0) @@ -543,8 +564,6 @@ static void usb_keyboard_event(void *opaque, int keycode) } else return; } - - usb_hid_changed(hs); } static inline int int_clamp(int val, int vmin, int vmax) @@ -645,6 +664,8 @@ static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len) if (len < 2) return 0; + usb_keyboard_process_keycode(s); + buf[0] = s->modifiers & 0xff; buf[1] = 0; if (s->keys > 6) @@ -680,7 +701,7 @@ static void usb_mouse_handle_reset(USBDevice *dev) { USBHIDState *s = (USBHIDState *)dev; - memset (s->ptr.queue, 0, sizeof (s->ptr.queue)); + memset(s->ptr.queue, 0, sizeof (s->ptr.queue)); s->ptr.head = 0; s->ptr.n = 0; s->protocol = 1; @@ -691,6 +712,11 @@ static void usb_keyboard_handle_reset(USBDevice *dev) USBHIDState *s = (USBHIDState *)dev; qemu_add_kbd_event_handler(usb_keyboard_event, s); + memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes)); + s->kbd.head = 0; + s->kbd.n = 0; + memset(s->kbd.key, 0, sizeof (s->kbd.key)); + s->kbd.keys = 0; s->protocol = 1; } @@ -800,7 +826,7 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p) } else if (s->kind == USB_KEYBOARD) { ret = usb_keyboard_poll(s, p->data, p->len); - s->changed = 0; + s->changed = s->kbd.n > 0; } } else { goto fail; -- 1.7.1