• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

FreeBSD bhyve keyboard layout patch


コミットメタ情報

リビジョン540e494f2d9651e10a5849f1760a4fabc938ac79 (tree)
日時2022-01-02 13:21:32
作者Koine Yuusuke(koinec) <koinec@user...>
コミッターKoine Yuusuke(koinec)

ログメッセージ

Add for the patches for FreeBSD 13-statble (20211223).

変更サマリ

差分

--- /dev/null
+++ b/kbdlayout_option/bhyve_kbdlayout_option_fbsd13s_20211223.patch
@@ -0,0 +1,260 @@
1+diff -uprN bhyve_orig/Makefile bhyve/Makefile
2+--- bhyve_orig/Makefile 2021-12-23 09:07:49.000000000 +0900
3++++ bhyve/Makefile 2022-01-02 10:48:16.788031000 +0900
4+@@ -132,4 +132,6 @@ CFLAGS+=-DGDB_LOG
5+
6+ WARNS?= 2
7+
8++SUBDIR= kbdlayout
9++
10+ .include <bsd.prog.mk>
11+diff -uprN bhyve_orig/bhyve.8 bhyve/bhyve.8
12+--- bhyve_orig/bhyve.8 2021-12-23 09:07:49.000000000 +0900
13++++ bhyve/bhyve.8 2022-01-02 11:18:37.389081000 +0900
14+@@ -47,6 +47,7 @@
15+ .Sm on
16+ .Op Fl G Ar port
17+ .Op Fl k Ar config_file
18++.Op Fl K Ar layout
19+ .Oo Fl l
20+ .Sm off
21+ .Ar lpcdev Op Cm \&, Ar conf
22+@@ -169,6 +170,14 @@ are ignored.
23+ See
24+ .Xr bhyve_config 5
25+ for more details.
26++.It Fl K Ar layout
27++Specify the keyboard layout.
28++The value that can be specified sets the file name in
29++.Ar /usr/share/bhyve/kbdlayout .
30++This specification only works when loaded with UEFI mode for VNC.
31++(Not working via serial console or SSH)
32++When using a VNC client that supports QEMU Extended Key Event Message (e.g. TigerVNC), this option isn't needed.
33++When using a VNC client that doesn't support QEMU Extended Key Event Message (e.g. tightVNC), the default layout defaults to the US keyboard unless specified otherwise.
34+ .It Fl l Cm help
35+ Print a list of supported LPC devices.
36+ .It Fl l Ar lpcdev Ns Op Cm \&, Ns Ar conf
37+diff -uprN bhyve_orig/bhyve_config.5 bhyve/bhyve_config.5
38+--- bhyve_orig/bhyve_config.5 2021-12-23 09:07:49.000000000 +0900
39++++ bhyve/bhyve_config.5 2022-01-02 11:23:42.989892000 +0900
40+@@ -131,6 +131,12 @@ will listen for connections on this port.
41+ .It Va gdb.wait Ta bool Ta false Ta
42+ If the debug server is enabled, wait for a debugger to connect
43+ before starting the guest.
44++.It Va keyboard.layout Ta string Ta Ta
45++Specify the keyboard layout name with the file name in
46++.Ar /usr/share/bhyve/kbdlayout .
47++This value only works when loaded with UEFI mode for VNC, and
48++used a VNC client that don't support QEMU Extended Key Event
49++Message (e.g. TightVNC).
50+ .It Va rtc.use_localtime Ta bool Ta true Ta
51+ The real time clock uses the local time of the host.
52+ If this is set to false, the real time clock uses UTC.
53+diff -uprN bhyve_orig/bhyverun.c bhyve/bhyverun.c
54+--- bhyve_orig/bhyverun.c 2021-12-23 09:07:49.000000000 +0900
55++++ bhyve/bhyverun.c 2022-01-02 11:31:05.019976000 +0900
56+@@ -224,8 +224,9 @@ usage(int code)
57+ fprintf(stderr,
58+ "Usage: %s [-AaCDeHhPSuWwxY]\n"
59+ " %*s [-c [[cpus=]numcpus][,sockets=n][,cores=n][,threads=n]]\n"
60+- " %*s [-G port] [-k config_file] [-l lpc] [-m mem] [-o var=value]\n"
61+- " %*s [-p vcpu:hostcpu] [-r file] [-s pci] [-U uuid] vmname\n"
62++ " %*s [-G port] [-k config_file] [-K layout] [-l lpc] [-m mem]\n"
63++ " %*s [-o var=value] [-p vcpu:hostcpu] [-r file] [-s pci]\n"
64++ " %*s [-U uuid] vmname\n"
65+ " -A: create ACPI tables\n"
66+ " -a: local apic is in xAPIC mode (deprecated)\n"
67+ " -C: include guest memory in core file\n"
68+@@ -236,6 +237,7 @@ usage(int code)
69+ " -H: vmexit from the guest on HLT\n"
70+ " -h: help\n"
71+ " -k: key=value flat config file\n"
72++ " -K: PS2 keyboard layout\n"
73+ " -l: LPC device configuration\n"
74+ " -m: memory size in MB\n"
75+ " -o: set config 'var' to 'value'\n"
76+@@ -253,7 +255,7 @@ usage(int code)
77+ " -x: local APIC is in x2APIC mode\n"
78+ " -Y: disable MPtable generation\n",
79+ progname, (int)strlen(progname), "", (int)strlen(progname), "",
80+- (int)strlen(progname), "");
81++ (int)strlen(progname), "", (int)strlen(progname), "");
82+
83+ exit(code);
84+ }
85+@@ -1225,9 +1227,9 @@ main(int argc, char *argv[])
86+ progname = basename(argv[0]);
87+
88+ #ifdef BHYVE_SNAPSHOT
89+- optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:U:r:";
90++ optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:K:U:r:";
91+ #else
92+- optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:U:";
93++ optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:K:U:";
94+ #endif
95+ while ((c = getopt(argc, argv, optstr)) != -1) {
96+ switch (c) {
97+@@ -1264,6 +1266,9 @@ main(int argc, char *argv[])
98+ break;
99+ case 'k':
100+ parse_simple_config_file(optarg);
101++ break;
102++ case 'K':
103++ set_config_value("keyboard.layout", optarg);
104+ break;
105+ case 'l':
106+ if (strncmp(optarg, "help", strlen(optarg)) == 0) {
107+diff -uprN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
108+--- bhyve_orig/ps2kbd.c 2021-12-23 09:07:49.000000000 +0900
109++++ bhyve/ps2kbd.c 2022-01-02 11:33:03.248964000 +0900
110+@@ -31,6 +31,7 @@
111+ __FBSDID("$FreeBSD$");
112+
113+ #include <sys/types.h>
114++#include <sys/stat.h>
115+
116+ #include <machine/vmm_snapshot.h>
117+
118+@@ -42,9 +43,13 @@ __FBSDID("$FreeBSD$");
119+ #include <strings.h>
120+ #include <pthread.h>
121+ #include <pthread_np.h>
122++#include <unistd.h>
123++#include <fcntl.h>
124+
125++#include "bhyverun.h"
126+ #include "atkbdc.h"
127+ #include "debug.h"
128++#include "config.h"
129+ #include "console.h"
130+
131+ /* keyboard device commands */
132+@@ -62,6 +67,10 @@ __FBSDID("$FreeBSD$");
133+
134+ #define PS2KBD_FIFOSZ 16
135+
136++#define PS2KBD_LAYOUT_BASEDIR "/usr/share/bhyve/kbdlayout/"
137++
138++#define MAX_PATHNAME 256
139++
140+ struct fifo {
141+ uint8_t buf[PS2KBD_FIFOSZ];
142+ int rindex; /* index to read from */
143+@@ -90,7 +99,7 @@ struct extended_translation {
144+ /*
145+ * FIXME: Pause/break and Print Screen/SysRq require special handling.
146+ */
147+-static const struct extended_translation extended_translations[] = {
148++static struct extended_translation extended_translations[128] = {
149+ {0xff08, 0x66}, /* Back space */
150+ {0xff09, 0x0d}, /* Tab */
151+ {0xff0d, 0x5a}, /* Return */
152+@@ -162,7 +171,7 @@ static const struct extended_translation extended_tran
153+ };
154+
155+ /* ASCII to type 2 scancode lookup table */
156+-static const uint8_t ascii_translations[128] = {
157++static uint8_t ascii_translations[128] = {
158+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161+@@ -320,7 +329,7 @@ ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
162+ assert(pthread_mutex_isowned_np(&sc->mtx));
163+ int e0_prefix, found;
164+ uint8_t code;
165+- const struct extended_translation *trans;
166++ struct extended_translation *trans;
167+
168+ found = 0;
169+ if (keysym < 0x80) {
170+@@ -370,10 +379,90 @@ ps2kbd_event(int down, uint32_t keysym, void *arg)
171+ atkbdc_event(sc->atkbdc_sc, 1);
172+ }
173+
174++static void
175++ps2kbd_update_extended_translation(uint32_t keycode, uint32_t scancode, uint32_t prefix)
176++{
177++ int i = 0;
178++
179++ do {
180++ if (extended_translations[i].keysym == keycode)
181++ break;
182++ } while(extended_translations[++i].keysym);
183++
184++ if (i == (sizeof(extended_translations) / sizeof(struct extended_translation) - 1))
185++ return;
186++
187++ if (!extended_translations[i].keysym) {
188++ extended_translations[i].keysym = keycode;
189++
190++ extended_translations[i+1].keysym = 0;
191++ extended_translations[i+1].scancode = 0;
192++ extended_translations[i+1].flags = 0;
193++ }
194++
195++ extended_translations[i].scancode = (uint8_t)(scancode & 0xff);
196++ extended_translations[i].flags = (prefix ? SCANCODE_E0_PREFIX : 0);
197++}
198++
199++static void
200++ps2kbd_setkbdlayout(void)
201++{
202++ int err;
203++ int fd;
204++ char path[MAX_PATHNAME];
205++ char *buf, *next, *line;
206++ struct stat sb;
207++ size_t sz;
208++ uint8_t ascii;
209++ uint32_t keycode, scancode, prefix;
210++
211++ snprintf(path, MAX_PATHNAME, PS2KBD_LAYOUT_BASEDIR"%s", get_config_value("keyboard.layout") );
212++
213++ err = stat(path, &sb);
214++ if (err)
215++ return;
216++
217++ buf = (char *)malloc(sizeof(char) * sb.st_size);
218++ if (buf == NULL)
219++ return;
220++
221++ fd = open(path, O_RDONLY);
222++ if (fd == -1)
223++ goto out;
224++
225++ sz = read(fd, buf, sb.st_size );
226++
227++ close(fd);
228++
229++ if (sz != sb.st_size )
230++ goto out;
231++
232++ next = buf;
233++ while ((line = strsep(&next, "\n")) != NULL) {
234++ if (sscanf(line, "'%c',%x;", &ascii, &scancode) == 2) {
235++ if (ascii < 0x80)
236++ ascii_translations[ascii] = (uint8_t)(scancode & 0xff);
237++ } else if (sscanf(line, "%x,%x,%x;", &keycode, &scancode, &prefix) == 3 ) {
238++ ps2kbd_update_extended_translation(keycode, scancode, prefix);
239++ } else if (sscanf(line, "%x,%x;", &keycode, &scancode) == 2) {
240++ if (keycode < 0x80)
241++ ascii_translations[(uint8_t)(keycode & 0xff)] = (uint8_t)(scancode & 0xff);
242++ else
243++ ps2kbd_update_extended_translation(keycode, scancode, 0);
244++ }
245++ }
246++
247++out:
248++ free(buf);
249++}
250++
251+ struct ps2kbd_softc *
252+ ps2kbd_init(struct atkbdc_softc *atkbdc_sc)
253+ {
254+ struct ps2kbd_softc *sc;
255++
256++ if (get_config_value("keyboard.layout") != NULL)
257++ ps2kbd_setkbdlayout();
258+
259+ sc = calloc(1, sizeof (struct ps2kbd_softc));
260+ pthread_mutex_init(&sc->mtx, NULL);
--- /dev/null
+++ b/kbdlayout_option/bhyve_kbdlayout_vmrunsh_fbsd13s_20211223.patch
@@ -0,0 +1,41 @@
1+diff -uprN examples/bhyve_orig/vmrun.sh examples/bhyve/vmrun.sh
2+--- examples/bhyve_orig/vmrun.sh 2021-04-09 09:24:07.000000000 +0900
3++++ examples/bhyve/vmrun.sh 2021-05-03 13:46:11.358862000 +0900
4+@@ -59,8 +59,8 @@ usage() {
5+ echo " [-e <name=value>] [-f <path of firmware>]" \
6+ "[-F <size>]"
7+ echo " [-H <directory>]"
8+- echo " [-I <location of installation iso>] [-l <loader>]"
9+- echo " [-L <VNC IP for UEFI framebuffer>]"
10++ echo " [-I <location of installation iso>] [-K <layout>]"
11++ echo " [-l <loader>] [-L <VNC IP for UEFI framebuffer>]"
12+ echo " [-m <memsize>]" \
13+ "[-n <network adapter emulation type>]"
14+ echo " [-P <port>] [-t <tapdev>] <vmname>"
15+@@ -80,6 +80,7 @@ usage() {
16+ echo " -i: force boot of the Installation CDROM image"
17+ echo " -I: Installation CDROM image location" \
18+ "(default: ${DEFAULT_ISOFILE})"
19++ echo " -K: Specify the keyboard layout"
20+ echo " -l: the OS loader to use (default: /boot/userboot.so)"
21+ echo " -L: IP address for UEFI GOP VNC server" \
22+ "(default: ${DEFAULT_VNCHOST}"
23+@@ -132,7 +133,7 @@ vncport=${DEFAULT_VNCPORT}
24+ vncsize=${DEFAULT_VNCSIZE}
25+ tablet=""
26+
27+-while getopts aAc:C:d:e:Ef:F:g:hH:iI:l:L:m:n:p:P:t:Tuvw c ; do
28++while getopts aAc:C:d:e:Ef:F:g:hH:iI:K:l:L:m:n:p:P:t:Tuvw c ; do
29+ case $c in
30+ a)
31+ bhyverun_opt="${bhyverun_opt} -a"
32+@@ -173,6 +174,9 @@ while getopts aAc:C:d:e:Ef:F:g:hH:iI:l:L:m:n:p:P:t:Tuv
33+ ;;
34+ I)
35+ isofile=${OPTARG}
36++ ;;
37++ K)
38++ bhyverun_opt="${bhyverun_opt} -K ${OPTARG}"
39+ ;;
40+ l)
41+ loader_opt="${loader_opt} -l ${OPTARG}"
--- /dev/null
+++ b/qemu_ext_keyevent_msg/bhyve_qemu_ext_key_event_msg_fbsd13s_20211223.patch
@@ -0,0 +1,281 @@
1+diff -uprN bhyve_orig/console.c bhyve/console.c
2+--- bhyve_orig/console.c 2021-04-09 09:24:13.000000000 +0900
3++++ bhyve/console.c 2021-05-03 13:11:57.869902000 +0900
4+@@ -106,10 +106,10 @@ console_ptr_register(ptr_event_func_t event_cb, void *
5+ }
6+
7+ void
8+-console_key_event(int down, uint32_t keysym)
9++console_key_event(int down, uint32_t keysym, uint32_t keycode)
10+ {
11+ if (console.kbd_event_cb)
12+- (*console.kbd_event_cb)(down, keysym, console.kbd_arg);
13++ (*console.kbd_event_cb)(down, keysym, keycode, console.kbd_arg);
14+ }
15+
16+ void
17+diff -uprN bhyve_orig/console.h bhyve/console.h
18+--- bhyve_orig/console.h 2021-04-09 09:24:13.000000000 +0900
19++++ bhyve/console.h 2021-05-03 13:11:57.870288000 +0900
20+@@ -34,7 +34,7 @@
21+ struct bhyvegc;
22+
23+ typedef void (*fb_render_func_t)(struct bhyvegc *gc, void *arg);
24+-typedef void (*kbd_event_func_t)(int down, uint32_t keysym, void *arg);
25++typedef void (*kbd_event_func_t)(int down, uint32_t keysym, uint32_t keycode, void *arg);
26+ typedef void (*ptr_event_func_t)(uint8_t mask, int x, int y, void *arg);
27+
28+ void console_init(int w, int h, void *fbaddr);
29+@@ -47,7 +47,7 @@ void console_fb_register(fb_render_func_t render_cb, v
30+ void console_refresh(void);
31+
32+ void console_kbd_register(kbd_event_func_t event_cb, void *arg, int pri);
33+-void console_key_event(int down, uint32_t keysym);
34++void console_key_event(int down, uint32_t keysym, uint32_t keycode);
35+
36+ void console_ptr_register(ptr_event_func_t event_cb, void *arg, int pri);
37+ void console_ptr_event(uint8_t button, int x, int y);
38+diff -uprN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
39+--- bhyve_orig/ps2kbd.c 2021-04-09 09:24:13.000000000 +0900
40++++ bhyve/ps2kbd.c 2021-05-03 13:11:57.870908000 +0900
41+@@ -181,6 +181,26 @@ static const uint8_t ascii_translations[128] = {
42+ 0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x0e, 0x00,
43+ };
44+
45++/* ScanCode set1 to set2 lookup table */
46++const uint8_t keyset1to2_translations[128] = {
47++ 0, 0x76, 0x16, 0x1E, 0x26, 0x25, 0x2e, 0x36,
48++ 0x3d, 0x3e, 0x46, 0x45, 0x4e, 0x55, 0x66, 0x0d,
49++ 0x15, 0x1d, 0x24, 0x2d, 0x2c, 0x35, 0x3c, 0x43,
50++ 0x44, 0x4d, 0x54, 0x5b, 0x5a, 0x14, 0x1c, 0x1b,
51++ 0x23, 0x2b, 0x34, 0x33, 0x3b, 0x42, 0x4b, 0x4c,
52++ 0x52, 0x0e, 0x12, 0x5d, 0x1a, 0x22, 0x21, 0x2a,
53++ 0x32, 0x31, 0x3a, 0x41, 0x49, 0x4a, 0x59, 0x7c,
54++ 0x11, 0x29, 0x58, 0x05, 0x06, 0x04, 0x0c, 0x03,
55++ 0x0b, 0x83, 0x0a, 0x01, 0x09, 0x77, 0x7e, 0x6c,
56++ 0x75, 0x7d, 0x7b, 0x6b, 0x73, 0x74, 0x79, 0x69,
57++ 0x72, 0x7a, 0x70, 0x71, 0x84, 0x60, 0x61, 0x78,
58++ 0x07, 0x0f, 0x17, 0x1f, 0x27, 0x2f, 0x37, 0x3f,
59++ 0x47, 0x4f, 0x56, 0x5e, 0x08, 0x10, 0x18, 0x20,
60++ 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x57, 0x6f,
61++ 0x13, 0x19, 0x39, 0x51, 0x53, 0x5c, 0x5f, 0x62,
62++ 0x63, 0x64, 0x65, 0x67, 0x68, 0x6a, 0x6d, 0x6e,
63++};
64++
65+ static void
66+ fifo_init(struct ps2kbd_softc *sc)
67+ {
68+@@ -315,26 +335,32 @@ ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val)
69+ */
70+ static void
71+ ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
72+- int down, uint32_t keysym)
73++ int down, uint32_t keysym, uint32_t keycode)
74+ {
75+ assert(pthread_mutex_isowned_np(&sc->mtx));
76+ int e0_prefix, found;
77+ uint8_t code;
78+ const struct extended_translation *trans;
79+
80+- found = 0;
81+- if (keysym < 0x80) {
82+- code = ascii_translations[keysym];
83+- e0_prefix = 0;
84++ if (keycode) {
85++ code = keyset1to2_translations[(uint8_t)(keycode & 0x7f)];
86++ e0_prefix = ((keycode & 0x80) ? SCANCODE_E0_PREFIX : 0);
87+ found = 1;
88+ } else {
89+- for (trans = &(extended_translations[0]); trans->keysym != 0;
90+- trans++) {
91+- if (keysym == trans->keysym) {
92+- code = trans->scancode;
93+- e0_prefix = trans->flags & SCANCODE_E0_PREFIX;
94+- found = 1;
95+- break;
96++ found = 0;
97++ if (keysym < 0x80) {
98++ code = ascii_translations[keysym];
99++ e0_prefix = 0;
100++ found = 1;
101++ } else {
102++ for (trans = &(extended_translations[0]); trans->keysym != 0;
103++ trans++) {
104++ if (keysym == trans->keysym) {
105++ code = trans->scancode;
106++ e0_prefix = trans->flags & SCANCODE_E0_PREFIX;
107++ found = 1;
108++ break;
109++ }
110+ }
111+ }
112+ }
113+@@ -352,7 +378,7 @@ ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
114+ }
115+
116+ static void
117+-ps2kbd_event(int down, uint32_t keysym, void *arg)
118++ps2kbd_event(int down, uint32_t keysym, uint32_t keycode, void *arg)
119+ {
120+ struct ps2kbd_softc *sc = arg;
121+ int fifo_full;
122+@@ -363,7 +389,7 @@ ps2kbd_event(int down, uint32_t keysym, void *arg)
123+ return;
124+ }
125+ fifo_full = sc->fifo.num == PS2KBD_FIFOSZ;
126+- ps2kbd_keysym_queue(sc, down, keysym);
127++ ps2kbd_keysym_queue(sc, down, keysym, keycode);
128+ pthread_mutex_unlock(&sc->mtx);
129+
130+ if (!fifo_full)
131+diff -uprN bhyve_orig/rfb.c bhyve/rfb.c
132+--- bhyve_orig/rfb.c 2021-04-09 09:24:13.000000000 +0900
133++++ bhyve/rfb.c 2021-05-03 13:13:08.713857000 +0900
134+@@ -98,6 +98,7 @@ static int rfb_debug = 0;
135+ #define CS_KEY_EVENT 4
136+ #define CS_POINTER_EVENT 5
137+ #define CS_CUT_TEXT 6
138++#define CS_MSG_CLIENT_QEMU 255
139+
140+ #define SECURITY_TYPE_NONE 1
141+ #define SECURITY_TYPE_VNC_AUTH 2
142+@@ -118,7 +119,10 @@ struct rfb_softc {
143+ bool enc_raw_ok;
144+ bool enc_zlib_ok;
145+ bool enc_resize_ok;
146++ bool enc_extkeyevent_ok;
147+
148++ bool enc_extkeyevent_send;
149++
150+ z_stream zstream;
151+ uint8_t *zbuf;
152+ int zbuflen;
153+@@ -170,7 +174,10 @@ struct rfb_pixfmt_msg {
154+ #define RFB_ENCODING_RAW 0
155+ #define RFB_ENCODING_ZLIB 6
156+ #define RFB_ENCODING_RESIZE -223
157++#define RFB_ENCODING_EXT_KEYEVENT -258
158+
159++#define RFB_CLIENTMSG_EXT_KEYEVENT 0
160++
161+ #define RFB_MAX_WIDTH 2000
162+ #define RFB_MAX_HEIGHT 1200
163+ #define RFB_ZLIB_BUFSZ RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4
164+@@ -197,6 +204,19 @@ struct rfb_key_msg {
165+ uint8_t type;
166+ uint8_t down;
167+ uint16_t pad;
168++ uint32_t sym;
169++};
170++
171++struct rfb_client_msg {
172++ uint8_t type;
173++ uint8_t subtype;
174++};
175++
176++struct rfb_extended_key_msg {
177++ uint8_t type;
178++ uint8_t subtype;
179++ uint16_t down;
180++ uint32_t sym;
181+ uint32_t code;
182+ };
183+
184+@@ -277,6 +297,27 @@ rfb_send_resize_update_msg(struct rfb_softc *rc, int c
185+ }
186+
187+ static void
188++rfb_send_extended_keyevent_update_msg(struct rfb_softc *rc, int cfd)
189++{
190++ struct rfb_srvr_updt_msg supdt_msg;
191++ struct rfb_srvr_rect_hdr srect_hdr;
192++
193++ /* Number of rectangles: 1 */
194++ supdt_msg.type = 0;
195++ supdt_msg.pad = 0;
196++ supdt_msg.numrects = htons(1);
197++ stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg));
198++
199++ /* Rectangle header */
200++ srect_hdr.x = htons(0);
201++ srect_hdr.y = htons(0);
202++ srect_hdr.width = htons(rc->width);
203++ srect_hdr.height = htons(rc->height);
204++ srect_hdr.encoding = htonl(RFB_ENCODING_EXT_KEYEVENT);
205++ stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr));
206++}
207++
208++static void
209+ rfb_recv_set_pixfmt_msg(struct rfb_softc *rc, int cfd)
210+ {
211+ struct rfb_pixfmt_msg pixfmt_msg;
212+@@ -309,6 +350,9 @@ rfb_recv_set_encodings_msg(struct rfb_softc *rc, int c
213+ case RFB_ENCODING_RESIZE:
214+ rc->enc_resize_ok = true;
215+ break;
216++ case RFB_ENCODING_EXT_KEYEVENT:
217++ rc->enc_extkeyevent_ok = true;
218++ break;
219+ }
220+ }
221+ }
222+@@ -686,6 +730,11 @@ rfb_recv_update_msg(struct rfb_softc *rc, int cfd)
223+
224+ (void)stream_read(cfd, ((void *)&updt_msg) + 1 , sizeof(updt_msg) - 1);
225+
226++ if (rc->enc_extkeyevent_ok && (!rc->enc_extkeyevent_send)) {
227++ rfb_send_extended_keyevent_update_msg(rc, cfd);
228++ rc->enc_extkeyevent_send = true;
229++ }
230++
231+ rc->pending = true;
232+ if (!updt_msg.incremental)
233+ rc->update_all = true;
234+@@ -698,11 +747,26 @@ rfb_recv_key_msg(struct rfb_softc *rc, int cfd)
235+
236+ (void)stream_read(cfd, ((void *)&key_msg) + 1, sizeof(key_msg) - 1);
237+
238+- console_key_event(key_msg.down, htonl(key_msg.code));
239++ console_key_event(key_msg.down, htonl(key_msg.sym), htonl(0));
240+ rc->input_detected = true;
241+ }
242+
243+ static void
244++rfb_recv_client_msg(struct rfb_softc *rc, int cfd)
245++{
246++ struct rfb_client_msg client_msg;
247++ struct rfb_extended_key_msg extkey_msg;
248++
249++ (void)stream_read(cfd, ((void *)&client_msg) + 1, sizeof(client_msg) - 1);
250++
251++ if (client_msg.subtype == RFB_CLIENTMSG_EXT_KEYEVENT ) {
252++ (void)stream_read(cfd, ((void *)&extkey_msg) + 2, sizeof(extkey_msg) - 2);
253++ console_key_event((int)extkey_msg.down, htonl(extkey_msg.sym), htonl(extkey_msg.code));
254++ rc->input_detected = true;
255++ }
256++}
257++
258++static void
259+ rfb_recv_ptr_msg(struct rfb_softc *rc, int cfd)
260+ {
261+ struct rfb_ptr_msg ptr_msg;
262+@@ -997,6 +1061,9 @@ report_and_done:
263+ case CS_CUT_TEXT:
264+ rfb_recv_cuttext_msg(rc, cfd);
265+ break;
266++ case CS_MSG_CLIENT_QEMU:
267++ rfb_recv_client_msg(rc, cfd);
268++ break;
269+ default:
270+ WPRINTF(("rfb unknown cli-code %d!", buf[0] & 0xff));
271+ goto done;
272+@@ -1031,6 +1098,9 @@ rfb_thr(void *arg)
273+ rc->enc_raw_ok = false;
274+ rc->enc_zlib_ok = false;
275+ rc->enc_resize_ok = false;
276++ rc->enc_extkeyevent_ok = false;
277++
278++ rc->enc_extkeyevent_send = false;
279+
280+ cfd = accept(rc->sfd, NULL, NULL);
281+ if (rc->conn_wait) {