Input: introduce device properties
Today, userspace sets up an input device based on the data it emits. This is not always enough; a tablet and a touchscreen may emit exactly the same data, for instance, but the former should be set up with a pointer whereas the latter does not need to. Recently, a new type of touchpad has emerged where the buttons are under the pad, which changes logic without changing the emitted data. This patch introduces a new ioctl, EVIOCGPROP, which enables user access to a set of device properties useful during setup. The properties are given as a bitmap in the same fashion as the event types, and are also made available via sysfs, uevent and /proc/bus/input/devices. Acked-by: Ping Cheng <pingc@wacom.com> Acked-by: Chase Douglas <chase.douglas@canonical.com> Acked-by: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
This commit is contained in:
		
					parent
					
						
							
								4dd295a73e
							
						
					
				
			
			
				commit
				
					
						85b7720039
					
				
			
		
					 5 changed files with 44 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -677,6 +677,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 | 
			
		|||
#define EVIOC_MASK_SIZE(nr)	((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
 | 
			
		||||
	switch (EVIOC_MASK_SIZE(cmd)) {
 | 
			
		||||
 | 
			
		||||
	case EVIOCGPROP(0):
 | 
			
		||||
		return bits_to_user(dev->propbit, INPUT_PROP_MAX,
 | 
			
		||||
				    size, p, compat_mode);
 | 
			
		||||
 | 
			
		||||
	case EVIOCGKEY(0):
 | 
			
		||||
		return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1095,6 +1095,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
 | 
			
		|||
		seq_printf(seq, "%s ", handle->name);
 | 
			
		||||
	seq_putc(seq, '\n');
 | 
			
		||||
 | 
			
		||||
	input_seq_print_bitmap(seq, "PROP", dev->propbit, INPUT_PROP_MAX);
 | 
			
		||||
 | 
			
		||||
	input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
 | 
			
		||||
	if (test_bit(EV_KEY, dev->evbit))
 | 
			
		||||
		input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
 | 
			
		||||
| 
						 | 
				
			
			@ -1318,11 +1320,26 @@ static ssize_t input_dev_show_modalias(struct device *dev,
 | 
			
		|||
}
 | 
			
		||||
static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
 | 
			
		||||
 | 
			
		||||
static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
 | 
			
		||||
			      int max, int add_cr);
 | 
			
		||||
 | 
			
		||||
static ssize_t input_dev_show_properties(struct device *dev,
 | 
			
		||||
					 struct device_attribute *attr,
 | 
			
		||||
					 char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct input_dev *input_dev = to_input_dev(dev);
 | 
			
		||||
	int len = input_print_bitmap(buf, PAGE_SIZE, input_dev->propbit,
 | 
			
		||||
				     INPUT_PROP_MAX, true);
 | 
			
		||||
	return min_t(int, len, PAGE_SIZE);
 | 
			
		||||
}
 | 
			
		||||
static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
 | 
			
		||||
 | 
			
		||||
static struct attribute *input_dev_attrs[] = {
 | 
			
		||||
	&dev_attr_name.attr,
 | 
			
		||||
	&dev_attr_phys.attr,
 | 
			
		||||
	&dev_attr_uniq.attr,
 | 
			
		||||
	&dev_attr_modalias.attr,
 | 
			
		||||
	&dev_attr_properties.attr,
 | 
			
		||||
	NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1522,6 +1539,8 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
 | 
			
		|||
	if (dev->uniq)
 | 
			
