> Date: Thu, 29 Sep 2016 14:19:43 +0200 (CEST) > From: Mark Kettenis <mark.kette...@xs4all.nl> > > This diff adds a WSKBDIO_GETENCODINGS ioctl and uses it to print a > list of supported encodings like the old kvm groveling code did. The > ioctl will clamp the number of entries that are returns to the number > that was passed in. This means that if the number returned is the > same as the number passed in, there might be more entries and you > probably want to retry with a larger buffer. The new implementation > does this.
Thanks to tb@ for testing this on a ramdisk. Here is a slightly better diff that frees the allocated memory. ok? Index: sys/dev/wscons/wsconsio.h =================================================================== RCS file: /cvs/src/sys/dev/wscons/wsconsio.h,v retrieving revision 1.75 diff -u -p -r1.75 wsconsio.h --- sys/dev/wscons/wsconsio.h 14 Sep 2016 03:25:51 -0000 1.75 +++ sys/dev/wscons/wsconsio.h 29 Sep 2016 18:12:48 -0000 @@ -207,6 +207,12 @@ struct wskbd_backlight { #define WSKBD_TRANSLATED 0 #define WSKBD_RAW 1 +struct wskbd_encoding_data { + int nencodings; + kbd_t *encodings; +}; +#define WSKBDIO_GETENCODINGS _IOWR('W', 21, struct wskbd_encoding_data) + /* * Mouse ioctls (32 - 63) */ Index: sys/dev/wscons/wskbd.c =================================================================== RCS file: /cvs/src/sys/dev/wscons/wskbd.c,v retrieving revision 1.83 diff -u -p -r1.83 wskbd.c --- sys/dev/wscons/wskbd.c 12 Dec 2015 12:30:18 -0000 1.83 +++ sys/dev/wscons/wskbd.c 29 Sep 2016 18:12:48 -0000 @@ -1001,9 +1001,11 @@ wskbd_displayioctl(struct device *dev, u struct wskbd_bell_data *ubdp, *kbdp; struct wskbd_keyrepeat_data *ukdp, *kkdp; struct wskbd_map_data *umdp; + struct wskbd_encoding_data *uedp; kbd_t enc; void *buf; int len, error; + int count, i; switch (cmd) { case WSKBDIO_BELL: @@ -1159,6 +1161,20 @@ getkeyrepeat: wsmux_set_layout(sc->sc_base.me_parent, enc); #endif return (0); + + case WSKBDIO_GETENCODINGS: + uedp = (struct wskbd_encoding_data *)data; + for (count = 0; sc->id->t_keymap.keydesc[count].name; count++) + ; + if (uedp->nencodings > count) + uedp->nencodings = count; + for (i = 0; i < uedp->nencodings; i++) { + error = copyout(&sc->id->t_keymap.keydesc[i].name, + &uedp->encodings[i], sizeof(kbd_t)); + if (error) + return (error); + } + return(0); case WSKBDIO_GETBACKLIGHT: if (wskbd_get_backlight != NULL) Index: sbin/kbd/kbd_wscons.c =================================================================== RCS file: /cvs/src/sbin/kbd/kbd_wscons.c,v retrieving revision 1.30 diff -u -p -r1.30 kbd_wscons.c --- sbin/kbd/kbd_wscons.c 27 Sep 2016 22:03:49 -0000 1.30 +++ sbin/kbd/kbd_wscons.c 29 Sep 2016 18:12:48 -0000 @@ -34,6 +34,7 @@ #include <fcntl.h> #include <limits.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> @@ -82,31 +83,83 @@ struct nameint kbdvar_tab[] = { extern char *__progname; -void kbd_show_enc(int idx); +void kbd_show_enc(struct wskbd_encoding_data *encs, int idx); +void kbd_get_encs(int fd, struct wskbd_encoding_data *encs); void kbd_list(void); void kbd_set(char *name, int verbose); void -kbd_show_enc(int idx) +kbd_show_enc(struct wskbd_encoding_data *encs, int idx) { + int found; + kbd_t encoding, variant; + struct nameint *n; int i; printf("tables available for %s keyboard:\nencoding\n\n", kbtype_tab[idx]); - for (i = 0; kbdenc_tab[i].value; i++) - printf("%s\n", kbdenc_tab[i].name); + for (i = 0; i < encs->nencodings; i++) { + n = &kbdenc_tab[0]; + found = 0; + encoding = encs->encodings[i]; + while (n->value) { + if (n->value == KB_ENCODING(encoding)) { + printf("%s", n->name); + found++; + } + n++; + } + if (found == 0) + printf("<encoding 0x%04x>", KB_ENCODING(encoding)); + n = &kbdvar_tab[0]; + found = 0; + variant = KB_VARIANT(encoding); + while (n->value) { + if ((n->value & KB_VARIANT(encoding)) == n->value) { + printf(".%s", n->name); + variant &= ~n->value; + } + n++; + } + if (variant != 0) + printf(".<variant 0x%08x>", variant); + printf("\n"); + } printf("\n"); } void +kbd_get_encs(int fd, struct wskbd_encoding_data *encs) +{ + int nencodings = 64; + + encs->nencodings = nencodings; + while (encs->nencodings == nencodings) { + encs->encodings = reallocarray(encs->encodings, + encs->nencodings, sizeof(kbd_t)); + if (encs->encodings == NULL) + err(1, "reallocarray"); + if (ioctl(fd, WSKBDIO_GETENCODINGS, encs) < 0) + err(1, "WSKBDIO_GETENCODINGS"); + if (encs->nencodings == nencodings) { + nencodings *= 2; + encs->nencodings = nencodings; + } + } +} + +void kbd_list(void) { int kbds[SA_MAX]; - int fd, i, kbtype; + struct wskbd_encoding_data encs[SA_MAX]; + int fd, i, kbtype, t; char device[PATH_MAX]; + int j; - bzero(kbds, sizeof(kbds)); + memset(kbds, 0, sizeof(kbds)); + memset(encs, 0, sizeof(encs)); /* Go through all keyboards. */ for (i = 0; i < NUM_KBD; i++) { @@ -120,41 +173,53 @@ kbd_list(void) switch (kbtype) { case WSKBD_TYPE_PC_XT: case WSKBD_TYPE_PC_AT: - kbds[SA_PCKBD]++; + t = SA_PCKBD; break; case WSKBD_TYPE_USB: - kbds[SA_UKBD]++; + t = SA_UKBD; break; case WSKBD_TYPE_ADB: - kbds[SA_AKBD]++; + t = SA_AKBD; break; case WSKBD_TYPE_LK201: case WSKBD_TYPE_LK401: - kbds[SA_LKKBD]++; + t = SA_LKKBD; break; case WSKBD_TYPE_SUN: - kbds[SA_SUNKBD]++; + t = SA_SUNKBD; break; case WSKBD_TYPE_SUN5: - kbds[SA_SUN5KBD]++; + t = SA_SUN5KBD; break; case WSKBD_TYPE_HIL: - kbds[SA_HILKBD]++; + t = SA_HILKBD; break; case WSKBD_TYPE_GSC: - kbds[SA_GSCKBD]++; + t = SA_GSCKBD; break; case WSKBD_TYPE_SGI: - kbds[SA_SGIKBD]++; + t = SA_SGIKBD; + break; + default: + t = SA_MAX; break; }; + + if (t != SA_MAX) { + kbds[t]++; + if (encs[t].encodings == NULL) + kbd_get_encs(fd, &encs[t]); + } close(fd); } } for (i = 0; i < SA_MAX; i++) if (kbds[i] != 0) - kbd_show_enc(i); + kbd_show_enc(&encs[i], i); + + for (i = 0; i < SA_MAX; i++) + free(encs[i].encodings); } void