• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#objective-cqtwindows誰得cocoapythonphprubygameguibathyscaphec翻訳omegat計画中(planning stage)frameworktwittertestdomvb.netdirectxbtronarduinopreviewerゲームエンジン

FreeBSD bhyve keyboard layout patch


Commit MetaInfo

Révision3b4b39842a8bd5879d5cc3cd034217175f427f0e (tree)
l'heure2022-01-02 10:14:34
AuteurKoine Yuusuke(koinec) <koinec@user...>
CommiterKoine Yuusuke(koinec)

Message de Log

Add for the patches for FreeBSD 12.3-RELEASE.

Change Summary

Modification

--- /dev/null
+++ b/kbdlayout_option/bhyve_kbdlayout_option_fbsd123r.patch
@@ -0,0 +1,249 @@
1+diff -uprN bhyve_orig/Makefile bhyve/Makefile
2+--- bhyve_orig/Makefile 2021-12-02 09:22:48.000000000 +0900
3++++ bhyve/Makefile 2022-01-02 09:43:54.032581000 +0900
4+@@ -96,4 +96,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-02 09:22:48.000000000 +0900
13++++ bhyve/bhyve.8 2022-01-02 09:50:18.123909000 +0900
14+@@ -47,6 +47,7 @@
15+ .Sm on
16+ .Op Fl G Ar port
17+ .Op Fl g Ar gdbport
18++.Op Fl K Ar layout
19+ .Oo Fl l
20+ .Sm off
21+ .Ar lpcdev Op Cm \&, Ar conf
22+@@ -180,6 +181,14 @@ value.
23+ Blank lines and lines starting with
24+ .Sq #
25+ are ignored.
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/bhyverun.c bhyve/bhyverun.c
38+--- bhyve_orig/bhyverun.c 2021-12-02 09:22:48.000000000 +0900
39++++ bhyve/bhyverun.c 2022-01-02 09:46:58.043670000 +0900
40+@@ -165,6 +165,8 @@ char *vmname;
41+ int guest_ncpus;
42+ uint16_t cores, maxcpus, sockets, threads;
43+
44++char *kbdlayout_name;
45++
46+ char *guest_uuid_str;
47+
48+ int raw_stdio = 0;
49+@@ -215,7 +217,7 @@ usage(int code)
50+ fprintf(stderr,
51+ "Usage: %s [-AaCDeHhPSuWwxY]\n"
52+ " %*s [-c [[cpus=]numcpus][,sockets=n][,cores=n][,threads=n]]\n"
53+- " %*s [-G port] [-k file] [-l lpc] [-m mem] [-o var=value]\n"
54++ " %*s [-G port] [-k file] [-K layout] [-l lpc] [-m mem] [-o var=value]\n"
55+ " %*s [-p vcpu:hostcpu] [-s pci] [-U uuid] vmname\n"
56+ " -A: create ACPI tables\n"
57+ " -a: local apic is in xAPIC mode (deprecated)\n"
58+@@ -227,6 +229,7 @@ usage(int code)
59+ " -H: vmexit from the guest on HLT\n"
60+ " -h: help\n"
61+ " -k: key=value flat config file\n"
62++ " -K: PS2 keyboard layout\n"
63+ " -l: LPC device configuration\n"
64+ " -m: memory size in MB\n"
65+ " -o: set config 'var' to 'value'\n"
66+@@ -1025,8 +1028,9 @@ main(int argc, char *argv[])
67+ mptgen = 1;
68+ rtc_localtime = 1;
69+ memflags = 0;
70++ kbdlayout_name = NULL;
71+
72+- optstr = "abehuwxACDHIPSWYp:g:G:c:s:m:l:U:";
73++ optstr = "abehuwxACDHIPSWYp:g:G:c:s:m:l:K:U:";
74+ while ((c = getopt(argc, argv, optstr)) != -1) {
75+ switch (c) {
76+ case 'a':
77+@@ -1067,6 +1071,9 @@ main(int argc, char *argv[])
78+ optarg++;
79+ }
80+ gdb_port = atoi(optarg);
81++ break;
82++ case 'K':
83++ kbdlayout_name = optarg;
84+ break;
85+ case 'l':
86+ if (strncmp(optarg, "help", strlen(optarg)) == 0) {
87+diff -uprN bhyve_orig/bhyverun.h bhyve/bhyverun.h
88+--- bhyve_orig/bhyverun.h 2021-12-02 09:22:48.000000000 +0900
89++++ bhyve/bhyverun.h 2022-01-02 09:43:54.036211000 +0900
90+@@ -39,6 +39,7 @@ extern int guest_ncpus;
91+ extern uint16_t cores, sockets, threads;
92+ extern char *guest_uuid_str;
93+ extern char *vmname;
94++extern char *kbdlayout_name;
95+
96+ void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len);
97+
98+diff -uprN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
99+--- bhyve_orig/ps2kbd.c 2021-12-02 09:22:48.000000000 +0900
100++++ bhyve/ps2kbd.c 2022-01-02 09:43:54.037117000 +0900
101+@@ -31,15 +31,20 @@
102+ __FBSDID("$FreeBSD: releng/12.3/usr.sbin/bhyve/ps2kbd.c 358184 2020-02-20 21:48:36Z vmaffione $");
103+
104+ #include <sys/types.h>
105++#include <sys/stat.h>
106+
107+ #include <assert.h>
108+ #include <stdbool.h>
109+ #include <stdio.h>
110+ #include <stdlib.h>
111++#include <string.h>
112+ #include <strings.h>
113+ #include <pthread.h>
114+ #include <pthread_np.h>
115++#include <unistd.h>
116++#include <fcntl.h>
117+
118++#include "bhyverun.h"
119+ #include "atkbdc.h"
120+ #include "debug.h"
121+ #include "console.h"
122+@@ -59,6 +64,8 @@ __FBSDID("$FreeBSD: releng/12.3/usr.sbin/bhyve/ps2kbd.
123+
124+ #define PS2KBD_FIFOSZ 16
125+
126++#define PS2KBD_LAYOUT_BASEDIR "/usr/share/bhyve/kbdlayout/"
127++
128+ struct fifo {
129+ uint8_t buf[PS2KBD_FIFOSZ];
130+ int rindex; /* index to read from */
131+@@ -87,7 +94,7 @@ struct extended_translation {
132+ /*
133+ * FIXME: Pause/break and Print Screen/SysRq require special handling.
134+ */
135+-static const struct extended_translation extended_translations[] = {
136++static struct extended_translation extended_translations[128] = {
137+ {0xff08, 0x66}, /* Back space */
138+ {0xff09, 0x0d}, /* Tab */
139+ {0xff0d, 0x5a}, /* Return */
140+@@ -159,7 +166,7 @@ static const struct extended_translation extended_tran
141+ };
142+
143+ /* ASCII to type 2 scancode lookup table */
144+-static const uint8_t ascii_translations[128] = {
145++static uint8_t ascii_translations[128] = {
146+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149+@@ -317,7 +324,7 @@ ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
150+ assert(pthread_mutex_isowned_np(&sc->mtx));
151+ int e0_prefix, found;
152+ uint8_t code;
153+- const struct extended_translation *trans;
154++ struct extended_translation *trans;
155+
156+ found = 0;
157+ if (keysym < 0x80) {
158+@@ -367,10 +374,91 @@ ps2kbd_event(int down, uint32_t keysym, void *arg)
159+ atkbdc_event(sc->atkbdc_sc, 1);
160+ }
161+
162++static void
163++ps2kbd_update_extended_translation(uint32_t keycode, uint32_t scancode, uint32_t prefix)
164++{
165++ int i = 0;
166++
167++ do {
168++ if (extended_translations[i].keysym == keycode)
169++ break;
170++ } while(extended_translations[++i].keysym);
171++
172++ if (i == (sizeof(extended_translations) / sizeof(struct extended_translation) - 1))
173++ return;
174++
175++ if (!extended_translations[i].keysym) {
176++ extended_translations[i].keysym = keycode;
177++
178++ extended_translations[i+1].keysym = 0;
179++ extended_translations[i+1].scancode = 0;
180++ extended_translations[i+1].flags = 0;
181++ }
182++
183++ extended_translations[i].scancode = (uint8_t)(scancode & 0xff);
184++ extended_translations[i].flags = (prefix ? SCANCODE_E0_PREFIX : 0);
185++}
186++
187++static void
188++ps2kbd_setkbdlayout(void)
189++{
190++ int err;
191++ int fd;
192++ char path[256];
193++ char *buf, *next, *line;
194++ struct stat sb;
195++ size_t sz;
196++ uint8_t ascii;
197++ uint32_t keycode, scancode, prefix;
198++
199++ strcpy(path, PS2KBD_LAYOUT_BASEDIR);
200++ strncat(path, kbdlayout_name, (sizeof(path) - strlen(PS2KBD_LAYOUT_BASEDIR) - 1));
201++
202++ err = stat(path, &sb);
203++ if (err)
204++ return;
205++
206++ buf = (char *)malloc(sizeof(char) * sb.st_size);
207++ if (buf == NULL)
208++ return;
209++
210++ fd = open(path, O_RDONLY);
211++ if (fd == -1)
212++ goto out;
213++
214++ sz = read(fd, buf, sb.st_size );
215++
216++ close(fd);
217++
218++ if (sz != sb.st_size )
219++ goto out;
220++
221++ next = buf;
222++ while ((line = strsep(&next, "\n")) != NULL) {
223++ if (sscanf(line, "'%c',%x;", &ascii, &scancode) == 2) {
224++ if (ascii < 0x80)
225++ ascii_translations[ascii] = (uint8_t)(scancode & 0xff);
226++ } else if (sscanf(line, "%x,%x,%x;", &keycode, &scancode, &prefix) == 3 ) {
227++ ps2kbd_update_extended_translation(keycode, scancode, prefix);
228++ } else if (sscanf(line, "%x,%x;", &keycode, &scancode) == 2) {
229++ if (keycode < 0x80)
230++ ascii_translations[(uint8_t)(keycode & 0xff)] = (uint8_t)(scancode & 0xff);
231++ else
232++ ps2kbd_update_extended_translation(keycode, scancode, 0);
233++ }
234++ }
235++
236++out:
237++ free(buf);
238++}
239++
240+ struct ps2kbd_softc *
241+ ps2kbd_init(struct atkbdc_softc *atkbdc_sc)
242+ {
243+ struct ps2kbd_softc *sc;
244++
245++ if (kbdlayout_name != NULL)
246++ ps2kbd_setkbdlayout();
247+
248+ sc = calloc(1, sizeof (struct ps2kbd_softc));
249+ pthread_mutex_init(&sc->mtx, NULL);
--- /dev/null
+++ b/kbdlayout_option/bhyve_kbdlayout_vmrunsh_fbsd123r.patch
@@ -0,0 +1,41 @@
1+diff -uprN examples/bhyve_orig/vmrun.sh examples/bhyve/vmrun.sh
2+--- examples/bhyve_orig/vmrun.sh 2021-12-02 09:22:58.000000000 +0900
3++++ examples/bhyve/vmrun.sh 2022-01-02 10:08:33.921094000 +0900
4+@@ -59,8 +59,8 @@ usage() {
5+ echo " [-e <name=value>] [-f <path of firmware>]" \
6+ "[-F <size>]"
7+ echo " [-g <gdbport> ] [-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+@@ -81,6 +81,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+@@ -134,7 +135,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+@@ -178,6 +179,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_fbsd123r.patch
@@ -0,0 +1,271 @@
1+diff -uprN bhyve_orig/console.c bhyve/console.c
2+--- bhyve_orig/console.c 2020-10-23 09:02:29.000000000 +0900
3++++ bhyve/console.c 2020-12-30 18:21:24.579446000 +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 2020-10-23 09:02:29.000000000 +0900
19++++ bhyve/console.h 2020-12-30 18:21:24.579887000 +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 2020-10-23 09:02:29.000000000 +0900
40++++ bhyve/ps2kbd.c 2020-12-30 18:21:24.580562000 +0900
41+@@ -178,6 +178,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+@@ -312,26 +332,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+@@ -349,7 +375,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+@@ -360,7 +386,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 2020-10-23 09:02:29.000000000 +0900
133++++ bhyve/rfb.c 2020-12-30 18:21:24.581683000 +0900
134+@@ -99,7 +99,10 @@ struct rfb_softc {
135+ bool enc_raw_ok;
136+ bool enc_zlib_ok;
137+ bool enc_resize_ok;
138++ bool enc_extkeyevent_ok;
139+
140++ bool enc_extkeyevent_send;
141++
142+ z_stream zstream;
143+ uint8_t *zbuf;
144+ int zbuflen;
145+@@ -145,7 +148,10 @@ struct rfb_pixfmt_msg {
146+ #define RFB_ENCODING_RAW 0
147+ #define RFB_ENCODING_ZLIB 6
148+ #define RFB_ENCODING_RESIZE -223
149++#define RFB_ENCODING_EXT_KEYEVENT -258
150+
151++#define RFB_CLIENTMSG_EXT_KEYEVENT 0
152++
153+ #define RFB_MAX_WIDTH 2000
154+ #define RFB_MAX_HEIGHT 1200
155+ #define RFB_ZLIB_BUFSZ RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4
156+@@ -172,6 +178,19 @@ struct rfb_key_msg {
157+ uint8_t type;
158+ uint8_t down;
159+ uint16_t pad;
160++ uint32_t sym;
161++};
162++
163++struct rfb_client_msg {
164++ uint8_t type;
165++ uint8_t subtype;
166++};
167++
168++struct rfb_extended_key_msg {
169++ uint8_t type;
170++ uint8_t subtype;
171++ uint16_t down;
172++ uint32_t sym;
173+ uint32_t code;
174+ };
175+
176+@@ -250,6 +269,27 @@ rfb_send_resize_update_msg(struct rfb_softc *rc, int c
177+ }
178+
179+ static void
180++rfb_send_extended_keyevent_update_msg(struct rfb_softc *rc, int cfd)
181++{
182++ struct rfb_srvr_updt_msg supdt_msg;
183++ struct rfb_srvr_rect_hdr srect_hdr;
184++
185++ /* Number of rectangles: 1 */
186++ supdt_msg.type = 0;
187++ supdt_msg.pad = 0;
188++ supdt_msg.numrects = htons(1);
189++ stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg));
190++
191++ /* Rectangle header */
192++ srect_hdr.x = htons(0);
193++ srect_hdr.y = htons(0);
194++ srect_hdr.width = htons(rc->width);
195++ srect_hdr.height = htons(rc->height);
196++ srect_hdr.encoding = htonl(RFB_ENCODING_EXT_KEYEVENT);
197++ stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr));
198++}
199++
200++static void
201+ rfb_recv_set_pixfmt_msg(struct rfb_softc *rc, int cfd)
202+ {
203+ struct rfb_pixfmt_msg pixfmt_msg;
204+@@ -283,6 +323,9 @@ rfb_recv_set_encodings_msg(struct rfb_softc *rc, int c
205+ case RFB_ENCODING_RESIZE:
206+ rc->enc_resize_ok = true;
207+ break;
208++ case RFB_ENCODING_EXT_KEYEVENT:
209++ rc->enc_extkeyevent_ok = true;
210++ break;
211+ }
212+ }
213+ }
214+@@ -648,6 +691,11 @@ rfb_recv_update_msg(struct rfb_softc *rc, int cfd, int
215+ rfb_send_resize_update_msg(rc, cfd);
216+ }
217+
218++ if (rc->enc_extkeyevent_ok && (!rc->enc_extkeyevent_send)) {
219++ rfb_send_extended_keyevent_update_msg(rc, cfd);
220++ rc->enc_extkeyevent_send = true;
221++ }
222++
223+ if (discardonly)
224+ return;
225+
226+@@ -661,10 +709,24 @@ rfb_recv_key_msg(struct rfb_softc *rc, int cfd)
227+
228+ (void)stream_read(cfd, ((void *)&key_msg) + 1, sizeof(key_msg) - 1);
229+
230+- console_key_event(key_msg.down, htonl(key_msg.code));
231++ console_key_event(key_msg.down, htonl(key_msg.sym), htonl(0));
232+ }
233+
234+ static void
235++rfb_recv_client_msg(struct rfb_softc *rc, int cfd)
236++{
237++ struct rfb_client_msg client_msg;
238++ struct rfb_extended_key_msg extkey_msg;
239++
240++ (void)stream_read(cfd, ((void *)&client_msg) + 1, sizeof(client_msg) - 1);
241++
242++ if (client_msg.subtype == RFB_CLIENTMSG_EXT_KEYEVENT ) {
243++ (void)stream_read(cfd, ((void *)&extkey_msg) + 2, sizeof(extkey_msg) - 2);
244++ console_key_event((int)extkey_msg.down, htonl(extkey_msg.sym), htonl(extkey_msg.code));
245++ }
246++}
247++
248++static void
249+ rfb_recv_ptr_msg(struct rfb_softc *rc, int cfd)
250+ {
251+ struct rfb_ptr_msg ptr_msg;
252+@@ -903,6 +965,9 @@ rfb_handle(struct rfb_softc *rc, int cfd)
253+ case 6:
254+ rfb_recv_cuttext_msg(rc, cfd);
255+ break;
256++ case 255:
257++ rfb_recv_client_msg(rc, cfd);
258++ break;
259+ default:
260+ WPRINTF(("rfb unknown cli-code %d!", buf[0] & 0xff));
261+ goto done;
262+@@ -937,6 +1002,9 @@ rfb_thr(void *arg)
263+ rc->enc_raw_ok = false;
264+ rc->enc_zlib_ok = false;
265+ rc->enc_resize_ok = false;
266++ rc->enc_extkeyevent_ok = false;
267++
268++ rc->enc_extkeyevent_send = false;
269+
270+ cfd = accept(rc->sfd, NULL, NULL);
271+ if (rc->conn_wait) {