diff options
Diffstat (limited to 'sbin/kbd/kbd_wscons.c')
-rw-r--r-- | sbin/kbd/kbd_wscons.c | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/sbin/kbd/kbd_wscons.c b/sbin/kbd/kbd_wscons.c new file mode 100644 index 00000000000..292513364e3 --- /dev/null +++ b/sbin/kbd/kbd_wscons.c @@ -0,0 +1,236 @@ +/* $OpenBSD: kbd_wscons.c,v 1.1 2001/03/08 08:00:16 maja Exp $ */ + +/* + * Copyright (c) 2001 Mats O Jansson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <err.h> +#include <errno.h> +#include <kvm.h> +#include <fcntl.h> +#include <limits.h> +#include <nlist.h> +#include <stdio.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsksymdef.h> + +#define NUM_KBD 10 + +#define SA_PCKBD 0 +#define SA_UKBD 1 +#define SA_AKBD 2 + +struct nlist nl[] = { + { "_pckbd_keydesctab" }, + { "_ukbd_keydesctab" }, + { "_akbd_keydesctab" }, + { NULL }, +}; + +char *kbtype_tab[] = { + "pc-xt/pc-at", + "usb", + "adb", +}; + +struct nameint { + int value; + char *name; +}; + +struct nameint kbdenc_tab[] = { + KB_ENCTAB + , + { 0, 0 } +}; + +struct nameint kbdvar_tab[] = { + KB_VARTAB + , + { 0, 0 } +}; + +extern char *__progname; + +void +kbd_show_enc(kd, idx) + kvm_t *kd; + int idx; +{ + struct wscons_keydesc r; + unsigned long p; + struct nameint *n; + + printf("tables available for %s keyboard:\nencoding\n\n", + kbtype_tab[idx]); + p = nl[idx].n_value; + kvm_read(kd, p, &r, sizeof(r)); + while (r.name != 0) { + n = &kbdenc_tab[0]; + while(n->value) { + if (n->value == KB_ENCODING(r.name)) { + printf("%s",n->name); + } + n++; + } + n = &kbdvar_tab[0]; + while(n->value) { + if ((n->value & KB_VARIANT(r.name)) == n->value) { + printf(".%s",n->name); + } + n++; + } + printf("\n"); + p += sizeof(r); + kvm_read(kd, p, &r, sizeof(r)); + } + printf("\n"); +} + +void +kbd_list() +{ + int fd, i, kbtype, ret; + kvm_t *kd; + char device[sizeof "/dev/wskbd00"]; + char errbuf[_POSIX2_LINE_MAX]; + int pc_kbd = 0; + int usb_kbd = 0; + int adb_kbd = 0; + + /* Go through all keyboards. */ + for (i = 0; i < NUM_KBD; i++) { + (void) sprintf(device, "/dev/wskbd%d", i); + fd = open(device, O_WRONLY); + if (fd < 0) + fd = open(device, O_RDONLY); + if (fd >= 0) { + if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) < 0) + err(1, "WDKBDIO_GTYPE"); + if ((kbtype == WSKBD_TYPE_PC_XT) || + (kbtype == WSKBD_TYPE_PC_AT)) + pc_kbd++; + if (kbtype == WSKBD_TYPE_USB) + usb_kbd++; + if (kbtype == WSKBD_TYPE_ADB) + adb_kbd++; + close(fd); + } + } + + if ((kd = kvm_openfiles(NULL,NULL,NULL,O_RDONLY, errbuf)) == 0) + errx(1, "kvm_openfiles: %s", errbuf); + + if ((ret = kvm_nlist(kd, nl)) == -1) + errx(1, "kvm_nlist: %s", kvm_geterr(kd)); + + if (pc_kbd > 0) + kbd_show_enc(kd, SA_PCKBD); + + if (usb_kbd > 0) + kbd_show_enc(kd, SA_UKBD); + + if (adb_kbd > 0) + kbd_show_enc(kd, SA_AKBD); + + kvm_close(kd); +} + +void +kbd_set(name, verbose) + char *name; + int verbose; +{ + char buf[_POSIX2_LINE_MAX]; + char *c,*b; + struct nameint *n; + int map = 0,v,i,fd; + char device[sizeof "/dev/wskbd00"]; + + c = name; + b = buf; + while((*c != '.') && (*c != '\0')) { + *b++ = *c++; + } + *b = '\0'; + n = &kbdenc_tab[0]; + while(n->value) { + if (strcmp(n->name,buf) == 0) { + map = n->value; + } + n++; + } + if (map == 0) + errx(1, "unknown encodeing %s", buf); + while(*c == '.') { + b = buf; + c++; + while((*c != '.') && (*c != '\0')) { + *b++ = *c++; + } + *b = '\0'; + v = 0; + n = &kbdvar_tab[0]; + while(n->value) { + if (strcmp(n->name,buf) == 0) { + v = n->value; + } + n++; + } + if (v == 0) + errx(1, "unknown variant %s", buf); + map |= v; + } + + /* Go through all keyboards. */ + v = 0; + for (i = 0; i < NUM_KBD; i++) { + (void) sprintf(device, "/dev/wskbd%d", i); + fd = open(device, O_WRONLY); + if (fd < 0) + fd = open(device, O_RDONLY); + if (fd >= 0) { + if (ioctl(fd, WSKBDIO_SETENCODING, &map) < 0) { + if (errno == EINVAL) { + fprintf(stderr, "%s: unsupported encoding %s on %s\n", + __progname, name, device); + } else { + err(1, "WDKBDIO_SETENCODING: %s", device); + } + v--; + } + v++; + close(fd); + } + } + + if (verbose && v > 0) + fprintf(stderr, "keyboard mapping set to %s\n", name); +} |