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:
parent
2e37c5a333
commit
4673ea01e3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=148017
@ -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);
|
||||
}
|
||||
|
@ -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) */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user