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
This commit is contained in:
Maksim Yevmenkin 2005-07-14 22:43:20 +00:00
parent 2e37c5a333
commit 4673ea01e3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=148017
4 changed files with 127 additions and 31 deletions

View File

@ -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));
k->kbd = kbd_get_keyboard(
kbd_allocate(
ki->kb_name,
ki->kb_unit,
(void *) &k->kbd,
kbdmux_kbd_event, (void *) state));
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,
(void *) &k->kbd,
kbdmux_kbd_event, (void *) state);
if (k->idx == -1) {
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);
}

View File

@ -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) */

View File

@ -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

View File

@ -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;