• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

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

javaandroidc++linuxc#windowsobjective-ccocoaqtpython誰得phprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

FreeBSD bhyve keyboard layout patch


コミットメタ情報

リビジョンb2a09ce2ef5c8996cd2f5154d13eaa97cf434d97 (tree)
日時2021-01-02 12:40:49
作者Koine Yuusuke(koinec) <koinec@user...>
コミッターKoine Yuusuke(koinec)

ログメッセージ

kbdlayout: regist old version(2020/05/29-v3: support for QEMU extended keyevent message)

変更サマリ

差分

--- a/kbdlayout_option/bhyve_kbdlayout_fbsd121r.patch
+++ b/kbdlayout_option/bhyve_kbdlayout_fbsd121r.patch
@@ -1,6 +1,6 @@
11 diff -upN bhyve_orig/Makefile bhyve/Makefile
22 --- bhyve_orig/Makefile 2020-05-01 11:25:57.446272000 +0900
3-+++ bhyve/Makefile 2020-04-28 21:10:08.503651000 +0900
3++++ bhyve/Makefile 2020-05-28 09:25:47.142698000 +0900
44 @@ -95,4 +95,6 @@ CFLAGS+=-DGDB_LOG
55
66 WARNS?= 2
@@ -8,9 +8,41 @@ diff -upN bhyve_orig/Makefile bhyve/Makefile
88 +SUBDIR= kbdlayout
99 +
1010 .include <bsd.prog.mk>
11+diff -upN bhyve_orig/atkbdc.c bhyve/atkbdc.c
12+--- bhyve_orig/atkbdc.c 2020-05-01 11:25:57.441270000 +0900
13++++ bhyve/atkbdc.c 2020-05-28 16:28:56.411057000 +0900
14+@@ -211,24 +211,25 @@ atkbdc_kbd_read(struct atkbdc_softc *sc)
15+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
16+ };
17+ uint8_t val;
18++ uint8_t trans;
19+ uint8_t release = 0;
20+
21+ assert(pthread_mutex_isowned_np(&sc->mtx));
22+
23+ if (sc->ram[0] & KBD_TRANSLATION) {
24+- while (ps2kbd_read(sc->ps2kbd_sc, &val) != -1) {
25++ while (ps2kbd_read(sc->ps2kbd_sc, &val, &trans) != -1) {
26+ if (val == 0xf0) {
27+ release = 0x80;
28+ continue;
29+ } else {
30+- val = translation[val] | release;
31++ val = ((trans) ? translation[val] : val) | release;
32+ }
33+ atkbdc_kbd_queue_data(sc, val);
34+ break;
35+ }
36+ } else {
37+ while (sc->kbd.bcnt < FIFOSZ) {
38+- if (ps2kbd_read(sc->ps2kbd_sc, &val) != -1)
39++ if (ps2kbd_read(sc->ps2kbd_sc, &val, &trans) != -1)
40+ atkbdc_kbd_queue_data(sc, val);
41+ else
42+ break;
1143 diff -upN bhyve_orig/bhyve.8 bhyve/bhyve.8
1244 --- bhyve_orig/bhyve.8 2020-05-01 11:25:57.441891000 +0900
13-+++ bhyve/bhyve.8 2020-05-01 12:24:39.448446000 +0900
45++++ bhyve/bhyve.8 2020-05-28 14:26:02.139585000 +0900
1446 @@ -44,6 +44,7 @@
1547 .Op Ar ,threads=n
1648 .Oc
@@ -19,7 +51,7 @@ diff -upN bhyve_orig/bhyve.8 bhyve/bhyve.8
1951 .Op Fl l Ar help|lpcdev Ns Op , Ns Ar conf
2052 .Op Fl m Ar memsize Ns Op Ar K|k|M|m|G|g|T|t
2153 .Op Fl p Ar vcpu:hostcpu
22-@@ -144,6 +145,12 @@ Print help message and exit.
54+@@ -144,6 +145,13 @@ Print help message and exit.
2355 .It Fl H
2456 Yield the virtual CPU thread when a HLT instruction is detected.
2557 If this option is not specified, virtual CPUs will use 100% of a host CPU.
@@ -28,13 +60,14 @@ diff -upN bhyve_orig/bhyve.8 bhyve/bhyve.8
2860 +The value that can be specified sets the file name in
2961 +.Ar /usr/share/bhyve/kbdlayout .
3062 +This specification only works when loaded with UEFI mode.(Not working via console or SSH)
31-+If not specified, the US keyboard layout(default) is specified.
63++If you are using a VNC client that supports QEMU Extended Key Event Message (e.g. TigerVNC), don't need to specify this option.
64++If you are using a VNC client that doesn't support it(e.g. tightVNC), and you don't specify this option, the US keyboard layout(default) is specified.
3265 .It Fl l Op Ar help|lpcdev Ns Op , Ns Ar conf
3366 Allow devices behind the LPC PCI-ISA bridge to be configured.
3467 The only supported devices are the TTY-class devices
3568 diff -upN bhyve_orig/bhyverun.c bhyve/bhyverun.c
3669 --- bhyve_orig/bhyverun.c 2020-05-01 11:25:57.439138000 +0900
37-+++ bhyve/bhyverun.c 2020-05-01 11:56:57.568136000 +0900
70++++ bhyve/bhyverun.c 2020-05-28 09:25:47.144660000 +0900
3871 @@ -165,6 +165,8 @@ char *vmname;
3972 int guest_ncpus;
4073 uint16_t cores, maxcpus, sockets, threads;
@@ -84,7 +117,7 @@ diff -upN bhyve_orig/bhyverun.c bhyve/bhyverun.c
84117 if (strncmp(optarg, "help", strlen(optarg)) == 0) {
85118 diff -upN bhyve_orig/bhyverun.h bhyve/bhyverun.h
86119 --- bhyve_orig/bhyverun.h 2020-05-01 11:25:57.444136000 +0900
87-+++ bhyve/bhyverun.h 2020-04-28 20:51:08.322277000 +0900
120++++ bhyve/bhyverun.h 2020-05-28 09:25:47.145111000 +0900
88121 @@ -39,6 +39,7 @@ extern int guest_ncpus;
89122 extern uint16_t cores, sockets, threads;
90123 extern char *guest_uuid_str;
@@ -93,10 +126,47 @@ diff -upN bhyve_orig/bhyverun.h bhyve/bhyverun.h
93126
94127 void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len);
95128
129+diff -upN bhyve_orig/console.c bhyve/console.c
130+--- bhyve_orig/console.c 2020-05-01 11:25:57.441001000 +0900
131++++ bhyve/console.c 2020-05-28 10:47:10.699395000 +0900
132+@@ -106,10 +106,10 @@ console_ptr_register(ptr_event_func_t event_cb, void *
133+ }
134+
135+ void
136+-console_key_event(int down, uint32_t keysym)
137++console_key_event(int down, uint32_t keysym, uint32_t keycode)
138+ {
139+ if (console.kbd_event_cb)
140+- (*console.kbd_event_cb)(down, keysym, console.kbd_arg);
141++ (*console.kbd_event_cb)(down, keysym, keycode, console.kbd_arg);
142+ }
143+
144+ void
145+diff -upN bhyve_orig/console.h bhyve/console.h
146+--- bhyve_orig/console.h 2020-05-01 11:25:57.446732000 +0900
147++++ bhyve/console.h 2020-05-28 10:47:47.290438000 +0900
148+@@ -34,7 +34,7 @@
149+ struct bhyvegc;
150+
151+ typedef void (*fb_render_func_t)(struct bhyvegc *gc, void *arg);
152+-typedef void (*kbd_event_func_t)(int down, uint32_t keysym, void *arg);
153++typedef void (*kbd_event_func_t)(int down, uint32_t keysym, uint32_t keycode, void *arg);
154+ typedef void (*ptr_event_func_t)(uint8_t mask, int x, int y, void *arg);
155+
156+ void console_init(int w, int h, void *fbaddr);
157+@@ -47,7 +47,7 @@ void console_fb_register(fb_render_func_t render_cb, v
158+ void console_refresh(void);
159+
160+ void console_kbd_register(kbd_event_func_t event_cb, void *arg, int pri);
161+-void console_key_event(int down, uint32_t keysym);
162++void console_key_event(int down, uint32_t keysym, uint32_t keycode);
163+
164+ void console_ptr_register(ptr_event_func_t event_cb, void *arg, int pri);
165+ void console_ptr_event(uint8_t button, int x, int y);
96166 Common subdirectories: bhyve_orig/kbdlayout and bhyve/kbdlayout
97167 diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
98168 --- bhyve_orig/ps2kbd.c 2020-05-01 11:25:57.446548000 +0900
99-+++ bhyve/ps2kbd.c 2020-04-30 21:16:15.390220000 +0900
169++++ bhyve/ps2kbd.c 2020-05-28 16:28:16.325233000 +0900
100170 @@ -31,15 +31,20 @@
101171 __FBSDID("$FreeBSD: releng/12.1/usr.sbin/bhyve/ps2kbd.c 341757 2018-12-09 06:41:57Z araujo $");
102172
@@ -118,7 +188,7 @@ diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
118188 #include "atkbdc.h"
119189 #include "console.h"
120190
121-@@ -58,6 +63,8 @@ __FBSDID("$FreeBSD: releng/12.1/usr.sbin/bhyve/ps2kbd.
191+@@ -58,8 +63,11 @@ __FBSDID("$FreeBSD: releng/12.1/usr.sbin/bhyve/ps2kbd.
122192
123193 #define PS2KBD_FIFOSZ 16
124194
@@ -126,8 +196,11 @@ diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
126196 +
127197 struct fifo {
128198 uint8_t buf[PS2KBD_FIFOSZ];
199++ uint8_t trans[PS2KBD_FIFOSZ];
129200 int rindex; /* index to read from */
130-@@ -86,7 +93,7 @@ struct extended_translation {
201+ int windex; /* index to write to */
202+ int num; /* number of bytes in the fifo */
203+@@ -86,7 +94,7 @@ struct extended_translation {
131204 /*
132205 * FIXME: Pause/break and Print Screen/SysRq require special handling.
133206 */
@@ -136,7 +209,7 @@ diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
136209 {0xff08, 0x66}, /* Back space */
137210 {0xff09, 0x0d}, /* Tab */
138211 {0xff0d, 0x5a}, /* Return */
139-@@ -158,7 +165,7 @@ static const struct extended_translation extended_tran
212+@@ -158,7 +166,7 @@ static const struct extended_translation extended_tran
140213 };
141214
142215 /* ASCII to type 2 scancode lookup table */
@@ -145,16 +218,197 @@ diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
145218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148-@@ -316,7 +323,7 @@ ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
221+@@ -197,26 +205,28 @@ fifo_reset(struct ps2kbd_softc *sc)
222+ }
223+
224+ static void
225+-fifo_put(struct ps2kbd_softc *sc, uint8_t val)
226++fifo_put(struct ps2kbd_softc *sc, uint8_t val, uint8_t trans)
227+ {
228+ struct fifo *fifo;
229+
230+ fifo = &sc->fifo;
231+ if (fifo->num < fifo->size) {
232+ fifo->buf[fifo->windex] = val;
233++ fifo->trans[fifo->windex] = trans;
234+ fifo->windex = (fifo->windex + 1) % fifo->size;
235+ fifo->num++;
236+ }
237+ }
238+
239+ static int
240+-fifo_get(struct ps2kbd_softc *sc, uint8_t *val)
241++fifo_get(struct ps2kbd_softc *sc, uint8_t *val, uint8_t *trans)
242+ {
243+ struct fifo *fifo;
244+
245+ fifo = &sc->fifo;
246+ if (fifo->num > 0) {
247+ *val = fifo->buf[fifo->rindex];
248++ *trans = fifo->trans[fifo->rindex];
249+ fifo->rindex = (fifo->rindex + 1) % fifo->size;
250+ fifo->num--;
251+ return (0);
252+@@ -226,12 +236,12 @@ fifo_get(struct ps2kbd_softc *sc, uint8_t *val)
253+ }
254+
255+ int
256+-ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val)
257++ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val, uint8_t *trans)
258+ {
259+ int retval;
260+
261+ pthread_mutex_lock(&sc->mtx);
262+- retval = fifo_get(sc, val);
263++ retval = fifo_get(sc, val, trans);
264+ pthread_mutex_unlock(&sc->mtx);
265+
266+ return (retval);
267+@@ -244,13 +254,13 @@ ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val)
268+ if (sc->curcmd) {
269+ switch (sc->curcmd) {
270+ case PS2KC_SET_TYPEMATIC:
271+- fifo_put(sc, PS2KC_ACK);
272++ fifo_put(sc, PS2KC_ACK, 0);
273+ break;
274+ case PS2KC_SET_SCANCODE_SET:
275+- fifo_put(sc, PS2KC_ACK);
276++ fifo_put(sc, PS2KC_ACK, 0);
277+ break;
278+ case PS2KC_SET_LEDS:
279+- fifo_put(sc, PS2KC_ACK);
280++ fifo_put(sc, PS2KC_ACK, 0);
281+ break;
282+ default:
283+ fprintf(stderr, "Unhandled ps2 keyboard current "
284+@@ -261,41 +271,41 @@ ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val)
285+ } else {
286+ switch (val) {
287+ case 0x00:
288+- fifo_put(sc, PS2KC_ACK);
289++ fifo_put(sc, PS2KC_ACK, 0);
290+ break;
291+ case PS2KC_RESET_DEV:
292+ fifo_reset(sc);
293+- fifo_put(sc, PS2KC_ACK);
294+- fifo_put(sc, PS2KC_BAT_SUCCESS);
295++ fifo_put(sc, PS2KC_ACK, 0);
296++ fifo_put(sc, PS2KC_BAT_SUCCESS, 0);
297+ break;
298+ case PS2KC_DISABLE:
299+ sc->enabled = false;
300+- fifo_put(sc, PS2KC_ACK);
301++ fifo_put(sc, PS2KC_ACK, 0);
302+ break;
303+ case PS2KC_ENABLE:
304+ sc->enabled = true;
305+ fifo_reset(sc);
306+- fifo_put(sc, PS2KC_ACK);
307++ fifo_put(sc, PS2KC_ACK, 0);
308+ break;
309+ case PS2KC_SET_TYPEMATIC:
310+ sc->curcmd = val;
311+- fifo_put(sc, PS2KC_ACK);
312++ fifo_put(sc, PS2KC_ACK, 0);
313+ break;
314+ case PS2KC_SEND_DEV_ID:
315+- fifo_put(sc, PS2KC_ACK);
316+- fifo_put(sc, 0xab);
317+- fifo_put(sc, 0x83);
318++ fifo_put(sc, PS2KC_ACK, 0);
319++ fifo_put(sc, 0xab, 0);
320++ fifo_put(sc, 0x83, 0);
321+ break;
322+ case PS2KC_SET_SCANCODE_SET:
323+ sc->curcmd = val;
324+- fifo_put(sc, PS2KC_ACK);
325++ fifo_put(sc, PS2KC_ACK, 0);
326+ break;
327+ case PS2KC_ECHO:
328+- fifo_put(sc, PS2KC_ECHO);
329++ fifo_put(sc, PS2KC_ECHO, 0);
330+ break;
331+ case PS2KC_SET_LEDS:
332+ sc->curcmd = val;
333+- fifo_put(sc, PS2KC_ACK);
334++ fifo_put(sc, PS2KC_ACK, 0);
335+ break;
336+ default:
337+ fprintf(stderr, "Unhandled ps2 keyboard command "
338+@@ -311,26 +321,32 @@ ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val)
339+ */
340+ static void
341+ ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
342+- int down, uint32_t keysym)
343++ int down, uint32_t keysym, uint32_t keycode)
344+ {
149345 assert(pthread_mutex_isowned_np(&sc->mtx));
150346 int e0_prefix, found;
151347 uint8_t code;
152348 - const struct extended_translation *trans;
153349 + struct extended_translation *trans;
154350
155- found = 0;
156- if (keysym < 0x80) {
157-@@ -366,10 +373,91 @@ ps2kbd_event(int down, uint32_t keysym, void *arg)
351+- found = 0;
352+- if (keysym < 0x80) {
353+- code = ascii_translations[keysym];
354+- e0_prefix = 0;
355++ if (keycode) {
356++ code = (uint8_t)(keycode & 0x7f);
357++ e0_prefix = ((keycode & 0x80) ? SCANCODE_E0_PREFIX : 0);
358+ found = 1;
359+ } else {
360+- for (trans = &(extended_translations[0]); trans->keysym != 0;
361+- trans++) {
362+- if (keysym == trans->keysym) {
363+- code = trans->scancode;
364+- e0_prefix = trans->flags & SCANCODE_E0_PREFIX;
365+- found = 1;
366+- break;
367++ found = 0;
368++ if (keysym < 0x80) {
369++ code = ascii_translations[keysym];
370++ e0_prefix = 0;
371++ found = 1;
372++ } else {
373++ for (trans = &(extended_translations[0]); trans->keysym != 0;
374++ trans++) {
375++ if (keysym == trans->keysym) {
376++ code = trans->scancode;
377++ e0_prefix = trans->flags & SCANCODE_E0_PREFIX;
378++ found = 1;
379++ break;
380++ }
381+ }
382+ }
383+ }
384+@@ -341,14 +357,14 @@ ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
385+ }
386+
387+ if (e0_prefix)
388+- fifo_put(sc, 0xe0);
389++ fifo_put(sc, 0xe0, 0);
390+ if (!down)
391+- fifo_put(sc, 0xf0);
392+- fifo_put(sc, code);
393++ fifo_put(sc, 0xf0, 0);
394++ fifo_put(sc, code, (keycode ? 0 : 1));
395+ }
396+
397+ static void
398+-ps2kbd_event(int down, uint32_t keysym, void *arg)
399++ps2kbd_event(int down, uint32_t keysym, uint32_t keycode, void *arg)
400+ {
401+ struct ps2kbd_softc *sc = arg;
402+ int fifo_full;
403+@@ -359,17 +375,98 @@ ps2kbd_event(int down, uint32_t keysym, void *arg)
404+ return;
405+ }
406+ fifo_full = sc->fifo.num == PS2KBD_FIFOSZ;
407+- ps2kbd_keysym_queue(sc, down, keysym);
408++ ps2kbd_keysym_queue(sc, down, keysym, keycode);
409+ pthread_mutex_unlock(&sc->mtx);
410+
411+ if (!fifo_full)
158412 atkbdc_event(sc->atkbdc_sc, 1);
159413 }
160414
@@ -246,3 +500,156 @@ diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
246500
247501 sc = calloc(1, sizeof (struct ps2kbd_softc));
248502 pthread_mutex_init(&sc->mtx, NULL);
503+diff -upN bhyve_orig/ps2kbd.h bhyve/ps2kbd.h
504+--- bhyve_orig/ps2kbd.h 2020-05-01 11:25:57.441775000 +0900
505++++ bhyve/ps2kbd.h 2020-05-28 13:42:50.937234000 +0900
506+@@ -35,7 +35,7 @@ struct atkbdc_softc;
507+
508+ struct ps2kbd_softc *ps2kbd_init(struct atkbdc_softc *sc);
509+
510+-int ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val);
511++int ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val, uint8_t *trans);
512+ void ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val);
513+
514+ #endif /* _PS2KBD_H_ */
515+diff -upN bhyve_orig/rfb.c bhyve/rfb.c
516+--- bhyve_orig/rfb.c 2020-05-01 11:25:57.446856000 +0900
517++++ bhyve/rfb.c 2020-05-28 13:16:38.135646000 +0900
518+@@ -97,7 +97,10 @@ struct rfb_softc {
519+ bool enc_raw_ok;
520+ bool enc_zlib_ok;
521+ bool enc_resize_ok;
522++ bool enc_extkeyevent_ok;
523+
524++ bool enc_extkeyevent_send;
525++
526+ z_stream zstream;
527+ uint8_t *zbuf;
528+ int zbuflen;
529+@@ -143,7 +146,10 @@ struct rfb_pixfmt_msg {
530+ #define RFB_ENCODING_RAW 0
531+ #define RFB_ENCODING_ZLIB 6
532+ #define RFB_ENCODING_RESIZE -223
533++#define RFB_ENCODING_EXT_KEYEVENT -258
534+
535++#define RFB_CLIENTMSG_EXT_KEYEVENT 0
536++
537+ #define RFB_MAX_WIDTH 2000
538+ #define RFB_MAX_HEIGHT 1200
539+ #define RFB_ZLIB_BUFSZ RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4
540+@@ -170,6 +176,19 @@ struct rfb_key_msg {
541+ uint8_t type;
542+ uint8_t down;
543+ uint16_t pad;
544++ uint32_t sym;
545++};
546++
547++struct rfb_client_msg {
548++ uint8_t type;
549++ uint8_t subtype;
550++};
551++
552++struct rfb_extended_key_msg {
553++ uint8_t type;
554++ uint8_t subtype;
555++ uint16_t down;
556++ uint32_t sym;
557+ uint32_t code;
558+ };
559+
560+@@ -248,6 +267,27 @@ rfb_send_resize_update_msg(struct rfb_softc *rc, int c
561+ }
562+
563+ static void
564++rfb_send_extended_keyevent_update_msg(struct rfb_softc *rc, int cfd)
565++{
566++ struct rfb_srvr_updt_msg supdt_msg;
567++ struct rfb_srvr_rect_hdr srect_hdr;
568++
569++ /* Number of rectangles: 1 */
570++ supdt_msg.type = 0;
571++ supdt_msg.pad = 0;
572++ supdt_msg.numrects = htons(1);
573++ stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg));
574++
575++ /* Rectangle header */
576++ srect_hdr.x = htons(0);
577++ srect_hdr.y = htons(0);
578++ srect_hdr.width = htons(rc->width);
579++ srect_hdr.height = htons(rc->height);
580++ srect_hdr.encoding = htonl(RFB_ENCODING_EXT_KEYEVENT);
581++ stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr));
582++}
583++
584++static void
585+ rfb_recv_set_pixfmt_msg(struct rfb_softc *rc, int cfd)
586+ {
587+ struct rfb_pixfmt_msg pixfmt_msg;
588+@@ -281,6 +321,9 @@ rfb_recv_set_encodings_msg(struct rfb_softc *rc, int c
589+ case RFB_ENCODING_RESIZE:
590+ rc->enc_resize_ok = true;
591+ break;
592++ case RFB_ENCODING_EXT_KEYEVENT:
593++ rc->enc_extkeyevent_ok = true;
594++ break;
595+ }
596+ }
597+ }
598+@@ -646,6 +689,11 @@ rfb_recv_update_msg(struct rfb_softc *rc, int cfd, int
599+ rfb_send_resize_update_msg(rc, cfd);
600+ }
601+
602++ if (rc->enc_extkeyevent_ok && (!rc->enc_extkeyevent_send)) {
603++ rfb_send_extended_keyevent_update_msg(rc, cfd);
604++ rc->enc_extkeyevent_send = true;
605++ }
606++
607+ if (discardonly)
608+ return;
609+
610+@@ -659,10 +707,24 @@ rfb_recv_key_msg(struct rfb_softc *rc, int cfd)
611+
612+ (void)stream_read(cfd, ((void *)&key_msg) + 1, sizeof(key_msg) - 1);
613+
614+- console_key_event(key_msg.down, htonl(key_msg.code));
615++ console_key_event(key_msg.down, htonl(key_msg.sym), htonl(0));
616+ }
617+
618+ static void
619++rfb_recv_client_msg(struct rfb_softc *rc, int cfd)
620++{
621++ struct rfb_client_msg client_msg;
622++ struct rfb_extended_key_msg extkey_msg;
623++
624++ (void)stream_read(cfd, ((void *)&client_msg) + 1, sizeof(client_msg) - 1);
625++
626++ if (client_msg.subtype == RFB_CLIENTMSG_EXT_KEYEVENT ) {
627++ (void)stream_read(cfd, ((void *)&extkey_msg) + 2, sizeof(extkey_msg) - 2);
628++ console_key_event((int)extkey_msg.down, htonl(extkey_msg.sym), htonl(extkey_msg.code));
629++ }
630++}
631++
632++static void
633+ rfb_recv_ptr_msg(struct rfb_softc *rc, int cfd)
634+ {
635+ struct rfb_ptr_msg ptr_msg;
636+@@ -901,6 +963,9 @@ rfb_handle(struct rfb_softc *rc, int cfd)
637+ case 6:
638+ rfb_recv_cuttext_msg(rc, cfd);
639+ break;
640++ case 255:
641++ rfb_recv_client_msg(rc, cfd);
642++ break;
643+ default:
644+ WPRINTF(("rfb unknown cli-code %d!\n", buf[0] & 0xff));
645+ goto done;
646+@@ -935,6 +1000,9 @@ rfb_thr(void *arg)
647+ rc->enc_raw_ok = false;
648+ rc->enc_zlib_ok = false;
649+ rc->enc_resize_ok = false;
650++ rc->enc_extkeyevent_ok = false;
651++
652++ rc->enc_extkeyevent_send = false;
653+
654+ cfd = accept(rc->sfd, NULL, NULL);
655+ if (rc->conn_wait) {
--- a/kbdlayout_option/bhyve_kbdlayout_fbsd13c.patch
+++ b/kbdlayout_option/bhyve_kbdlayout_fbsd13c.patch
@@ -1,6 +1,6 @@
11 diff -upN bhyve_orig/Makefile bhyve/Makefile
22 --- bhyve_orig/Makefile 2020-04-23 09:06:39.000000000 +0900
3-+++ bhyve/Makefile 2020-05-02 13:09:01.382770000 +0900
3++++ bhyve/Makefile 2020-05-29 18:03:10.627095000 +0900
44 @@ -99,4 +99,6 @@ CFLAGS+=-DGDB_LOG
55
66 WARNS?= 2
@@ -8,9 +8,41 @@ diff -upN bhyve_orig/Makefile bhyve/Makefile
88 +SUBDIR= kbdlayout
99 +
1010 .include <bsd.prog.mk>
11+diff -upN bhyve_orig/atkbdc.c bhyve/atkbdc.c
12+--- bhyve_orig/atkbdc.c 2020-04-23 09:06:39.000000000 +0900
13++++ bhyve/atkbdc.c 2020-05-29 18:03:10.653893000 +0900
14+@@ -211,24 +211,25 @@ atkbdc_kbd_read(struct atkbdc_softc *sc)
15+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
16+ };
17+ uint8_t val;
18++ uint8_t trans;
19+ uint8_t release = 0;
20+
21+ assert(pthread_mutex_isowned_np(&sc->mtx));
22+
23+ if (sc->ram[0] & KBD_TRANSLATION) {
24+- while (ps2kbd_read(sc->ps2kbd_sc, &val) != -1) {
25++ while (ps2kbd_read(sc->ps2kbd_sc, &val, &trans) != -1) {
26+ if (val == 0xf0) {
27+ release = 0x80;
28+ continue;
29+ } else {
30+- val = translation[val] | release;
31++ val = ((trans) ? translation[val] : val) | release;
32+ }
33+ atkbdc_kbd_queue_data(sc, val);
34+ break;
35+ }
36+ } else {
37+ while (sc->kbd.bcnt < FIFOSZ) {
38+- if (ps2kbd_read(sc->ps2kbd_sc, &val) != -1)
39++ if (ps2kbd_read(sc->ps2kbd_sc, &val, &trans) != -1)
40+ atkbdc_kbd_queue_data(sc, val);
41+ else
42+ break;
1143 diff -upN bhyve_orig/bhyve.8 bhyve/bhyve.8
1244 --- bhyve_orig/bhyve.8 2020-04-23 09:06:39.000000000 +0900
13-+++ bhyve/bhyve.8 2020-05-02 13:11:28.198679000 +0900
45++++ bhyve/bhyve.8 2020-05-29 18:11:54.290185000 +0900
1446 @@ -47,6 +47,7 @@
1547 .Sm on
1648 .Op Fl G Ar port
@@ -19,7 +51,7 @@ diff -upN bhyve_orig/bhyve.8 bhyve/bhyve.8
1951 .Oo Fl l
2052 .Sm off
2153 .Cm help | Ar lpcdev Op Cm \&, Ar conf
22-@@ -161,6 +162,12 @@ Print help message and exit.
54+@@ -161,6 +162,13 @@ Print help message and exit.
2355 .It Fl H
2456 Yield the virtual CPU thread when a HLT instruction is detected.
2557 If this option is not specified, virtual CPUs will use 100% of a host CPU.
@@ -28,13 +60,14 @@ diff -upN bhyve_orig/bhyve.8 bhyve/bhyve.8
2860 +The value that can be specified sets the file name in
2961 +.Ar /usr/share/bhyve/kbdlayout .
3062 +This specification only works when loaded with UEFI mode.(Not working via console or SSH)
31-+If not specified, the US keyboard layout(default) is specified.
63++If you are using a VNC client that supports QEMU Extended Key Event Message (e.g. TigerVNC), don't need to specify this option.
64++If you are using a VNC client that doesn't support it(e.g. tightVNC), and you don't specify this option, the US keyboard layout(default) is specified.
3265 .It Fl l Op Ar help|lpcdev Ns Op , Ns Ar conf
3366 Allow devices behind the LPC PCI-ISA bridge to be configured.
3467 The only supported devices are the TTY-class devices
3568 diff -upN bhyve_orig/bhyverun.c bhyve/bhyverun.c
3669 --- bhyve_orig/bhyverun.c 2020-04-23 09:06:39.000000000 +0900
37-+++ bhyve/bhyverun.c 2020-05-02 13:09:01.437624000 +0900
70++++ bhyve/bhyverun.c 2020-05-29 18:03:10.699642000 +0900
3871 @@ -168,6 +168,8 @@ char *vmname;
3972 int guest_ncpus;
4073 uint16_t cores, maxcpus, sockets, threads;
@@ -84,7 +117,7 @@ diff -upN bhyve_orig/bhyverun.c bhyve/bhyverun.c
84117 if (strncmp(optarg, "help", strlen(optarg)) == 0) {
85118 diff -upN bhyve_orig/bhyverun.h bhyve/bhyverun.h
86119 --- bhyve_orig/bhyverun.h 2020-04-23 09:06:39.000000000 +0900
87-+++ bhyve/bhyverun.h 2020-05-02 13:09:01.444814000 +0900
120++++ bhyve/bhyverun.h 2020-05-29 18:03:10.703030000 +0900
88121 @@ -39,6 +39,7 @@ extern int guest_ncpus;
89122 extern uint16_t cores, sockets, threads;
90123 extern char *guest_uuid_str;
@@ -93,10 +126,47 @@ diff -upN bhyve_orig/bhyverun.h bhyve/bhyverun.h
93126
94127 void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len);
95128
129+diff -upN bhyve_orig/console.c bhyve/console.c
130+--- bhyve_orig/console.c 2020-04-23 09:06:39.000000000 +0900
131++++ bhyve/console.c 2020-05-29 18:03:10.705936000 +0900
132+@@ -106,10 +106,10 @@ console_ptr_register(ptr_event_func_t event_cb, void *
133+ }
134+
135+ void
136+-console_key_event(int down, uint32_t keysym)
137++console_key_event(int down, uint32_t keysym, uint32_t keycode)
138+ {
139+ if (console.kbd_event_cb)
140+- (*console.kbd_event_cb)(down, keysym, console.kbd_arg);
141++ (*console.kbd_event_cb)(down, keysym, keycode, console.kbd_arg);
142+ }
143+
144+ void
145+diff -upN bhyve_orig/console.h bhyve/console.h
146+--- bhyve_orig/console.h 2020-04-23 09:06:39.000000000 +0900
147++++ bhyve/console.h 2020-05-29 18:03:10.708779000 +0900
148+@@ -34,7 +34,7 @@
149+ struct bhyvegc;
150+
151+ typedef void (*fb_render_func_t)(struct bhyvegc *gc, void *arg);
152+-typedef void (*kbd_event_func_t)(int down, uint32_t keysym, void *arg);
153++typedef void (*kbd_event_func_t)(int down, uint32_t keysym, uint32_t keycode, void *arg);
154+ typedef void (*ptr_event_func_t)(uint8_t mask, int x, int y, void *arg);
155+
156+ void console_init(int w, int h, void *fbaddr);
157+@@ -47,7 +47,7 @@ void console_fb_register(fb_render_func_t render_cb, v
158+ void console_refresh(void);
159+
160+ void console_kbd_register(kbd_event_func_t event_cb, void *arg, int pri);
161+-void console_key_event(int down, uint32_t keysym);
162++void console_key_event(int down, uint32_t keysym, uint32_t keycode);
163+
164+ void console_ptr_register(ptr_event_func_t event_cb, void *arg, int pri);
165+ void console_ptr_event(uint8_t button, int x, int y);
96166 Common subdirectories: bhyve_orig/kbdlayout and bhyve/kbdlayout
97167 diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
98168 --- bhyve_orig/ps2kbd.c 2020-04-23 09:06:39.000000000 +0900
99-+++ bhyve/ps2kbd.c 2020-05-02 13:09:01.462761000 +0900
169++++ bhyve/ps2kbd.c 2020-05-29 18:03:10.788431000 +0900
100170 @@ -31,15 +31,20 @@
101171 __FBSDID("$FreeBSD: head/usr.sbin/bhyve/ps2kbd.c 356523 2020-01-08 22:55:22Z vmaffione $");
102172
@@ -118,7 +188,7 @@ diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
118188 #include "atkbdc.h"
119189 #include "debug.h"
120190 #include "console.h"
121-@@ -59,6 +64,8 @@ __FBSDID("$FreeBSD: head/usr.sbin/bhyve/ps2kbd.c 35652
191+@@ -59,8 +64,11 @@ __FBSDID("$FreeBSD: head/usr.sbin/bhyve/ps2kbd.c 35652
122192
123193 #define PS2KBD_FIFOSZ 16
124194
@@ -126,8 +196,11 @@ diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
126196 +
127197 struct fifo {
128198 uint8_t buf[PS2KBD_FIFOSZ];
199++ uint8_t trans[PS2KBD_FIFOSZ];
129200 int rindex; /* index to read from */
130-@@ -87,7 +94,7 @@ struct extended_translation {
201+ int windex; /* index to write to */
202+ int num; /* number of bytes in the fifo */
203+@@ -87,7 +95,7 @@ struct extended_translation {
131204 /*
132205 * FIXME: Pause/break and Print Screen/SysRq require special handling.
133206 */
@@ -136,7 +209,7 @@ diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
136209 {0xff08, 0x66}, /* Back space */
137210 {0xff09, 0x0d}, /* Tab */
138211 {0xff0d, 0x5a}, /* Return */
139-@@ -159,7 +166,7 @@ static const struct extended_translation extended_tran
212+@@ -159,7 +167,7 @@ static const struct extended_translation extended_tran
140213 };
141214
142215 /* ASCII to type 2 scancode lookup table */
@@ -145,16 +218,197 @@ diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
145218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148-@@ -317,7 +324,7 @@ ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
221+@@ -198,26 +206,28 @@ fifo_reset(struct ps2kbd_softc *sc)
222+ }
223+
224+ static void
225+-fifo_put(struct ps2kbd_softc *sc, uint8_t val)
226++fifo_put(struct ps2kbd_softc *sc, uint8_t val, uint8_t trans)
227+ {
228+ struct fifo *fifo;
229+
230+ fifo = &sc->fifo;
231+ if (fifo->num < fifo->size) {
232+ fifo->buf[fifo->windex] = val;
233++ fifo->trans[fifo->windex] = trans;
234+ fifo->windex = (fifo->windex + 1) % fifo->size;
235+ fifo->num++;
236+ }
237+ }
238+
239+ static int
240+-fifo_get(struct ps2kbd_softc *sc, uint8_t *val)
241++fifo_get(struct ps2kbd_softc *sc, uint8_t *val, uint8_t *trans)
242+ {
243+ struct fifo *fifo;
244+
245+ fifo = &sc->fifo;
246+ if (fifo->num > 0) {
247+ *val = fifo->buf[fifo->rindex];
248++ *trans = fifo->trans[fifo->rindex];
249+ fifo->rindex = (fifo->rindex + 1) % fifo->size;
250+ fifo->num--;
251+ return (0);
252+@@ -227,12 +237,12 @@ fifo_get(struct ps2kbd_softc *sc, uint8_t *val)
253+ }
254+
255+ int
256+-ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val)
257++ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val, uint8_t *trans)
258+ {
259+ int retval;
260+
261+ pthread_mutex_lock(&sc->mtx);
262+- retval = fifo_get(sc, val);
263++ retval = fifo_get(sc, val, trans);
264+ pthread_mutex_unlock(&sc->mtx);
265+
266+ return (retval);
267+@@ -245,13 +255,13 @@ ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val)
268+ if (sc->curcmd) {
269+ switch (sc->curcmd) {
270+ case PS2KC_SET_TYPEMATIC:
271+- fifo_put(sc, PS2KC_ACK);
272++ fifo_put(sc, PS2KC_ACK, 0);
273+ break;
274+ case PS2KC_SET_SCANCODE_SET:
275+- fifo_put(sc, PS2KC_ACK);
276++ fifo_put(sc, PS2KC_ACK, 0);
277+ break;
278+ case PS2KC_SET_LEDS:
279+- fifo_put(sc, PS2KC_ACK);
280++ fifo_put(sc, PS2KC_ACK, 0);
281+ break;
282+ default:
283+ EPRINTLN("Unhandled ps2 keyboard current "
284+@@ -262,41 +272,41 @@ ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val)
285+ } else {
286+ switch (val) {
287+ case 0x00:
288+- fifo_put(sc, PS2KC_ACK);
289++ fifo_put(sc, PS2KC_ACK, 0);
290+ break;
291+ case PS2KC_RESET_DEV:
292+ fifo_reset(sc);
293+- fifo_put(sc, PS2KC_ACK);
294+- fifo_put(sc, PS2KC_BAT_SUCCESS);
295++ fifo_put(sc, PS2KC_ACK, 0);
296++ fifo_put(sc, PS2KC_BAT_SUCCESS, 0);
297+ break;
298+ case PS2KC_DISABLE:
299+ sc->enabled = false;
300+- fifo_put(sc, PS2KC_ACK);
301++ fifo_put(sc, PS2KC_ACK, 0);
302+ break;
303+ case PS2KC_ENABLE:
304+ sc->enabled = true;
305+ fifo_reset(sc);
306+- fifo_put(sc, PS2KC_ACK);
307++ fifo_put(sc, PS2KC_ACK, 0);
308+ break;
309+ case PS2KC_SET_TYPEMATIC:
310+ sc->curcmd = val;
311+- fifo_put(sc, PS2KC_ACK);
312++ fifo_put(sc, PS2KC_ACK, 0);
313+ break;
314+ case PS2KC_SEND_DEV_ID:
315+- fifo_put(sc, PS2KC_ACK);
316+- fifo_put(sc, 0xab);
317+- fifo_put(sc, 0x83);
318++ fifo_put(sc, PS2KC_ACK, 0);
319++ fifo_put(sc, 0xab, 0);
320++ fifo_put(sc, 0x83, 0);
321+ break;
322+ case PS2KC_SET_SCANCODE_SET:
323+ sc->curcmd = val;
324+- fifo_put(sc, PS2KC_ACK);
325++ fifo_put(sc, PS2KC_ACK, 0);
326+ break;
327+ case PS2KC_ECHO:
328+- fifo_put(sc, PS2KC_ECHO);
329++ fifo_put(sc, PS2KC_ECHO, 0);
330+ break;
331+ case PS2KC_SET_LEDS:
332+ sc->curcmd = val;
333+- fifo_put(sc, PS2KC_ACK);
334++ fifo_put(sc, PS2KC_ACK, 0);
335+ break;
336+ default:
337+ EPRINTLN("Unhandled ps2 keyboard command "
338+@@ -312,26 +322,32 @@ ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val)
339+ */
340+ static void
341+ ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
342+- int down, uint32_t keysym)
343++ int down, uint32_t keysym, uint32_t keycode)
344+ {
149345 assert(pthread_mutex_isowned_np(&sc->mtx));
150346 int e0_prefix, found;
151347 uint8_t code;
152348 - const struct extended_translation *trans;
153349 + struct extended_translation *trans;
154350
155- found = 0;
156- if (keysym < 0x80) {
157-@@ -367,10 +374,91 @@ ps2kbd_event(int down, uint32_t keysym, void *arg)
351+- found = 0;
352+- if (keysym < 0x80) {
353+- code = ascii_translations[keysym];
354+- e0_prefix = 0;
355++ if (keycode) {
356++ code = (uint8_t)(keycode & 0x7f);
357++ e0_prefix = ((keycode & 0x80) ? SCANCODE_E0_PREFIX : 0);
358+ found = 1;
359+ } else {
360+- for (trans = &(extended_translations[0]); trans->keysym != 0;
361+- trans++) {
362+- if (keysym == trans->keysym) {
363+- code = trans->scancode;
364+- e0_prefix = trans->flags & SCANCODE_E0_PREFIX;
365+- found = 1;
366+- break;
367++ found = 0;
368++ if (keysym < 0x80) {
369++ code = ascii_translations[keysym];
370++ e0_prefix = 0;
371++ found = 1;
372++ } else {
373++ for (trans = &(extended_translations[0]); trans->keysym != 0;
374++ trans++) {
375++ if (keysym == trans->keysym) {
376++ code = trans->scancode;
377++ e0_prefix = trans->flags & SCANCODE_E0_PREFIX;
378++ found = 1;
379++ break;
380++ }
381+ }
382+ }
383+ }
384+@@ -342,14 +358,14 @@ ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
385+ }
386+
387+ if (e0_prefix)
388+- fifo_put(sc, 0xe0);
389++ fifo_put(sc, 0xe0, 0);
390+ if (!down)
391+- fifo_put(sc, 0xf0);
392+- fifo_put(sc, code);
393++ fifo_put(sc, 0xf0, 0);
394++ fifo_put(sc, code, (keycode ? 0 : 1));
395+ }
396+
397+ static void
398+-ps2kbd_event(int down, uint32_t keysym, void *arg)
399++ps2kbd_event(int down, uint32_t keysym, uint32_t keycode, void *arg)
400+ {
401+ struct ps2kbd_softc *sc = arg;
402+ int fifo_full;
403+@@ -360,17 +376,98 @@ ps2kbd_event(int down, uint32_t keysym, void *arg)
404+ return;
405+ }
406+ fifo_full = sc->fifo.num == PS2KBD_FIFOSZ;
407+- ps2kbd_keysym_queue(sc, down, keysym);
408++ ps2kbd_keysym_queue(sc, down, keysym, keycode);
409+ pthread_mutex_unlock(&sc->mtx);
410+
411+ if (!fifo_full)
158412 atkbdc_event(sc->atkbdc_sc, 1);
159413 }
160414
@@ -246,3 +500,156 @@ diff -upN bhyve_orig/ps2kbd.c bhyve/ps2kbd.c
246500
247501 sc = calloc(1, sizeof (struct ps2kbd_softc));
248502 pthread_mutex_init(&sc->mtx, NULL);
503+diff -upN bhyve_orig/ps2kbd.h bhyve/ps2kbd.h
504+--- bhyve_orig/ps2kbd.h 2020-04-23 09:06:39.000000000 +0900
505++++ bhyve/ps2kbd.h 2020-05-29 18:03:10.795460000 +0900
506+@@ -35,7 +35,7 @@ struct atkbdc_softc;
507+
508+ struct ps2kbd_softc *ps2kbd_init(struct atkbdc_softc *sc);
509+
510+-int ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val);
511++int ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val, uint8_t *trans);
512+ void ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val);
513+
514+ #endif /* _PS2KBD_H_ */
515+diff -upN bhyve_orig/rfb.c bhyve/rfb.c
516+--- bhyve_orig/rfb.c 2020-04-23 09:06:39.000000000 +0900
517++++ bhyve/rfb.c 2020-05-29 18:03:10.843000000 +0900
518+@@ -99,7 +99,10 @@ struct rfb_softc {
519+ bool enc_raw_ok;
520+ bool enc_zlib_ok;
521+ bool enc_resize_ok;
522++ bool enc_extkeyevent_ok;
523+
524++ bool enc_extkeyevent_send;
525++
526+ z_stream zstream;
527+ uint8_t *zbuf;
528+ int zbuflen;
529+@@ -145,7 +148,10 @@ struct rfb_pixfmt_msg {
530+ #define RFB_ENCODING_RAW 0
531+ #define RFB_ENCODING_ZLIB 6
532+ #define RFB_ENCODING_RESIZE -223
533++#define RFB_ENCODING_EXT_KEYEVENT -258
534+
535++#define RFB_CLIENTMSG_EXT_KEYEVENT 0
536++
537+ #define RFB_MAX_WIDTH 2000
538+ #define RFB_MAX_HEIGHT 1200
539+ #define RFB_ZLIB_BUFSZ RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4
540+@@ -172,6 +178,19 @@ struct rfb_key_msg {
541+ uint8_t type;
542+ uint8_t down;
543+ uint16_t pad;
544++ uint32_t sym;
545++};
546++
547++struct rfb_client_msg {
548++ uint8_t type;
549++ uint8_t subtype;
550++};
551++
552++struct rfb_extended_key_msg {
553++ uint8_t type;
554++ uint8_t subtype;
555++ uint16_t down;
556++ uint32_t sym;
557+ uint32_t code;
558+ };
559+
560+@@ -250,6 +269,27 @@ rfb_send_resize_update_msg(struct rfb_softc *rc, int c
561+ }
562+
563+ static void
564++rfb_send_extended_keyevent_update_msg(struct rfb_softc *rc, int cfd)
565++{
566++ struct rfb_srvr_updt_msg supdt_msg;
567++ struct rfb_srvr_rect_hdr srect_hdr;
568++
569++ /* Number of rectangles: 1 */
570++ supdt_msg.type = 0;
571++ supdt_msg.pad = 0;
572++ supdt_msg.numrects = htons(1);
573++ stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg));
574++
575++ /* Rectangle header */
576++ srect_hdr.x = htons(0);
577++ srect_hdr.y = htons(0);
578++ srect_hdr.width = htons(rc->width);
579++ srect_hdr.height = htons(rc->height);
580++ srect_hdr.encoding = htonl(RFB_ENCODING_EXT_KEYEVENT);
581++ stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr));
582++}
583++
584++static void
585+ rfb_recv_set_pixfmt_msg(struct rfb_softc *rc, int cfd)
586+ {
587+ struct rfb_pixfmt_msg pixfmt_msg;
588+@@ -283,6 +323,9 @@ rfb_recv_set_encodings_msg(struct rfb_softc *rc, int c
589+ case RFB_ENCODING_RESIZE:
590+ rc->enc_resize_ok = true;
591+ break;
592++ case RFB_ENCODING_EXT_KEYEVENT:
593++ rc->enc_extkeyevent_ok = true;
594++ break;
595+ }
596+ }
597+ }
598+@@ -648,6 +691,11 @@ rfb_recv_update_msg(struct rfb_softc *rc, int cfd, int
599+ rfb_send_resize_update_msg(rc, cfd);
600+ }
601+
602++ if (rc->enc_extkeyevent_ok && (!rc->enc_extkeyevent_send)) {
603++ rfb_send_extended_keyevent_update_msg(rc, cfd);
604++ rc->enc_extkeyevent_send = true;
605++ }
606++
607+ if (discardonly)
608+ return;
609+
610+@@ -661,10 +709,24 @@ rfb_recv_key_msg(struct rfb_softc *rc, int cfd)
611+
612+ (void)stream_read(cfd, ((void *)&key_msg) + 1, sizeof(key_msg) - 1);
613+
614+- console_key_event(key_msg.down, htonl(key_msg.code));
615++ console_key_event(key_msg.down, htonl(key_msg.sym), htonl(0));
616+ }
617+
618+ static void
619++rfb_recv_client_msg(struct rfb_softc *rc, int cfd)
620++{
621++ struct rfb_client_msg client_msg;
622++ struct rfb_extended_key_msg extkey_msg;
623++
624++ (void)stream_read(cfd, ((void *)&client_msg) + 1, sizeof(client_msg) - 1);
625++
626++ if (client_msg.subtype == RFB_CLIENTMSG_EXT_KEYEVENT ) {
627++ (void)stream_read(cfd, ((void *)&extkey_msg) + 2, sizeof(extkey_msg) - 2);
628++ console_key_event((int)extkey_msg.down, htonl(extkey_msg.sym), htonl(extkey_msg.code));
629++ }
630++}
631++
632++static void
633+ rfb_recv_ptr_msg(struct rfb_softc *rc, int cfd)
634+ {
635+ struct rfb_ptr_msg ptr_msg;
636+@@ -903,6 +965,9 @@ rfb_handle(struct rfb_softc *rc, int cfd)
637+ case 6:
638+ rfb_recv_cuttext_msg(rc, cfd);
639+ break;
640++ case 255:
641++ rfb_recv_client_msg(rc, cfd);
642++ break;
643+ default:
644+ WPRINTF(("rfb unknown cli-code %d!", buf[0] & 0xff));
645+ goto done;
646+@@ -937,6 +1002,9 @@ rfb_thr(void *arg)
647+ rc->enc_raw_ok = false;
648+ rc->enc_zlib_ok = false;
649+ rc->enc_resize_ok = false;
650++ rc->enc_extkeyevent_ok = false;
651++
652++ rc->enc_extkeyevent_send = false;
653+
654+ cfd = accept(rc->sfd, NULL, NULL);
655+ if (rc->conn_wait) {