[SeaBIOS] [PATCH 08/10] usb-hid: Generate Ctrl+Break and Alt+SysReq keys

Kevin O'Connor kevin at koconnor.net
Mon Sep 5 20:36:09 CEST 2016


Detect the sequences for generating Ctrl+Break and Alt+SysReq on USB
keyboards and produce the appropriate legacy scancodes.

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 src/hw/usb-hid.c | 50 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 30 insertions(+), 20 deletions(-)

diff --git a/src/hw/usb-hid.c b/src/hw/usb-hid.c
index 09a6cf4..fa4d9a2 100644
--- a/src/hw/usb-hid.c
+++ b/src/hw/usb-hid.c
@@ -149,7 +149,7 @@ static u16 KeyToScanCode[] VAR16 = {
     0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
     0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
     0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
-    0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
+    0xe145, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
     0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
     0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
     0x0048, 0x0049, 0x0052, 0x0053
@@ -172,42 +172,52 @@ struct keyevent {
 
 // Translate data from KeyToScanCode[] to calls to process_key().
 static void
-prockeys(u16 keys)
+prockeys(u16 scancode, u8 key_release, u8 mods)
 {
-    if (keys > 0xff) {
-        u8 key = keys>>8;
-        if (key == 0xe1) {
-            // Pause key
-            process_key(0xe1);
-            process_key(0x1d | (keys & RELEASEBIT));
-            process_key(0x45 | (keys & RELEASEBIT));
+    if (scancode > 0xff) {
+        if (scancode == 0xe145) {
+            // XXX - a real AT keyboard would immediately send the key release
+            if (mods & ((1<<0) | (1<<4))) {
+                // Cntr+Break key
+                process_key(0xe0);
+                process_key(0x46 | key_release);
+            } else {
+                // Pause key
+                process_key(0xe1);
+                process_key(0x1d | key_release);
+                process_key(0x45 | key_release);
+            }
+            return;
+        } else if (scancode == 0xe037 && mods & ((1<<2) | (1<<6))) {
+            // Alt+SysReq key
+            process_key(0x54 | key_release);
             return;
         }
-        process_key(key);
+        process_key(0xe0);
     }
-    process_key(keys);
+    process_key(scancode | key_release);
 }
 
 // Handle a USB key press/release event.
 static void
-procscankey(u8 key, u8 flags)
+procscankey(u8 key, u8 key_release, u8 mods)
 {
     if (key >= ARRAY_SIZE(KeyToScanCode))
         return;
-    u16 keys = GET_GLOBAL(KeyToScanCode[key]);
-    if (keys)
-        prockeys(keys | flags);
+    u16 scancode = GET_GLOBAL(KeyToScanCode[key]);
+    if (scancode)
+        prockeys(scancode, key_release, mods);
 }
 
 // Handle a USB modifier press/release event.
 static void
-procmodkey(u8 mods, u8 flags)
+procmodkey(u8 mods, u8 key_release)
 {
     int i;
     for (i=0; mods; i++)
         if (mods & (1<<i)) {
             // Modifier key change.
-            prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
+            prockeys(GET_GLOBAL(ModifierToScanCode[i]), key_release, 0);
             mods &= ~(1<<i);
         }
 }
@@ -245,7 +255,7 @@ handle_key(struct keyevent *data)
         for (j=0;; j++) {
             if (j>=ARRAY_SIZE(data->keys)) {
                 // Key released.
-                procscankey(key, RELEASEBIT);
+                procscankey(key, RELEASEBIT, data->modifiers);
                 if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
                     // Last pressed key released - disable repeat.
                     old.repeatcount = 0xff;
@@ -269,7 +279,7 @@ handle_key(struct keyevent *data)
         if (!key)
             continue;
         // New key pressed.
-        procscankey(key, 0);
+        procscankey(key, 0, data->modifiers);
         old.keys[addpos++] = key;
         old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
     }
@@ -279,7 +289,7 @@ handle_key(struct keyevent *data)
     // Check for key repeat event.
     if (addpos) {
         if (!old.repeatcount)
-            procscankey(old.keys[addpos-1], 0);
+            procscankey(old.keys[addpos-1], 0, data->modifiers);
         else if (old.repeatcount != 0xff)
             old.repeatcount--;
     }
-- 
2.5.5




More information about the SeaBIOS mailing list