From d2de93780cda13f880d4a89bafd3fb9440420da5 Mon Sep 17 00:00:00 2001 From: emax Date: Thu, 14 Jul 2005 22:43:20 +0000 Subject: kbdmux(4) keyboard multiplexer integration o Slightly change KBADDKBD and KBRELKBD ioctl() interface. Instead of passing keyboard index pass keyboard_info_t structure with populated 'kb_unit' and 'kb_name' fields. Keyboard index is not very user-friendly and is not very easy to obtain. Keyboard driver name and unit, on the other hand, is much more user friendly and known almost all the time; o Move definition of keyboard_info_t structure up; o Teach kbdcontrol(1) how to attach/detach keyboards to/from the keyboard multiplexor; o Update kbdcontrol(1) man page and document new functionality. To attach/detach keyboard to/from keyboard multiplexor one needs to use keyboard device name (i.e. ukbd0). MFC after: 1 week --- sys/dev/kbdmux/kbdmux.c | 43 +++++++++++++----------- sys/sys/kbio.h | 21 ++++++------ usr.sbin/kbdcontrol/kbdcontrol.1 | 22 ++++++++++++ usr.sbin/kbdcontrol/kbdcontrol.c | 72 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 127 insertions(+), 31 deletions(-) diff --git a/sys/dev/kbdmux/kbdmux.c b/sys/dev/kbdmux/kbdmux.c index 4a36513..f052a8e 100644 --- a/sys/dev/kbdmux/kbdmux.c +++ b/sys/dev/kbdmux/kbdmux.c @@ -143,7 +143,6 @@ MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor"); struct kbdmux_kbd { keyboard_t *kbd; /* keyboard */ - int idx; /* keyboard index */ SLIST_ENTRY(kbdmux_kbd) next; /* link to next */ }; @@ -282,7 +281,6 @@ kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg) SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next); k->kbd = NULL; - k->idx = -1; free(k, M_KBDMUX); } @@ -500,7 +498,6 @@ kbdmux_term(keyboard_t *kbd) SLIST_REMOVE_HEAD(&state->ks_kbds, next); k->kbd = NULL; - k->idx = -1; free(k, M_KBDMUX); } @@ -903,6 +900,7 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; kbdmux_kbd_t *k; + keyboard_info_t *ki; int error = 0, mode; if (state == NULL) @@ -910,10 +908,17 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) switch (cmd) { case KBADDKBD: /* add keyboard to the mux */ + ki = (keyboard_info_t *) arg; + + if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' || + strcmp(ki->kb_name, "*") == 0) + return (EINVAL); /* bad input */ + KBDMUX_LOCK(state); SLIST_FOREACH(k, &state->ks_kbds, next) - if (k->idx == *((int *) arg)) + if (k->kbd->kb_unit == ki->kb_unit && + strcmp(k->kbd->kb_name, ki->kb_name) == 0) break; if (k != NULL) { @@ -929,22 +934,17 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) return (ENOMEM); /* out of memory */ } - k->kbd = kbd_get_keyboard(*((int *) arg)); - if (k->kbd == NULL) { - KBDMUX_UNLOCK(state); - free(k, M_KBDMUX); - - return (EINVAL); /* bad keyboard index */ - } - - k->idx = kbd_allocate(k->kbd->kb_name, k->kbd->kb_unit, + k->kbd = kbd_get_keyboard( + kbd_allocate( + ki->kb_name, + ki->kb_unit, (void *) &k->kbd, - kbdmux_kbd_event, (void *) state); - if (k->idx == -1) { + kbdmux_kbd_event, (void *) state)); + if (k->kbd == NULL) { KBDMUX_UNLOCK(state); free(k, M_KBDMUX); - return (EBUSY); /* keyboard is busy */ + return (EINVAL); /* bad keyboard */ } KBDMUX_ENABLE(k->kbd); @@ -964,7 +964,6 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) kbd_release(k->kbd, &k->kbd); k->kbd = NULL; - k->idx = -1; free(k, M_KBDMUX); @@ -977,10 +976,17 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) break; case KBRELKBD: /* release keyboard from the mux */ + ki = (keyboard_info_t *) arg; + + if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' || + strcmp(ki->kb_name, "*") == 0) + return (EINVAL); /* bad input */ + KBDMUX_LOCK(state); SLIST_FOREACH(k, &state->ks_kbds, next) - if (k->idx == *((int *) arg)) + if (k->kbd->kb_unit == ki->kb_unit && + strcmp(k->kbd->kb_name, ki->kb_name) == 0) break; if (k != NULL) { @@ -989,7 +995,6 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next); k->kbd = NULL; - k->idx = -1; free(k, M_KBDMUX); } diff --git a/sys/sys/kbio.h b/sys/sys/kbio.h index e357582..a4b1f04 100644 --- a/sys/sys/kbio.h +++ b/sys/sys/kbio.h @@ -60,16 +60,6 @@ /* set keyboard repeat rate (obsolete, use KDSETREPEAT below) */ #define KDSETRAD _IO('K', 67 /*, int */) -/* add/remove keyboard to/from mux */ -#define KBADDKBD _IOW('K', 68, int) /* add keyboard */ -#define KBRELKBD _IOW('K', 69, int) /* release keyboard */ - -/* see console.h for the definition of the following ioctl */ -#if notdef -#define KDRASTER _IOW('K', 100, scr_size_t) -#endif - -/* get keyboard information */ struct keyboard_info { int kb_index; /* kbdio index# */ char kb_name[16]; /* driver name */ @@ -79,6 +69,17 @@ struct keyboard_info { int kb_flags; /* internal flags */ }; typedef struct keyboard_info keyboard_info_t; + +/* add/remove keyboard to/from mux */ +#define KBADDKBD _IOW('K', 68, keyboard_info_t) /* add keyboard */ +#define KBRELKBD _IOW('K', 69, keyboard_info_t) /* release keyboard */ + +/* see console.h for the definition of the following ioctl */ +#if notdef +#define KDRASTER _IOW('K', 100, scr_size_t) +#endif + +/* get keyboard information */ #define KDGKBINFO _IOR('K', 101, keyboard_info_t) /* set/get keyboard repeat rate (new interface) */ diff --git a/usr.sbin/kbdcontrol/kbdcontrol.1 b/usr.sbin/kbdcontrol/kbdcontrol.1 index 99ef3be..bae118d 100644 --- a/usr.sbin/kbdcontrol/kbdcontrol.1 +++ b/usr.sbin/kbdcontrol/kbdcontrol.1 @@ -22,6 +22,8 @@ .Sh SYNOPSIS .Nm .Op Fl dFKix +.Op Fl A Ar name +.Op Fl a Ar name .Oo .Fl b .Ar duration . Ns Ar pitch | Ar belltype @@ -52,6 +54,26 @@ below. .Pp The following command line options are supported: .Bl -tag -width indent +.It Fl A Ar name +Detach the keyboard, specified by the keyboard device name, from the keyboard +multiplexer. +When using this option, the standard input of the +.Nm +process should be redirected from the keyboard multilpexor keyboard device +(if keyboard multiplexor is not active keyboard) or +.Pa /dev/console +(if keyboard multiplexor is active keyboard and +you are not working on the system console). +.It Fl a Ar name +Attach the keyboard, specified by the keyboard device name, to the keyboard +multiplexer. +When using this option, the standard input of the +.Nm +process should be redirected from the keyboard multilpexor keyboard device +(if keyboard multiplexor is not active keyboard) or +.Pa /dev/console +(if keyboard multiplexor is active keyboard and +you are not working on the system console). .It Fl b Xo .Ar duration . Ns Ar pitch | Ar belltype .Xc diff --git a/usr.sbin/kbdcontrol/kbdcontrol.c b/usr.sbin/kbdcontrol/kbdcontrol.c index eb72b82..7607ff4 100644 --- a/usr.sbin/kbdcontrol/kbdcontrol.c +++ b/usr.sbin/kbdcontrol/kbdcontrol.c @@ -130,6 +130,7 @@ void print_key_definition_line(FILE *fp, int scancode, struct keyent_t *key); void print_keymap(void); void release_keyboard(void); +void mux_keyboard(int op, char *kbd); void set_bell_values(char *opt); void set_functionkey(char *keynumstr, char *string); void set_keyboard(char *device); @@ -1080,12 +1081,75 @@ release_keyboard(void) warn("unable to release the keyboard"); } +void +mux_keyboard(int op, char *kbd) +{ + keyboard_info_t info; + char *unit, *ep; + + /* + * If stdin is not associated with a keyboard, the following ioctl + * will fail. + */ + if (ioctl(0, KDGKBINFO, &info) == -1) { + warn("unable to obtain keyboard information"); + return; + } +#if 1 + printf("kbd%d\n", info.kb_index); + printf(" %.*s%d, type:%s (%d)\n", + (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, + get_kbd_type_name(info.kb_type), info.kb_type); +#endif + /* + * split kbd into name and unit. find the right most part of the + * kbd string that consist of only digits. + */ + + memset(&info, 0, sizeof(info)); + + info.kb_unit = -1; + ep = kbd - 1; + + do { + unit = strpbrk(ep + 1, "0123456789"); + if (unit != NULL) { + info.kb_unit = strtol(unit, &ep, 10); + if (*ep != '\0') + info.kb_unit = -1; + } + } while (unit != NULL && info.kb_unit == -1); + + if (info.kb_unit == -1) { + warnx("unable to find keyboard driver unit in '%s'", kbd); + return; + } + + if (unit == kbd) { + warnx("unable to find keyboard driver name in '%s'", kbd); + return; + } + if (unit - kbd >= (int) sizeof(info.kb_name)) { + warnx("keyboard name '%s' is too long", kbd); + return; + } + + strncpy(info.kb_name, kbd, unit - kbd); + + /* + * If stdin is not associated with a kbdmux(4) keyboard, the following + * ioctl will fail. + */ + + if (ioctl(0, op, &info) == -1) + warn("unable to (un)mux the keyboard"); +} void usage() { fprintf(stderr, "%s\n%s\n%s\n", -"usage: kbdcontrol [-dFKix] [-b duration.pitch | [quiet.]belltype]", +"usage: kbdcontrol [-dFKix] [-A name] [-a name] [-b duration.pitch | [quiet.]belltype]", " [-r delay.repeat | speed] [-l mapfile] [-f # string]", " [-k device] [-L mapfile]"); exit(1); @@ -1097,8 +1161,12 @@ main(int argc, char **argv) { int opt; - while((opt = getopt(argc, argv, "b:df:iKk:Fl:L:r:x")) != -1) + while((opt = getopt(argc, argv, "A:a:b:df:iKk:Fl:L:r:x")) != -1) switch(opt) { + case 'A': + case 'a': + mux_keyboard((opt == 'A')? KBRELKBD : KBADDKBD, optarg); + break; case 'b': set_bell_values(optarg); break; -- cgit v1.1