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.

Waring; this did not go through a make release yet.  And that might be
relevant, since this code gets included in the ramdisks.

Thoughts?


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 12:10:57 -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 12:10:57 -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 12:10:57 -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,50 @@ 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);
 }
 
 void

Reply via email to