> Date: Thu, 29 Sep 2016 14:19:43 +0200 (CEST)
> From: Mark Kettenis <[email protected]>
>
> 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