All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Arbuckle <programmingkidx@gmail.com>
To: eblake@redhat.com, qemu-devel@nongnu.org
Cc: John Arbuckle <programmingkidx@gmail.com>
Subject: [Qemu-devel] [PATCH 2/3] hid.c: convert to QKeyCode
Date: Thu, 30 Jun 2016 17:32:19 -0400	[thread overview]
Message-ID: <1467322340-25602-3-git-send-email-programmingkidx@gmail.com> (raw)
In-Reply-To: <1467322340-25602-1-git-send-email-programmingkidx@gmail.com>

Switches hid.c from PS/2 to QKeyCode support.

Signed-off-by: John Arbuckle <programmingkidx@gmail.com>
---
 hw/input/hid.c | 270 ++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 179 insertions(+), 91 deletions(-)

diff --git a/hw/input/hid.c b/hw/input/hid.c
index d92c746..3e1b46e 100644
--- a/hw/input/hid.c
+++ b/hw/input/hid.c
@@ -27,47 +27,144 @@
 #include "ui/console.h"
 #include "qemu/timer.h"
 #include "hw/input/hid.h"
+#include "include/hw/input/usb-keys.h"
+#include <math.h>
 
 #define HID_USAGE_ERROR_ROLLOVER        0x01
 #define HID_USAGE_POSTFAIL              0x02
 #define HID_USAGE_ERROR_UNDEFINED       0x03
 