		||||
		INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);
 | 
			
		||||
 | 
			
		||||
	INPUT_ADD_HOTPLUG_BM_VAR("PROP=", dev->propbit, INPUT_PROP_MAX);
 | 
			
		||||
 | 
			
		||||
	INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);
 | 
			
		||||
	if (test_bit(EV_KEY, dev->evbit))
 | 
			
		||||
		INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -680,6 +680,10 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 | 
			
		|||
			retval = uinput_set_bit(arg, swbit, SW_MAX);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case UI_SET_PROPBIT:
 | 
			
		||||
			retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case UI_SET_PHYS:
 | 
			
		||||
			if (udev->state == UIST_CREATED) {
 | 
			
		||||
				retval = -EINVAL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,6 +91,7 @@ struct input_keymap_entry {
 | 
			
		|||
#define EVIOCGNAME(len)		_IOC(_IOC_READ, 'E', 0x06, len)		/* get device name */
 | 
			
		||||
#define EVIOCGPHYS(len)		_IOC(_IOC_READ, 'E', 0x07, len)		/* get physical location */
 | 
			
		||||
#define EVIOCGUNIQ(len)		_IOC(_IOC_READ, 'E', 0x08, len)		/* get unique identifier */
 | 
			
		||||
#define EVIOCGPROP(len)		_IOC(_IOC_READ, 'E', 0x09, len)		/* get device properties */
 | 
			
		||||
 | 
			
		||||
#define EVIOCGKEY(len)		_IOC(_IOC_READ, 'E', 0x18, len)		/* get global key state */
 | 
			
		||||
#define EVIOCGLED(len)		_IOC(_IOC_READ, 'E', 0x19, len)		/* get all LEDs */
 | 
			
		||||
| 
						 | 
				
			
			@ -107,6 +108,18 @@ struct input_keymap_entry {
 | 
			
		|||
 | 
			
		||||
#define EVIOCGRAB		_IOW('E', 0x90, int)			/* Grab/Release device */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Device properties and quirks
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define INPUT_PROP_POINTER		0x00	/* needs a pointer */
 | 
			
		||||
#define INPUT_PROP_DIRECT		0x01	/* direct input devices */
 | 
			
		||||
#define INPUT_PROP_BUTTONPAD		0x02	/* has button(s) under pad */
 | 
			
		||||
#define INPUT_PROP_SEMI_MT		0x03	/* touch rectangle only */
 | 
			
		||||
 | 
			
		||||
#define INPUT_PROP_MAX			0x1f
 | 
			
		||||
#define INPUT_PROP_CNT			(INPUT_PROP_MAX + 1)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Event types
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -1090,6 +1103,7 @@ struct ff_effect {
 | 
			
		|||
 * @phys: physical path to the device in the system hierarchy
 | 
			
		||||
 * @uniq: unique identification code for the device (if device has it)
 | 
			
		||||
 * @id: id of the device (struct input_id)
 | 
			
		||||
 * @propbit: bitmap of device properties and quirks
 | 
			
		||||
 * @evbit: bitmap of types of events supported by the device (EV_KEY,
 | 
			
		||||
 *	EV_REL, etc.)
 | 
			
		||||
 * @keybit: bitmap of keys/buttons this device has
 | 
			
		||||
| 
						 | 
				
			
			@ -1173,6 +1187,8 @@ struct input_dev {
 | 
			
		|||
	const char *uniq;
 | 
			
		||||
	struct input_id id;
 | 
			
		||||
 | 
			
		||||
	unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
 | 
			
		||||
 | 
			
		||||
	unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
 | 
			
		||||
	unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
 | 
			
		||||
	unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,6 +104,7 @@ struct uinput_ff_erase {
 | 
			
		|||
#define UI_SET_FFBIT		_IOW(UINPUT_IOCTL_BASE, 107, int)
 | 
			
		||||
#define UI_SET_PHYS		_IOW(UINPUT_IOCTL_BASE, 108, char*)
 | 
			
		||||
#define UI_SET_SWBIT		_IOW(UINPUT_IOCTL_BASE, 109, int)
 | 
			
		||||
#define UI_SET_PROPBIT		_IOW(UINPUT_IOCTL_BASE, 110, int)
 | 
			
		||||
 | 
			
		||||
#define UI_BEGIN_FF_UPLOAD	_IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
 | 
			
		||||
#define UI_END_FF_UPLOAD	_IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue