mirror of https://github.com/neutrinolabs/xrdp
Add initial scancode module
This commit is contained in:
parent
c12c475e04
commit
b0cfc1a12b
|
@ -59,6 +59,8 @@ libcommon_la_SOURCES = \
|
||||||
parse.c \
|
parse.c \
|
||||||
parse.h \
|
parse.h \
|
||||||
rail.h \
|
rail.h \
|
||||||
|
scancode.c \
|
||||||
|
scancode.h \
|
||||||
ssl_calls.c \
|
ssl_calls.c \
|
||||||
ssl_calls.h \
|
ssl_calls.h \
|
||||||
string_calls.c \
|
string_calls.c \
|
||||||
|
|
|
@ -0,0 +1,421 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2022 Matt Burt, all xrdp contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file common/scancode.c
|
||||||
|
* @brief Scancode handling
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
#include <config_ac.h>
|
||||||
|
#endif
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "scancode.h"
|
||||||
|
|
||||||
|
struct scancode_to_keycode
|
||||||
|
{
|
||||||
|
unsigned short scancode; // 0x1xx implies an extended key
|
||||||
|
unsigned char keycode;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
|
||||||
|
|
||||||
|
// Sources:-
|
||||||
|
// file:/usr/share/X11/xkb/keycodes/evdev
|
||||||
|
// https://wiki.osdev.org/PS/2_Keyboard
|
||||||
|
// https://www.kbdlayout.info/
|
||||||
|
static const struct scancode_to_keycode
|
||||||
|
evdev_scancode_to_keycode_map[] =
|
||||||
|
{
|
||||||
|
// Virtual XKB
|
||||||
|
// Key (US) Symbol
|
||||||
|
// -------- ------
|
||||||
|
{ 0x001, 9 }, // VK_ESCAPE ESC
|
||||||
|
{ 0x002, 10 }, // VK_1 AE01
|
||||||
|
{ 0x003, 11 }, // VK_2 AE02
|
||||||
|
{ 0x004, 12 }, // VK_3 AE03
|
||||||
|
{ 0x005, 13 }, // VK_4 AE04
|
||||||
|
{ 0x006, 14 }, // VK_5 AE05
|
||||||
|
{ 0x007, 15 }, // VK_6 AE06
|
||||||
|
{ 0x008, 16 }, // VK_7 AE07
|
||||||
|
{ 0x009, 17 }, // VK_8 AE08
|
||||||
|
{ 0x00a, 18 }, // VK_9 AE09
|
||||||
|
{ 0x00b, 19 }, // VK_0 AE10
|
||||||
|
{ 0x00c, 20 }, // VK_OEM_MINUS AE11
|
||||||
|
{ 0x00d, 21 }, // VK_OEM_PLUS AE12
|
||||||
|
{ 0x00e, 22 }, // VK_BACK BKSP
|
||||||
|
{ 0x00f, 23 }, // VK_TAB TAB
|
||||||
|
{ 0x010, 24 }, // VK_Q AD01
|
||||||
|
{ 0x011, 25 }, // VK_W AD02
|
||||||
|
{ 0x012, 26 }, // VK_E AD03
|
||||||
|
{ 0x013, 27 }, // VK_R AD04
|
||||||
|
{ 0x014, 28 }, // VK_T AD05
|
||||||
|
{ 0x015, 29 }, // VK_Y AD06
|
||||||
|
{ 0x016, 30 }, // VK_U AD07
|
||||||
|
{ 0x017, 31 }, // VK_I AD08
|
||||||
|
{ 0x018, 32 }, // VK_O AD09
|
||||||
|
{ 0x019, 33 }, // VK_P AD10
|
||||||
|
{ 0x01a, 34 }, // VK_OEM_4 AD11
|
||||||
|
{ 0x01b, 35 }, // VK_OEM_6 AD12
|
||||||
|
{ 0x01c, 36 }, // VK_RETURN RTRN
|
||||||
|
{ 0x01d, 37 }, // VK_LCONTROL LCTL
|
||||||
|
{ 0x01e, 38 }, // VK_A AC01
|
||||||
|
{ 0x01f, 39 }, // VK_S AC02
|
||||||
|
{ 0x020, 40 }, // VK_D AC03
|
||||||
|
{ 0x021, 41 }, // VK_F AC04
|
||||||
|
{ 0x022, 42 }, // VK_G AC05
|
||||||
|
{ 0x023, 43 }, // VK_H AC06
|
||||||
|
{ 0x024, 44 }, // VK_J AC07
|
||||||
|
{ 0x025, 45 }, // VK_K AC08
|
||||||
|
{ 0x026, 46 }, // VK_L AC09
|
||||||
|
{ 0x027, 47 }, // VK_OEM_1 AC10
|
||||||
|
{ 0x028, 48 }, // VK_OEM_7 AC11
|
||||||
|
{ 0x029, 49 }, // VK_OEM_3 TLDE
|
||||||
|
{ 0x02a, 50 }, // VK_LSHIFT LFSH
|
||||||
|
{ 0x02b, 51 }, // VK_OEM_5 BKSL
|
||||||
|
{ 0x02c, 52 }, // VK_Z AB01
|
||||||
|
{ 0x02d, 53 }, // VK_X AB02
|
||||||
|
{ 0x02e, 54 }, // VK_C AB03
|
||||||
|
{ 0x02f, 55 }, // VK_V AB04
|
||||||
|
{ 0x030, 56 }, // VK_B AB05
|
||||||
|
{ 0x031, 57 }, // VK_N AB06
|
||||||
|
{ 0x032, 58 }, // VK_M AB07
|
||||||
|
{ 0x033, 59 }, // VK_OEM_COMMA AB08
|
||||||
|
{ 0x034, 60 }, // VK_OEM_PERIOD AB09
|
||||||
|
{ 0x035, 61 }, // VK_OEM_2 AB10
|
||||||
|
{ 0x036, 62 }, // VK_RSHIFT RTSH
|
||||||
|
{ 0x037, 63 }, // VK_MULTIPLY KPMU
|
||||||
|
{ 0x038, 64 }, // VK_LMENU LALT
|
||||||
|
{ 0x039, 65 }, // VK_SPACE SPCE
|
||||||
|
{ 0x03a, 66 }, // VK_CAPITAL CAPS
|
||||||
|
{ 0x03b, 67 }, // VK_F1 FK01
|
||||||
|
{ 0x03c, 68 }, // VK_F2 FK02
|
||||||
|
{ 0x03d, 69 }, // VK_F3 FK03
|
||||||
|
{ 0x03e, 70 }, // VK_F4 FK04
|
||||||
|
{ 0x03f, 71 }, // VK_F5 FK05
|
||||||
|
{ 0x040, 72 }, // VK_F6 FK06
|
||||||
|
{ 0x041, 73 }, // VK_F7 FK07
|
||||||
|
{ 0x042, 74 }, // VK_F8 FK08
|
||||||
|
{ 0x043, 75 }, // VK_F9 FK09
|
||||||
|
{ 0x044, 76 }, // VK_F10 FK10
|
||||||
|
{ 0x045, 77 }, // VK_NUMLOCK NMLK
|
||||||
|
{ 0x046, 78 }, // VK_SCROLL SCLK
|
||||||
|
{ 0x047, 79 }, // VK_HOME KP7
|
||||||
|
{ 0x048, 80 }, // VK_UP KP8
|
||||||
|
{ 0x049, 81 }, // VK_PRIOR KP9
|
||||||
|
{ 0x04a, 82 }, // VK_SUBTRACT KPSU
|
||||||
|
{ 0x04b, 83 }, // VK_LEFT KP4
|
||||||
|
{ 0x04c, 84 }, // VK_CLEAR KP5
|
||||||
|
{ 0x04d, 85 }, // VK_RIGHT KP6
|
||||||
|
{ 0x04e, 86 }, // VK_ADD KPAD
|
||||||
|
{ 0x04f, 87 }, // VK_END KP1
|
||||||
|
{ 0x050, 88 }, // VK_DOWN KP2
|
||||||
|
{ 0x051, 89 }, // VK_NEXT KP3
|
||||||
|
{ 0x052, 90 }, // VK_INSERT KP0
|
||||||
|
{ 0x053, 91 }, // VK_DELETE KPDL
|
||||||
|
{ 0x056, 94 }, // VK_OEM_102 LSGT
|
||||||
|
{ 0x057, 95 }, // VK_F11 FK11
|
||||||
|
{ 0x058, 96 }, // VK_F12 FK12
|
||||||
|
{ 0x070, 101 }, // - HKTG
|
||||||
|
{ 0x073, 97 }, // VK_ABNT_C1 AB11
|
||||||
|
{ 0x079, 100 }, // - HENK
|
||||||
|
{ 0x07b, 102 }, // VK_OEM_PA1 MUHE
|
||||||
|
{ 0x07d, 132 }, // - AE13
|
||||||
|
{ 0x110, 173 }, // VK_MEDIA_PREV_TRACK I173 (KEY_PREVIOUSSONG)
|
||||||
|
{ 0x119, 171 }, // VK_MEDIA_NEXT_TRACK I171 (KEY_NEXTSONG)
|
||||||
|
{ 0x11c, 104 }, // VK_RETURN KPEN
|
||||||
|
{ 0x11d, 105 }, // VK_RCONTROL RCTL
|
||||||
|
{ 0x120, 121 }, // VK_VOLUME_MUTE MUTE
|
||||||
|
{ 0x121, 148 }, // VK_LAUNCH_APP2 I148 (KEY_CALC)
|
||||||
|
{ 0x122, 172 }, // VK_PLAY_PAUSE I172 (KEY_PLAYPAUSE)
|
||||||
|
{ 0x124, 174 }, // VK_MEDIA_STOP I174 (KEY_STOPCD)
|
||||||
|
{ 0x12e, 122 }, // VK_VOLUME_DOWN VOL-
|
||||||
|
{ 0x130, 123 }, // VK_VOLUME_UP VOL+
|
||||||
|
{ 0x132, 180 }, // VK_BROWSER_HOME I180 (KEY_HOMEPAGE)
|
||||||
|
{ 0x135, 106 }, // VK_DIVIDE KPDV
|
||||||
|
{ 0x137, 107 }, // VK_SNAPSHOT PRSC
|
||||||
|
{ 0x138, 108 }, // VK_RMENU RALT
|
||||||
|
{ 0x147, 110 }, // VK_HOME HOME
|
||||||
|
{ 0x148, 111 }, // VK_UP UP
|
||||||
|
{ 0x149, 112 }, // VK_PRIOR PGUP (KEY_COMPUTER)
|
||||||
|
{ 0x14b, 113 }, // VK_LEFT LEFT
|
||||||
|
{ 0x14d, 114 }, // VK_RIGHT RGHT
|
||||||
|
{ 0x14f, 115 }, // VK_END END
|
||||||
|
{ 0x150, 116 }, // VK_DOWN DOWN
|
||||||
|
{ 0x151, 117 }, // VK_NEXT PGDN
|
||||||
|
{ 0x152, 118 }, // VK_INSERT INS
|
||||||
|
{ 0x153, 119 }, // VK_DELETE DELE
|
||||||
|
{ 0x15b, 133 }, // VK_LWIN LWIN
|
||||||
|
{ 0x15c, 134 }, // VK_RWIN RWIN
|
||||||
|
{ 0x15d, 135 }, // VK_APPS COMP
|
||||||
|
{ 0x165, 225 }, // VK_BROWSER_SEARCH I225 (KEY_SEARCH)
|
||||||
|
{ 0x166, 164 }, // VK_BROWSER_FAVORITES I164 (KEY_BOOKMARKS)
|
||||||
|
{ 0x16b, 165 }, // VK_LAUNCH_APP1 I165 (KEY_COMPUTER)
|
||||||
|
{ 0x16c, 163 } // VK_LAUNCH_MAIL I163 (KEY_MAIL)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sources:-
|
||||||
|
// file:/usr/share/X11/xkb/keycodes/xfree86
|
||||||
|
// https://wiki.osdev.org/PS/2_Keyboard
|
||||||
|
// https://www.kbdlayout.info/
|
||||||
|
static const struct scancode_to_keycode
|
||||||
|
base_scancode_to_keycode_map[] =
|
||||||
|
{
|
||||||
|
// Virtual XKB
|
||||||
|
// Key (US) Symbol
|
||||||
|
// -------- ------
|
||||||
|
{ 0x001, 9 }, // VK_ESCAPE ESC
|
||||||
|
{ 0x002, 10 }, // VK_1 AE01
|
||||||
|
{ 0x003, 11 }, // VK_2 AE02
|
||||||
|
{ 0x004, 12 }, // VK_3 AE03
|
||||||
|
{ 0x005, 13 }, // VK_4 AE04
|
||||||
|
{ 0x006, 14 }, // VK_5 AE05
|
||||||
|
{ 0x007, 15 }, // VK_6 AE06
|
||||||
|
{ 0x008, 16 }, // VK_7 AE07
|
||||||
|
{ 0x009, 17 }, // VK_8 AE08
|
||||||
|
{ 0x00a, 18 }, // VK_9 AE09
|
||||||
|
{ 0x00b, 19 }, // VK_0 AE10
|
||||||
|
{ 0x00c, 20 }, // VK_OEM_MINUS AE11
|
||||||
|
{ 0x00d, 21 }, // VK_OEM_PLUS AE12
|
||||||
|
{ 0x00e, 22 }, // VK_BACK BKSP
|
||||||
|
{ 0x00f, 23 }, // VK_TAB TAB
|
||||||
|
{ 0x010, 24 }, // VK_Q AD01
|
||||||
|
{ 0x011, 25 }, // VK_W AD02
|
||||||
|
{ 0x012, 26 }, // VK_E AD03
|
||||||
|
{ 0x013, 27 }, // VK_R AD04
|
||||||
|
{ 0x014, 28 }, // VK_T AD05
|
||||||
|
{ 0x015, 29 }, // VK_Y AD06
|
||||||
|
{ 0x016, 30 }, // VK_U AD07
|
||||||
|
{ 0x017, 31 }, // VK_I AD08
|
||||||
|
{ 0x018, 32 }, // VK_O AD09
|
||||||
|
{ 0x019, 33 }, // VK_P AD10
|
||||||
|
{ 0x01a, 34 }, // VK_OEM_4 AD11
|
||||||
|
{ 0x01b, 35 }, // VK_OEM_6 AD12
|
||||||
|
{ 0x01c, 36 }, // VK_RETURN RTRN
|
||||||
|
{ 0x01d, 37 }, // VK_LCONTROL LCTL
|
||||||
|
{ 0x01e, 38 }, // VK_A AC01
|
||||||
|
{ 0x01f, 39 }, // VK_S AC02
|
||||||
|
{ 0x020, 40 }, // VK_D AC03
|
||||||
|
{ 0x021, 41 }, // VK_F AC04
|
||||||
|
{ 0x022, 42 }, // VK_G AC05
|
||||||
|
{ 0x023, 43 }, // VK_H AC06
|
||||||
|
{ 0x024, 44 }, // VK_J AC07
|
||||||
|
{ 0x025, 45 }, // VK_K AC08
|
||||||
|
{ 0x026, 46 }, // VK_L AC09
|
||||||
|
{ 0x027, 47 }, // VK_OEM_1 AC10
|
||||||
|
{ 0x028, 48 }, // VK_OEM_7 AC11
|
||||||
|
{ 0x029, 49 }, // VK_OEM_3 TLDE
|
||||||
|
{ 0x02a, 50 }, // VK_LSHIFT LFSH
|
||||||
|
{ 0x02b, 51 }, // VK_OEM_5 BKSL
|
||||||
|
{ 0x02c, 52 }, // VK_Z AB01
|
||||||
|
{ 0x02d, 53 }, // VK_X AB02
|
||||||
|
{ 0x02e, 54 }, // VK_C AB03
|
||||||
|
{ 0x02f, 55 }, // VK_V AB04
|
||||||
|
{ 0x030, 56 }, // VK_B AB05
|
||||||
|
{ 0x031, 57 }, // VK_N AB06
|
||||||
|
{ 0x032, 58 }, // VK_M AB07
|
||||||
|
{ 0x033, 59 }, // VK_OEM_COMMA AB08
|
||||||
|
{ 0x034, 60 }, // VK_OEM_PERIOD AB09
|
||||||
|
{ 0x035, 61 }, // VK_OEM_2 AB10
|
||||||
|
{ 0x036, 62 }, // VK_RSHIFT RTSH
|
||||||
|
{ 0x037, 63 }, // VK_MULTIPLY KPMU
|
||||||
|
{ 0x038, 64 }, // VK_LMENU LALT
|
||||||
|
{ 0x039, 65 }, // VK_SPACE SPCE
|
||||||
|
{ 0x03a, 66 }, // VK_CAPITAL CAPS
|
||||||
|
{ 0x03b, 67 }, // VK_F1 FK01
|
||||||
|
{ 0x03c, 68 }, // VK_F2 FK02
|
||||||
|
{ 0x03d, 69 }, // VK_F3 FK03
|
||||||
|
{ 0x03e, 70 }, // VK_F4 FK04
|
||||||
|
{ 0x03f, 71 }, // VK_F5 FK05
|
||||||
|
{ 0x040, 72 }, // VK_F6 FK06
|
||||||
|
{ 0x041, 73 }, // VK_F7 FK07
|
||||||
|
{ 0x042, 74 }, // VK_F8 FK08
|
||||||
|
{ 0x043, 75 }, // VK_F9 FK09
|
||||||
|
{ 0x044, 76 }, // VK_F10 FK10
|
||||||
|
{ 0x045, 77 }, // VK_NUMLOCK NMLK
|
||||||
|
{ 0x046, 78 }, // VK_SCROLL SCLK
|
||||||
|
{ 0x047, 79 }, // VK_HOME KP7
|
||||||
|
{ 0x048, 80 }, // VK_UP KP8
|
||||||
|
{ 0x049, 81 }, // VK_PRIOR KP9
|
||||||
|
{ 0x04a, 82 }, // VK_SUBTRACT KPSU
|
||||||
|
{ 0x04b, 83 }, // VK_LEFT KP4
|
||||||
|
{ 0x04c, 84 }, // VK_CLEAR KP5
|
||||||
|
{ 0x04d, 85 }, // VK_RIGHT KP6
|
||||||
|
{ 0x04e, 86 }, // VK_ADD KPAD
|
||||||
|
{ 0x04f, 87 }, // VK_END KP1
|
||||||
|
{ 0x050, 88 }, // VK_DOWN KP2
|
||||||
|
{ 0x051, 89 }, // VK_NEXT KP3
|
||||||
|
{ 0x052, 90 }, // VK_INSERT KP0
|
||||||
|
{ 0x053, 91 }, // VK_DELETE KPDL
|
||||||
|
{ 0x056, 94 }, // VK_OEM_102 LSGT
|
||||||
|
{ 0x057, 95 }, // VK_F11 FK11
|
||||||
|
{ 0x058, 96 }, // VK_F12 FK12
|
||||||
|
{ 0x070, 208 }, // - HKTG
|
||||||
|
{ 0x073, 211 }, // VK_ABNT_C1 AB11
|
||||||
|
{ 0x079, 129 }, // - XFER
|
||||||
|
{ 0x07b, 131 }, // VK_OEM_PA1 NFER
|
||||||
|
{ 0x07d, 133 }, // - AE13
|
||||||
|
{ 0x11c, 108 }, // VK_RETURN KPEN
|
||||||
|
{ 0x11d, 109 }, // VK_RCONTROL RCTL
|
||||||
|
{ 0x120, 141 }, // VK_VOLUME_MUTE MUTE
|
||||||
|
{ 0x12e, 142 }, // VK_VOLUME_DOWN VOL-
|
||||||
|
{ 0x130, 143 }, // VK_VOLUME_UP VOL+
|
||||||
|
{ 0x135, 112 }, // VK_DIVIDE KPDV
|
||||||
|
{ 0x137, 121 }, // VK_SNAPSHOT PRSC
|
||||||
|
{ 0x138, 113 }, // VK_RMENU RALT
|
||||||
|
{ 0x147, 97 }, // VK_HOME HOME
|
||||||
|
{ 0x148, 98 }, // VK_UP UP
|
||||||
|
{ 0x149, 99 }, // VK_PRIOR PGUP (KEY_COMPUTER)
|
||||||
|
{ 0x14b, 100 }, // VK_LEFT LEFT
|
||||||
|
{ 0x14d, 102 }, // VK_RIGHT RGHT
|
||||||
|
{ 0x14f, 103 }, // VK_END END
|
||||||
|
{ 0x150, 104 }, // VK_DOWN DOWN
|
||||||
|
{ 0x151, 105 }, // VK_NEXT PGDN
|
||||||
|
{ 0x152, 106 }, // VK_INSERT INS
|
||||||
|
{ 0x153, 107 }, // VK_DELETE DELE
|
||||||
|
{ 0x15b, 115 }, // VK_LWIN LWIN
|
||||||
|
{ 0x15c, 116 }, // VK_RWIN RWIN
|
||||||
|
{ 0x15d, 117 } // VK_APPS COMP
|
||||||
|
};
|
||||||
|
|
||||||
|
struct map_settings
|
||||||
|
{
|
||||||
|
const struct scancode_to_keycode *map;
|
||||||
|
const char *name;
|
||||||
|
unsigned int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum settings_index
|
||||||
|
{
|
||||||
|
SI_EVDEV = 0,
|
||||||
|
SI_BASE
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct map_settings global_settings[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// SI_EVDEV
|
||||||
|
.map = evdev_scancode_to_keycode_map,
|
||||||
|
.name = "evdev",
|
||||||
|
.size = ELEMENTS(evdev_scancode_to_keycode_map),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// SI_BASE
|
||||||
|
.map = base_scancode_to_keycode_map,
|
||||||
|
.name = "base",
|
||||||
|
.size = ELEMENTS(base_scancode_to_keycode_map)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Default mapping set is "evdev"
|
||||||
|
const struct map_settings *settings = &global_settings[SI_EVDEV];
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
unsigned short
|
||||||
|
scancode_to_keycode(unsigned short scancode)
|
||||||
|
{
|
||||||
|
unsigned int min = 0;
|
||||||
|
unsigned int max = settings->size;
|
||||||
|
unsigned short rv = 0;
|
||||||
|
|
||||||
|
// Check scancode is in range of map
|
||||||
|
if (scancode >= settings->map[min].scancode &&
|
||||||
|
scancode <= settings->map[max - 1].scancode)
|
||||||
|
{
|
||||||
|
// Use a binary chop to locate the correct index
|
||||||
|
// in logarithmic time.
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
unsigned int index = (min + max) / 2;
|
||||||
|
if (scancode == settings->map[index].scancode)
|
||||||
|
{
|
||||||
|
rv = settings->map[index].keycode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Adjust min or max, checking for end
|
||||||
|
// of iteration
|
||||||
|
if (scancode < settings->map[index].scancode)
|
||||||
|
{
|
||||||
|
max = index;
|
||||||
|
}
|
||||||
|
else if (min == index)
|
||||||
|
{
|
||||||
|
// We've already checked this value
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
min = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
unsigned short
|
||||||
|
scancode_get_next(unsigned int *iter)
|
||||||
|
{
|
||||||
|
unsigned short rv = 0;
|
||||||
|
if (*iter < settings->size)
|
||||||
|
{
|
||||||
|
rv = settings->map[*iter].scancode;
|
||||||
|
++(*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
int
|
||||||
|
scancode_set_keycode_set(const char *kk_set)
|
||||||
|
{
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
|
if (kk_set == NULL)
|
||||||
|
{
|
||||||
|
rv = 1;
|
||||||
|
}
|
||||||
|
else if (strncmp(kk_set, "evdev", 5) == 0)
|
||||||
|
{
|
||||||
|
settings = &global_settings[SI_EVDEV];
|
||||||
|
}
|
||||||
|
else if (strncmp(kk_set, "base", 4) == 0)
|
||||||
|
{
|
||||||
|
settings = &global_settings[SI_BASE];
|
||||||
|
}
|
||||||
|
else if (strncmp(kk_set, "xfree86", 7) == 0)
|
||||||
|
{
|
||||||
|
settings = &global_settings[SI_BASE];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
const char *
|
||||||
|
scancode_get_keycode_set(void)
|
||||||
|
{
|
||||||
|
return settings->name;
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2024 Matt Burt, all xrdp contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file common/scancode.h
|
||||||
|
* @brief Scancode handling
|
||||||
|
*
|
||||||
|
* Convert between RDP scancodes and X11 keycodes.
|
||||||
|
*
|
||||||
|
* RDP scancodes are largely the same as Windows scancodes. These are
|
||||||
|
* indirectly documented in the Microsoft "Keyboard Scan Code Specification",
|
||||||
|
* Rev 1.3a (March 16th 2000) and are otherwise known as "Scan code set
|
||||||
|
* 1" scancodes. This document no longer appears to be available directly from
|
||||||
|
* the Microsoft website.
|
||||||
|
*
|
||||||
|
* X11 keycodes are the X11 equivalent of RDP scancodes. In general, these
|
||||||
|
* are specific to an X server. In practice however, these are nowadays
|
||||||
|
* handled by the XKB extension and only two sets are in common use:-
|
||||||
|
* - evdev : Linux, FreeBSD and possibly others
|
||||||
|
* - base : Everything else.
|
||||||
|
*
|
||||||
|
* This module presents a single source of truth for conversions between
|
||||||
|
* RDP scancodes and X11 keycodes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(SCANCODE_H)
|
||||||
|
#define SCANCODE_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up an RDP scancode
|
||||||
|
*
|
||||||
|
* @param scancode Scancode. Extended scancodes have bit 9 set
|
||||||
|
* (i.e. are in 0x100 - 0x1ff)
|
||||||
|
* @return keycode, or 0 for no keycode
|
||||||
|
*/
|
||||||
|
unsigned short
|
||||||
|
scancode_to_keycode(unsigned short scancode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the next valid scancode from the list of valid scancodes
|
||||||
|
* @param iter Value (initialised to zero), used to iterate
|
||||||
|
* over available scancodes.
|
||||||
|
* @return Next valid scancode, or zero.
|
||||||
|
*
|
||||||
|
* The iterator is updated on a successful call. Use like this:-
|
||||||
|
*
|
||||||
|
* iter = 0;
|
||||||
|
* while ((scancode = scancode_get_next(&iter)) != 0)
|
||||||
|
* {
|
||||||
|
* . . .
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
unsigned short
|
||||||
|
scancode_get_next(unsigned int *iter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the keycode set used for the scancode translation
|
||||||
|
*
|
||||||
|
* @param kk_set "evdev", "base", or something more
|
||||||
|
* complex (e.g. "evdev+aliases(qwerty)")
|
||||||
|
* @result 0 for success
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scancode_set_keycode_set(const char *kk_set);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the keycode set used for the scancode translation
|
||||||
|
*
|
||||||
|
* @result "evdev", or "base"
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
scancode_get_keycode_set(void);
|
||||||
|
|
||||||
|
#endif /* SCANCODE_H */
|
|
@ -23,7 +23,8 @@ test_common_SOURCES = \
|
||||||
test_os_calls_signals.c \
|
test_os_calls_signals.c \
|
||||||
test_ssl_calls.c \
|
test_ssl_calls.c \
|
||||||
test_base64.c \
|
test_base64.c \
|
||||||
test_guid.c
|
test_guid.c \
|
||||||
|
test_scancode.c
|
||||||
|
|
||||||
test_common_CFLAGS = \
|
test_common_CFLAGS = \
|
||||||
@CHECK_CFLAGS@ \
|
@CHECK_CFLAGS@ \
|
||||||
|
|
|
@ -16,6 +16,7 @@ Suite *make_suite_test_os_calls(void);
|
||||||
Suite *make_suite_test_ssl_calls(void);
|
Suite *make_suite_test_ssl_calls(void);
|
||||||
Suite *make_suite_test_base64(void);
|
Suite *make_suite_test_base64(void);
|
||||||
Suite *make_suite_test_guid(void);
|
Suite *make_suite_test_guid(void);
|
||||||
|
Suite *make_suite_test_scancode(void);
|
||||||
|
|
||||||
TCase *make_tcase_test_os_calls_signals(void);
|
TCase *make_tcase_test_os_calls_signals(void);
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ int main (void)
|
||||||
srunner_add_suite(sr, make_suite_test_ssl_calls());
|
srunner_add_suite(sr, make_suite_test_ssl_calls());
|
||||||
srunner_add_suite(sr, make_suite_test_base64());
|
srunner_add_suite(sr, make_suite_test_base64());
|
||||||
srunner_add_suite(sr, make_suite_test_guid());
|
srunner_add_suite(sr, make_suite_test_guid());
|
||||||
|
srunner_add_suite(sr, make_suite_test_scancode());
|
||||||
|
|
||||||
srunner_set_tap(sr, "-");
|
srunner_set_tap(sr, "-");
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
#include "config_ac.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "scancode.h"
|
||||||
|
|
||||||
|
#include "test_common.h"
|
||||||
|
|
||||||
|
// Checks all returned evdev scancodes are mapped to a keycode
|
||||||
|
START_TEST(test_scancode__keycode_sets)
|
||||||
|
{
|
||||||
|
ck_assert_int_eq(scancode_set_keycode_set(NULL), 1);
|
||||||
|
ck_assert_int_eq(scancode_set_keycode_set(""), 1);
|
||||||
|
ck_assert_int_eq(scancode_set_keycode_set("evdev"), 0);
|
||||||
|
ck_assert_int_eq(scancode_set_keycode_set("evdev+aliases(qwerty)"), 0);
|
||||||
|
ck_assert_int_eq(scancode_set_keycode_set("base"), 0);
|
||||||
|
ck_assert_int_eq(scancode_set_keycode_set("xfree86"), 0);
|
||||||
|
ck_assert_int_eq(scancode_set_keycode_set("xfree86+aliases(qwerty)"), 0);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
// Checks all returned evdev scancodes are mapped to a keycode
|
||||||
|
START_TEST(test_scancode__evdev_all_values_returned)
|
||||||
|
{
|
||||||
|
unsigned int iter;
|
||||||
|
unsigned int scancode;
|
||||||
|
|
||||||
|
ck_assert_int_eq(scancode_set_keycode_set("evdev"), 0);
|
||||||
|
|
||||||
|
iter = 0;
|
||||||
|
while ((scancode = scancode_get_next(&iter)) != 0)
|
||||||
|
{
|
||||||
|
unsigned short keycode = scancode_to_keycode(scancode);
|
||||||
|
ck_assert_int_ne(keycode, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
// Checks all invalid evdev scancodes return 0
|
||||||
|
START_TEST(test_scancode__evdev_bad_values_mapped_to_0)
|
||||||
|
{
|
||||||
|
// Store valid scancodes which are between 0 and 0x1ff
|
||||||
|
int valid[512] = {0};
|
||||||
|
unsigned int iter;
|
||||||
|
unsigned int scancode;
|
||||||
|
|
||||||
|
ck_assert_int_eq(scancode_set_keycode_set("evdev"), 0);
|
||||||
|
|
||||||
|
iter = 0;
|
||||||
|
while ((scancode = scancode_get_next(&iter)) != 0)
|
||||||
|
{
|
||||||
|
valid[scancode] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (scancode = 0 ; scancode < 512; ++scancode)
|
||||||
|
{
|
||||||
|
if (!valid[scancode])
|
||||||
|
{
|
||||||
|
ck_assert_int_eq(scancode_to_keycode(scancode), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
// Checks all returned base scancodes are mapped to a keycode
|
||||||
|
START_TEST(test_scancode__base_all_values_returned)
|
||||||
|
{
|
||||||
|
unsigned int iter;
|
||||||
|
unsigned int scancode;
|
||||||
|
|
||||||
|
ck_assert_int_eq(scancode_set_keycode_set("base"), 0);
|
||||||
|
|
||||||
|
iter = 0;
|
||||||
|
while ((scancode = scancode_get_next(&iter)) != 0)
|
||||||
|
{
|
||||||
|
unsigned short keycode = scancode_to_keycode(scancode);
|
||||||
|
ck_assert_int_ne(keycode, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
// Checks all invalid base scancodes return 0
|
||||||
|
START_TEST(test_scancode__base_bad_values_mapped_to_0)
|
||||||
|
{
|
||||||
|
// Store valid scancodes which are between 0 and 0x1ff
|
||||||
|
int valid[512] = {0};
|
||||||
|
unsigned int iter;
|
||||||
|
unsigned int scancode;
|
||||||
|
|
||||||
|
ck_assert_int_eq(scancode_set_keycode_set("base"), 0);
|
||||||
|
|
||||||
|
iter = 0;
|
||||||
|
while ((scancode = scancode_get_next(&iter)) != 0)
|
||||||
|
{
|
||||||
|
valid[scancode] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (scancode = 0 ; scancode < 512; ++scancode)
|
||||||
|
{
|
||||||
|
if (!valid[scancode])
|
||||||
|
{
|
||||||
|
ck_assert_int_eq(scancode_to_keycode(scancode), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Suite *
|
||||||
|
make_suite_test_scancode(void)
|
||||||
|
{
|
||||||
|
Suite *s;
|
||||||
|
TCase *tc;
|
||||||
|
|
||||||
|
s = suite_create("Scancode");
|
||||||
|
|
||||||
|
tc = tcase_create("scancode");
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
tcase_add_test(tc, test_scancode__keycode_sets);
|
||||||
|
tcase_add_test(tc, test_scancode__evdev_all_values_returned);
|
||||||
|
tcase_add_test(tc, test_scancode__evdev_bad_values_mapped_to_0);
|
||||||
|
tcase_add_test(tc, test_scancode__base_all_values_returned);
|
||||||
|
tcase_add_test(tc, test_scancode__base_bad_values_mapped_to_0);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
Loading…
Reference in New Issue