Date: Mon, 21 Jan 2013 06:10:00 GMT From: Yuri <yuri@rawbw.com> To: freebsd-bugs@FreeBSD.org Subject: Re: misc/175425: kbdcontrol(1) printout about kbdmux isn't informative Message-ID: <201301210610.r0L6A01Q094506@freefall.freebsd.org>
index | next in thread | raw e-mail
The following reply was made to PR misc/175425; it has been noted by GNATS.
From: Yuri <yuri@rawbw.com>
To: bug-followup@FreeBSD.org
Cc:
Subject: Re: misc/175425: kbdcontrol(1) printout about kbdmux isn't informative
Date: Sun, 20 Jan 2013 22:01:14 -0800
This is a multi-part message in MIME format.
--------------070002040502000102020100
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Patches:
* patch-ioctl-var-size.txt : implements variable size ioctl(2) data
parameter. This is used by the ioctl in the second patch. Userland
truss(1) is updated accordingly.
* patch-kbd-mux-contents.txt : implements new ioctl KBLSTKBD listing
contents of the kbd mux. Userland kbdcontrol is updated with the new
option -I using KBLSTKBD.
--------------070002040502000102020100
Content-Type: text/plain; charset=UTF-8;
name="patch-ioctl-var-size.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="patch-ioctl-var-size.txt"
Index: sys/kern/sys_generic.c
===================================================================
--- sys/kern/sys_generic.c (revision 245654)
+++ sys/kern/sys_generic.c (working copy)
@@ -640,6 +640,7 @@
int arg, error;
u_int size;
caddr_t data;
+ int vsize;
if (uap->com > 0xffffffff) {
printf(
@@ -654,18 +655,30 @@
* copied to/from the user's address space.
*/
size = IOCPARM_LEN(com);
+ /* Both IOC_VOID and IOC_INOUT mean that data has variable size */
+ if (com & IOC_VOID && com & IOC_INOUT) {
+ if (size != 0)
+ return (EINVAL);
+ /* first integer has the length of the memory */
+ error = copyin(uap->data, (caddr_t)&vsize, sizeof(vsize));
+ if (error)
+ return (error);
+ size = (u_int)vsize;
+ if (size > IOCPARM_MAX)
+ return (EINVAL);
+ }
if ((size > IOCPARM_MAX) ||
- ((com & (IOC_VOID | IOC_IN | IOC_OUT)) == 0) ||
+ ((com & IOC_DIRMASK) == 0) ||
#if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
((com & IOC_OUT) && size == 0) ||
#else
((com & (IOC_IN | IOC_OUT)) && size == 0) ||
#endif
- ((com & IOC_VOID) && size > 0 && size != sizeof(int)))
+ (((com & IOC_DIRMASK) == IOC_VOID) && size > 0 && size != sizeof(int)))
return (ENOTTY);
if (size > 0) {
- if (com & IOC_VOID) {
+ if ((com & IOC_DIRMASK) == IOC_VOID) {
/* Integer argument. */
arg = (intptr_t)uap->data;
data = (void *)&arg;
Index: sys/netgraph/ng_eiface.c
===================================================================
--- sys/netgraph/ng_eiface.c (revision 245654)
+++ sys/netgraph/ng_eiface.c (working copy)
@@ -325,6 +325,15 @@
case IOC_INOUT:
str = "IORW";
break;
+ case IOC_OUT_EXT:
+ str = "IORE";
+ break;
+ case IOC_IN_EXT:
+ str = "IOWE";
+ break;
+ case IOC_INOUT_EXT:
+ str = "IORWE";
+ break;
default:
str = "IO??";
}
Index: sys/netgraph/ng_fec.c
===================================================================
--- sys/netgraph/ng_fec.c (revision 245654)
+++ sys/netgraph/ng_fec.c (working copy)
@@ -1167,6 +1167,15 @@
case IOC_INOUT:
str = "IORW";
break;
+ case IOC_OUT_EXT:
+ str = "IORE";
+ break;
+ case IOC_IN_EXT:
+ str = "IOWE";
+ break;
+ case IOC_INOUT_EXT:
+ str = "IORWE";
+ break;
default:
str = "IO??";
}
Index: sys/netgraph/ng_iface.c
===================================================================
--- sys/netgraph/ng_iface.c (revision 245654)
+++ sys/netgraph/ng_iface.c (working copy)
@@ -505,6 +505,15 @@
case IOC_INOUT:
str = "IORW";
break;
+ case IOC_OUT_EXT:
+ str = "IORE";
+ break;
+ case IOC_IN_EXT:
+ str = "IOWE";
+ break;
+ case IOC_INOUT_EXT:
+ str = "IORWE";
+ break;
default:
str = "IO??";
}
Index: sys/sys/ioccom.h
===================================================================
--- sys/sys/ioccom.h (revision 245654)
+++ sys/sys/ioccom.h (working copy)
@@ -48,8 +48,11 @@
#define IOC_VOID 0x20000000 /* no parameters */
#define IOC_OUT 0x40000000 /* copy out parameters */
#define IOC_IN 0x80000000 /* copy in parameters */
-#define IOC_INOUT (IOC_IN|IOC_OUT)
-#define IOC_DIRMASK (IOC_VOID|IOC_OUT|IOC_IN)
+#define IOC_INOUT (IOC_IN | IOC_OUT)
+#define IOC_DIRMASK (IOC_VOID | IOC_OUT | IOC_IN)
+#define IOC_OUT_EXT IOC_OUT | IOC_VOID /* copy out parameters */
+#define IOC_IN_EXT IOC_IN | IOC_VOID /* copy out parameters */
+#define IOC_INOUT_EXT IOC_INOUT | IOC_VOID /* copy out parameters */
#define _IOC(inout,group,num,len) ((unsigned long) \
((inout) | (((len) & IOCPARM_MASK) << 16) | ((group) << 8) | (num)))
@@ -59,6 +62,9 @@
#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t))
/* this should be _IORW, but stdio got there first */
#define _IOWR(g,n,t) _IOC(IOC_INOUT, (g), (n), sizeof(t))
+#define _IORE(g,n) _IOC(IOC_OUT_EXT, (g), (n), 0)
+#define _IOWE(g,n) _IOC(IOC_IN_EXT, (g), (n), 0)
+#define _IOWRE(g,n) _IOC(IOC_INOUT_EXT, (g), (n), 0)
#ifdef _KERNEL
Index: usr.bin/truss/syscalls.c
===================================================================
--- usr.bin/truss/syscalls.c (revision 245654)
+++ usr.bin/truss/syscalls.c (working copy)
@@ -668,9 +668,12 @@
tmp = strdup(temp);
else {
unsigned long arg = args[sc->offset];
- asprintf(&tmp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
- arg, arg & IOC_OUT ? "R" : "",
- arg & IOC_IN ? "W" : "", IOCGROUP(arg),
+ asprintf(&tmp, "0x%lx { IO%s%s%s 0x%lx('%c'), %lu, %lu }",
+ arg,
+ arg & IOC_OUT ? "R" : "",
+ arg & IOC_IN ? "W" : "",
+ (arg & IOC_VOID && arg & IOC_INOUT) ? "E" : "",
+ IOCGROUP(arg),
isprint(IOCGROUP(arg)) ? (char)IOCGROUP(arg) : '?',
arg & 0xFF, IOCPARM_LEN(arg));
}
--------------070002040502000102020100
Content-Type: text/plain; charset=UTF-8;
name="patch-kbd-mux-contents.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="patch-kbd-mux-contents.txt"
Index: sys/dev/kbdmux/kbdmux.c
===================================================================
--- sys/dev/kbdmux/kbdmux.c (revision 245654)
+++ sys/dev/kbdmux/kbdmux.c (working copy)
@@ -943,6 +943,9 @@
kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
kbdmux_kbd_t *k;
keyboard_info_t *ki;
+ keyboard_info_array_t *kia;
+ keyboard_info_array_t *kia_limit;
+ int ki_count;
int error = 0, mode;
#ifdef COMPAT_FREEBSD6
int ival;
@@ -1049,6 +1052,35 @@
KBDMUX_UNLOCK(state);
break;
+ case KBLSTKBD: /* list mux contents */
+ kia = (keyboard_info_array_t *) arg;
+
+ if (kia == NULL || kia->len <= 0)
+ return (EINVAL); /* bad input */
+
+ KBDMUX_LOCK(state);
+
+ kia_limit = (keyboard_info_array_t *) ((char*)arg+kia->len);
+ ki = kia->kbs;
+ ki_count = 0;
+ SLIST_FOREACH(k, &state->ks_kbds, next) {
+ if (kia+1 > kia_limit)
+ break;
+ ki->kb_index = k->kbd->kb_index;
+ (void) strcpy(ki->kb_name, k->kbd->kb_name);
+ ki->kb_unit = k->kbd->kb_unit;
+ ki->kb_type = k->kbd->kb_type;
+ ki->kb_config = k->kbd->kb_config;
+ ki->kb_flags = k->kbd->kb_flags;
+
+ ki++;
+ ki_count++;
+ }
+ kia->len = ki_count;
+
+ KBDMUX_UNLOCK(state);
+ break;
+
case KDGKBMODE: /* get kyboard mode */
KBDMUX_LOCK(state);
*(int *)arg = state->ks_mode;
Index: sys/dev/syscons/syscons.c
===================================================================
--- sys/dev/syscons/syscons.c (revision 245654)
+++ sys/dev/syscons/syscons.c (working copy)
@@ -1349,6 +1349,7 @@
case KBADDKBD: /* add/remove keyboard to/from mux */
case KBRELKBD:
+ case KBLSTKBD:
error = kbdd_ioctl(sc->kbd, cmd, data);
if (error == ENOIOCTL)
error = ENODEV;
Index: sys/sys/kbio.h
===================================================================
--- sys/sys/kbio.h (revision 245654)
+++ sys/sys/kbio.h (working copy)
@@ -70,9 +70,16 @@
};
typedef struct keyboard_info keyboard_info_t;
+struct keyboard_info_array {
+ int len; /* array kbs[] length */
+ keyboard_info_t kbs[1]; /* variable size array */
+};
+typedef struct keyboard_info_array keyboard_info_array_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 */
+#define KBLSTKBD _IOWRE('K', 70) /* list mux */
/* see console.h for the definition of the following ioctl */
#ifdef notdef
Index: usr.sbin/kbdcontrol/kbdcontrol.1
===================================================================
--- usr.sbin/kbdcontrol/kbdcontrol.1 (revision 245654)
+++ usr.sbin/kbdcontrol/kbdcontrol.1 (working copy)
@@ -146,6 +146,8 @@
Use hexadecimal numbers in keyboard map dump.
.It Fl i
Print brief information about the keyboard.
+.It Fl I
+Print contents of the keyboard multiplexer.
.It Fl K
Disconnect the keyboard from the console.
You need to use the
Index: usr.sbin/kbdcontrol/kbdcontrol.c
===================================================================
--- usr.sbin/kbdcontrol/kbdcontrol.c (revision 245654)
+++ usr.sbin/kbdcontrol/kbdcontrol.c (working copy)
@@ -138,6 +138,7 @@
void set_keyboard(char *device);
void set_keyrates(char *opt);
void show_kbd_info(void);
+void show_mux_info(void);
void usage(void) __dead2;
char *
@@ -1011,6 +1012,22 @@
return "unknown";
}
+static void
+print_kbd_info(keyboard_info_t *info)
+{
+ 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);
+}
+
+static void
+print_kbd_info_extended(keyboard_info_t *info)
+{
+ printf("kbd%d:\n", info->kb_index);
+ printf(" ");
+ print_kbd_info(info);
+}
+
void
show_kbd_info(void)
{
@@ -1020,13 +1037,41 @@
warn("unable to obtain keyboard information");
return;
}
- 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);
+ print_kbd_info_extended(&info);
}
void
+show_mux_info(void)
+{
+ int i;
+ keyboard_info_t info_mux;
+
+ keyboard_info_array_t *info_arr = (keyboard_info_array_t*)
+ malloc(IOCPARM_MAX);
+ info_arr->len = IOCPARM_MAX;
+
+ if (ioctl(0, KDGKBINFO, &info_mux) == -1) {
+ warn("unable to obtain keyboard information");
+ free(info_arr);
+ return;
+ }
+ if (ioctl(0, KBLSTKBD, info_arr) == -1) {
+ warn("unable to obtain keyboard multiplexer information");
+ free(info_arr);
+ return;
+ }
+
+ printf("Keyboard multiplexor kbd%d: ", info_mux.kb_index);
+ print_kbd_info(&info_mux);
+ for (i=0; i<info_arr->len; i++) {
+ printf(" part[%i]: kbd%d: ", i, info_arr->kbs[i].kb_index);
+ print_kbd_info(&info_arr->kbs[i]);
+ }
+
+ free(info_arr);
+}
+
+void
set_keyboard(char *device)
{
keyboard_info_t info;
@@ -1050,10 +1095,7 @@
ioctl(fd, CONS_RELKBD, 0);
close(fd);
#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);
+ print_kbd_info_extended(&info);
#endif
if (ioctl(0, CONS_SETKBD, info.kb_index) == -1)
@@ -1074,10 +1116,7 @@
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);
+ print_kbd_info_extended(&info);
#endif
if (ioctl(0, CONS_RELKBD, 0) == -1)
warn("unable to release the keyboard");
@@ -1098,10 +1137,7 @@
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);
+ print_kbd_info_extended(&info);
#endif
/*
* split kbd into name and unit. find the right most part of the
@@ -1163,7 +1199,7 @@
{
int opt;
- while((opt = getopt(argc, argv, "A:a:b:df:iKk:Fl:L:r:x")) != -1)
+ while((opt = getopt(argc, argv, "A:a:b:df:iIKk:Fl:L:r:x")) != -1)
switch(opt) {
case 'A':
case 'a':
@@ -1191,6 +1227,9 @@
case 'i':
show_kbd_info();
break;
+ case 'I':
+ show_mux_info();
+ break;
case 'K':
release_keyboard();
break;
--------------070002040502000102020100--
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201301210610.r0L6A01Q094506>
