From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47522) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZEwM1-0006E9-Kd for qemu-devel@nongnu.org; Tue, 14 Jul 2015 05:18:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZEwLw-0007zI-Jr for qemu-devel@nongnu.org; Tue, 14 Jul 2015 05:18:21 -0400 Received: from mail-wi0-x229.google.com ([2a00:1450:400c:c05::229]:35893) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZEwLw-0007yy-Cc for qemu-devel@nongnu.org; Tue, 14 Jul 2015 05:18:16 -0400 Received: by widjy10 with SMTP id jy10so93284257wid.1 for ; Tue, 14 Jul 2015 02:18:15 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Tue, 14 Jul 2015 11:18:06 +0200 Message-Id: <1436865486-22930-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH] hid: clarify hid_keyboard_process_keycode List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kraxel@redhat.com Coverity thinks the fallthroughs are smelly. They are correct, but everything else in this function is like "wut?". Refer explicitly to bits 8 and 9 of hs->kbd.modifiers instead of shifting right first and using (1 << 7). Document what the scancode is when hid_code is 0xe0. And add plenty of comments. Signed-off-by: Paolo Bonzini --- hw/input/hid.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/hw/input/hid.c b/hw/input/hid.c index 6841cb8..21ebd9e 100644 --- a/hw/input/hid.c +++ b/hw/input/hid.c @@ -239,7 +239,7 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src, static void hid_keyboard_process_keycode(HIDState *hs) { - uint8_t hid_code, key; + uint8_t hid_code, index, key; int i, keycode, slot; if (hs->n == 0) { @@ -249,7 +249,8 @@ static void hid_keyboard_process_keycode(HIDState *hs) keycode = hs->kbd.keycodes[slot]; key = keycode & 0x7f; - hid_code = hid_usage_keys[key | ((hs->kbd.modifiers >> 1) & (1 << 7))]; + index = key | ((hs->kbd.modifiers & (1 << 8)) >> 1); + hid_code = hid_usage_keys[index]; hs->kbd.modifiers &= ~(1 << 8); switch (hid_code) { @@ -257,18 +258,41 @@ static void hid_keyboard_process_keycode(HIDState *hs) return; case 0xe0: + assert(key == 0x1d); if (hs->kbd.modifiers & (1 << 9)) { - hs->kbd.modifiers ^= 3 << 8; + /* The hid_codes for the 0xe1/0x1d scancode sequence are 0xe9/0xe0. + * Here we're processing the second hid_code. By dropping bit 9 + * and setting bit 8, the scancode after 0x1d will access the + * second half of the table. + */ + hs->kbd.modifiers ^= (1 << 8) | (1 << 9); return; } + /* fall through to process Ctrl_L */ case 0xe1 ... 0xe7: + /* Ctrl_L/Ctrl_R, Shift_L/Shift_R, Alt_L/Alt_R, Win_L/Win_R. + * Handle releases here, or fall through to process presses. + */ if (keycode & (1 << 7)) { hs->kbd.modifiers &= ~(1 << (hid_code & 0x0f)); return; } - case 0xe8 ... 0xef: + /* fall through */ + case 0xe8 ... 0xe9: + /* USB modifiers are just 1 byte long. Bits 8 and 9 of + * hs->kbd.modifiers implement a state machine that detects the + * 0xe0 and 0xe1/0x1d sequences. These bits do not follow the + * usual rules where bit 7 marks released keys; they are cleared + * elsewhere in the function as the state machine dictates. + */ hs->kbd.modifiers |= 1 << (hid_code & 0x0f); return; + + case 0xea ... 0xef: + abort(); + + default: + break; } if (keycode & (1 << 7)) { -- 2.4.3