-/* Indices are QEMU keycodes, values are from HID Usage Table.  Indices
- * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d.  */
-static const uint8_t hid_usage_keys[0x100] = {
-    0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
-    0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
-    0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
-    0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
-    0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
-    0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
-    0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
-    0xe2, 0x2c, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
-    0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
-    0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
-    0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x64, 0x44,
-    0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
-    0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
-
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
-    0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
-    0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
-    0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+#define RELEASED -1
+#define PUSHED -2
+
+/* Translates a QKeyCode to USB HID value */
+static const uint8_t qcode_to_usb_hid[] = {
+    [Q_KEY_CODE_SHIFT] = USB_HID_LEFT_SHIFT,
+    [Q_KEY_CODE_SHIFT_R] = USB_HID_RIGHT_SHIFT,
+    [Q_KEY_CODE_ALT] = USB_HID_LEFT_OPTION,
+    [Q_KEY_CODE_ALT_R] = USB_HID_RIGHT_OPTION,
+    [Q_KEY_CODE_ALTGR] = USB_HID_LEFT_OPTION,
+    [Q_KEY_CODE_ALTGR_R] = USB_HID_RIGHT_OPTION,
+    [Q_KEY_CODE_CTRL] = USB_HID_LEFT_CONTROL,
+    [Q_KEY_CODE_CTRL_R] = USB_HID_RIGHT_CONTROL,
+    [Q_KEY_CODE_MENU] = USB_HID_MENU,
+    [Q_KEY_CODE_ESC] = USB_HID_ESC,
+    [Q_KEY_CODE_1] = USB_HID_1,
+    [Q_KEY_CODE_2] = USB_HID_2,
+    [Q_KEY_CODE_3] = USB_HID_3,
+    [Q_KEY_CODE_4] = USB_HID_4,
+    [Q_KEY_CODE_5] = USB_HID_5,
+    [Q_KEY_CODE_6] = USB_HID_6,
+    [Q_KEY_CODE_7] = USB_HID_7,
+    [Q_KEY_CODE_8] = USB_HID_8,
+    [Q_KEY_CODE_9] = USB_HID_9,
+    [Q_KEY_CODE_0] = USB_HID_0,
+    [Q_KEY_CODE_MINUS] = USB_HID_MINUS,
+    [Q_KEY_CODE_EQUAL] = USB_HID_EQUALS,
+    [Q_KEY_CODE_BACKSPACE] = USB_HID_DELETE,
+    [Q_KEY_CODE_TAB] = USB_HID_TAB,
+    [Q_KEY_CODE_Q] = USB_HID_Q,
+    [Q_KEY_CODE_W] = USB_HID_W,
+    [Q_KEY_CODE_E] = USB_HID_E,
+    [Q_KEY_CODE_R] = USB_HID_R,
+    [Q_KEY_CODE_T] = USB_HID_T,
+    [Q_KEY_CODE_Y] = USB_HID_Y,
+    [Q_KEY_CODE_U] = USB_HID_U,
+    [Q_KEY_CODE_I] = USB_HID_I,
+    [Q_KEY_CODE_O] = USB_HID_O,
+    [Q_KEY_CODE_P] = USB_HID_P,
+    [Q_KEY_CODE_BRACKET_LEFT] = USB_HID_LEFT_BRACKET,
+    [Q_KEY_CODE_BRACKET_RIGHT] = USB_HID_RIGHT_BRACKET,
+    [Q_KEY_CODE_RET] = USB_HID_RETURN,
+    [Q_KEY_CODE_A] = USB_HID_A,
+    [Q_KEY_CODE_S] = USB_HID_S,
+    [Q_KEY_CODE_D] = USB_HID_D,
+    [Q_KEY_CODE_F] = USB_HID_F,
+    [Q_KEY_CODE_G] = USB_HID_G,
+    [Q_KEY_CODE_H] = USB_HID_H,
+    [Q_KEY_CODE_J] = USB_HID_J,
+    [Q_KEY_CODE_K] = USB_HID_K,
+    [Q_KEY_CODE_L] = USB_HID_L,
+    [Q_KEY_CODE_SEMICOLON] = USB_HID_SEMICOLON,
+    [Q_KEY_CODE_APOSTROPHE] = USB_HID_QUOTE,
+    [Q_KEY_CODE_GRAVE_ACCENT] = USB_HID_GRAVE_ACCENT,
+    [Q_KEY_CODE_BACKSLASH] = USB_HID_BACKSLASH,
+    [Q_KEY_CODE_Z] = USB_HID_Z,
+    [Q_KEY_CODE_X] = USB_HID_X,
+    [Q_KEY_CODE_C] = USB_HID_C,
+    [Q_KEY_CODE_V] = USB_HID_V,
+    [Q_KEY_CODE_B] = USB_HID_B,
+    [Q_KEY_CODE_N] = USB_HID_N,
+    [Q_KEY_CODE_M] = USB_HID_M,
+    [Q_KEY_CODE_COMMA] = USB_HID_COMMA,
+    [Q_KEY_CODE_DOT] = USB_HID_PERIOD,
+    [Q_KEY_CODE_SLASH] = USB_HID_FORWARD_SLASH,
+    [Q_KEY_CODE_ASTERISK] = USB_HID_KP_MULTIPLY,
+    [Q_KEY_CODE_SPC] = USB_HID_SPACE,
+    [Q_KEY_CODE_CAPS_LOCK] = USB_HID_CAPS_LOCK,
+    [Q_KEY_CODE_F1] = USB_HID_F1,
+    [Q_KEY_CODE_F2] = USB_HID_F2,
+    [Q_KEY_CODE_F3] = USB_HID_F3,
+    [Q_KEY_CODE_F4] = USB_HID_F4,
+    [Q_KEY_CODE_F5] = USB_HID_F5,
+    [Q_KEY_CODE_F6] = USB_HID_F6,
+    [Q_KEY_CODE_F7] = USB_HID_F7,
+    [Q_KEY_CODE_F8] = USB_HID_F8,
+    [Q_KEY_CODE_F9] = USB_HID_F9,
+    [Q_KEY_CODE_F10] = USB_HID_F10,
+    [Q_KEY_CODE_NUM_LOCK] = USB_HID_CLEAR,
+    [Q_KEY_CODE_SCROLL_LOCK] = USB_HID_SCROLL_LOCK,
+    [Q_KEY_CODE_KP_DIVIDE] = USB_HID_KP_DIVIDE,
+    [Q_KEY_CODE_KP_MULTIPLY] = USB_HID_KP_MULTIPLY,
+    [Q_KEY_CODE_KP_SUBTRACT] = USB_HID_KP_MINUS,
+    [Q_KEY_CODE_KP_ADD] = USB_HID_KP_ADD,
+    [Q_KEY_CODE_KP_ENTER] = USB_HID_KP_ENTER,
+    [Q_KEY_CODE_KP_DECIMAL] = USB_HID_KP_PERIOD,
+    [Q_KEY_CODE_SYSRQ] = USB_HID_PRINT,
+    [Q_KEY_CODE_KP_0] = USB_HID_KP_0,
+    [Q_KEY_CODE_KP_1] = USB_HID_KP_1,
+    [Q_KEY_CODE_KP_2] = USB_HID_KP_2,
+    [Q_KEY_CODE_KP_3] = USB_HID_KP_3,
+    [Q_KEY_CODE_KP_4] = USB_HID_KP_4,
+    [Q_KEY_CODE_KP_5] = USB_HID_KP_5,
+    [Q_KEY_CODE_KP_6] = USB_HID_KP_6,
+    [Q_KEY_CODE_KP_7] = USB_HID_KP_7,
+    [Q_KEY_CODE_KP_8] = USB_HID_KP_8,
+    [Q_KEY_CODE_KP_9] = USB_HID_KP_9,
+    [Q_KEY_CODE_LESS] = 0,
+    [Q_KEY_CODE_F11] = USB_HID_F11,
+    [Q_KEY_CODE_F12] = USB_HID_F12,
+    [Q_KEY_CODE_PRINT] = USB_HID_PRINT,
+    [Q_KEY_CODE_HOME] = USB_HID_HOME,
+    [Q_KEY_CODE_PGUP] = USB_HID_PAGE_UP,
+    [Q_KEY_CODE_PGDN] = USB_HID_PAGE_DOWN,
+    [Q_KEY_CODE_END] = USB_HID_END,
+    [Q_KEY_CODE_LEFT] = USB_HID_LEFT_ARROW,
+    [Q_KEY_CODE_UP] = USB_HID_UP_ARROW,
+    [Q_KEY_CODE_DOWN] = USB_HID_DOWN_ARROW,
+    [Q_KEY_CODE_RIGHT] = USB_HID_RIGHT_ARROW,
+    [Q_KEY_CODE_INSERT] = USB_HID_INSERT,
+    [Q_KEY_CODE_DELETE] = USB_HID_FORWARD_DELETE,
+    [Q_KEY_CODE_STOP] = USB_HID_STOP,
+    [Q_KEY_CODE_AGAIN] = USB_HID_AGAIN,
+    [Q_KEY_CODE_PROPS] = 0,
+    [Q_KEY_CODE_UNDO] = USB_HID_UNDO,
+    [Q_KEY_CODE_FRONT] = 0,
+    [Q_KEY_CODE_COPY] = USB_HID_COPY,
+    [Q_KEY_CODE_OPEN] = 0,
+    [Q_KEY_CODE_PASTE] = USB_HID_PASTE,
+    [Q_KEY_CODE_FIND] = USB_HID_FIND,
+    [Q_KEY_CODE_CUT] = USB_HID_CUT,
+    [Q_KEY_CODE_LF] = 0,
+    [Q_KEY_CODE_HELP] = USB_HID_HELP,
+    [Q_KEY_CODE_META_L] = USB_HID_LEFT_GUI,
+    [Q_KEY_CODE_META_R] = USB_HID_RIGHT_GUI,
+    [Q_KEY_CODE_COMPOSE] = 0,
+    [Q_KEY_CODE_PAUSE] = USB_HID_PAUSE,
+    [Q_KEY_CODE_RO] = 0,
+    [Q_KEY_CODE_KP_COMMA] = USB_HID_KP_COMMA,
+    [Q_KEY_CODE_KP_EQUALS] = USB_HID_KP_EQUALS,
+    [Q_KEY_CODE_POWER] = USB_HID_POWER,
 };
 
 bool hid_has_events(HIDState *hs)
@@ -227,12 +324,22 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
 {
     HIDState *hs = (HIDState *)dev;
     int scancodes[3], i, count;
-    int slot;
-    InputKeyEvent *key = evt->u.key.data;
+    int slot, qcode, keycode;
+
+    qcode = qemu_input_key_value_to_qcode(evt->u.key.data->key);
+    if (qcode >= ARRAY_SIZE(qcode_to_usb_hid)) {
+        return;
+    }
+    keycode = qcode_to_usb_hid[qcode];
+
+    count = 2;
+    if (evt->u.key.data->down == false) { /* if key up event */
+        scancodes[0] = RELEASED;
+    } else {
+        scancodes[0] = PUSHED;
+    }
+    scancodes[1] = keycode;
 
-    count = qemu_input_key_value_to_scancode(key->key,
-                                             key->down,
-                                             scancodes);
     if (hs->n + count > QUEUE_LENGTH) {
         fprintf(stderr, "usb-kbd: warning: key event queue full\n");
         return;
@@ -244,67 +351,47 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
     hs->event(hs);
 }
 
+/* Sets the modifiers variable */
+static void set_modifiers(int status, int bit_position, uint16_t *modifiers)
+{
+    int value = pow(2, bit_position);
+    if (status == PUSHED) {
+        *modifiers |= value;
+    }  else {
+        *modifiers &= ~value;
+    }
+}
+
+/* Handles the modifier keys - they are handled differently from other keys. */
+static void process_modifier_key(int status, int keycode, uint16_t *modifiers)
+{
+    /* subtracting 0xe0 from the keycode gives us the bit position */
+    set_modifiers(status, keycode - 0xe0, modifiers);
+}
+
 static void hid_keyboard_process_keycode(HIDState *hs)
 {
-    uint8_t hid_code, index, key;
-    int i, keycode, slot;
+    int i, keycode, slot, status;
 
     if (hs->n == 0) {
         return;
     }
     slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
+    status = hs->kbd.keycodes[slot];
+    slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
     keycode = hs->kbd.keycodes[slot];
 
-    key = keycode & 0x7f;
-    index = key | ((hs->kbd.modifiers & (1 << 8)) >> 1);
-    hid_code = hid_usage_keys[index];
-    hs->kbd.modifiers &= ~(1 << 8);
-
-    switch (hid_code) {
-    case 0x00:
-        return;
-
-    case 0xe0:
-        assert(key == 0x1d);
-        if (hs->kbd.modifiers & (1 << 9)) {
-            /* 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;
-        }
-        /* 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);
+    /* handle Control, Option, GUI/Windows/Command, and Shift keys */
+    if (keycode >= 0xe0) {
+        process_modifier_key(status, keycode, &(hs->kbd.modifiers));
         return;
-
-    case 0xea ... 0xef:
-        abort();
-
-    default:
-        break;
     }
 
-    if (keycode & (1 << 7)) {
+    /* if key released */
+    if (status == RELEASED) {
+        /* find the key then remove it from the buffer */
         for (i = hs->kbd.keys - 1; i >= 0; i--) {
-            if (hs->kbd.key[i] == hid_code) {
+            if (hs->kbd.key[i] == keycode) {
                 hs->kbd.key[i] = hs->kbd.key[-- hs->kbd.keys];
                 hs->kbd.key[hs->kbd.keys] = 0x00;
                 break;
@@ -314,14 +401,15 @@ static void hid_keyboard_process_keycode(HIDState *hs)
             return;
         }
     } else {
+        /* search for the key's location in the buffer */
         for (i = hs->kbd.keys - 1; i >= 0; i--) {
-            if (hs->kbd.key[i] == hid_code) {
+            if (hs->kbd.key[i] == keycode) {
                 break;
             }
         }
         if (i < 0) {
             if (hs->kbd.keys < sizeof(hs->kbd.key)) {
-                hs->kbd.key[hs->kbd.keys++] = hid_code;
+                hs->kbd.key[hs->kbd.keys++] = keycode;
             }
         } else {
             return;
-- 
2.5.0

  parent reply	other threads:[~2016-06-30 21:34 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-30 21:32 [Qemu-devel] [PATCH 0/3] Switch USB HID to QKeyCode John Arbuckle
2016-06-30 21:32 ` [Qemu-devel] [PATCH 1/3] usb-keys.h: initial commit John Arbuckle
2016-06-30 21:32 ` John Arbuckle [this message]
2016-06-30 21:32 ` [Qemu-devel] [PATCH 3/3] hid.c: Add debug support John Arbuckle
2016-07-01 14:44   ` Eric Blake
  -- strict thread matches above, loose matches on Subject: below --
2016-03-25 16:09 [Qemu-devel] [PATCH 2/3] hid.c: convert to QKeyCode Programmingkid

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1467322340-25602-3-git-send-email-programmingkidx@gmail.com \
    --to=programmingkidx@gmail.com \
    --cc=eblake@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.