Skip site navigation (1)Skip section navigation (2)
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>

next in thread | raw e-mail | index | archive | help
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--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201301210610.r0L6A01Q094506>