Re: [PATCH 1/2] input: mt: Introduce MT event slots (rev 5)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 05/22/10 18:30, Henrik Rydberg wrote:
> With the rapidly increasing number of intelligent multi-contact and
> multi-user devices, the need to send digested, filtered information
> from a set of different sources within the same device is imminent.
> This patch adds the concept of slots to the MT protocol. The slots
> enumerate a set of identified sources, such that all MT events
> can be passed independently and selectively per identified source.
> 
> The protocol works like this: Instead of sending a SYN_MT_REPORT
> event immediately after the contact data, one sends an ABS_MT_SLOT
> event immediately before the contact data. The input core will only
> emit events for slots with modified MT events. It is assumed that
> the same slot is used for the duration of an initiated contact.
> 
Sorry, about taking so long to look at this patch.  This looks like a good step
forward and it looks good to me.

Acked-by: Rafi Rubin <rafi@xxxxxxxxxxxxxx>
> Signed-off-by: Henrik Rydberg <rydberg@xxxxxxxxxxx>
> ---
> Revision 5 incorporates the following changes:
> 	 - Rename the slot event to ABS_MT_SLOT to keep all MT-related events
> 	   in the same namespace.
> 	 - Move the MT slot event list to input.h so that it can be read
> 	   by userspace.
> 
>  drivers/input/input.c |  105 +++++++++++++++++++++++++++++++++++++------------
>  include/linux/input.h |   44 ++++++++++++++++++++
>  2 files changed, 123 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index 9c79bd5..9b6d474 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -33,24 +33,9 @@ MODULE_LICENSE("GPL");
>  
>  #define INPUT_DEVICES	256
>  
> -/*
> - * EV_ABS events which should not be cached are listed here.
> - */
> -static unsigned int input_abs_bypass_init_data[] __initdata = {
> -	ABS_MT_TOUCH_MAJOR,
> -	ABS_MT_TOUCH_MINOR,
> -	ABS_MT_WIDTH_MAJOR,
> -	ABS_MT_WIDTH_MINOR,
> -	ABS_MT_ORIENTATION,
> -	ABS_MT_POSITION_X,
> -	ABS_MT_POSITION_Y,
> -	ABS_MT_TOOL_TYPE,
> -	ABS_MT_BLOB_ID,
> -	ABS_MT_TRACKING_ID,
> -	ABS_MT_PRESSURE,
> -	0
> -};
> -static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)];
> +static unsigned int input_mt_abs_map_init_data[] __initdata =
> +	MT_SLOT_ABS_EVENTS;
> +static unsigned char input_mt_abs_map[ABS_CNT];
>  
>  static LIST_HEAD(input_dev_list);
>  static LIST_HEAD(input_handler_list);
> @@ -181,6 +166,26 @@ static void input_stop_autorepeat(struct input_dev *dev)
>  #define INPUT_PASS_TO_DEVICE	2
>  #define INPUT_PASS_TO_ALL	(INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
>  
> +static void input_mt_handle_abs_event(struct input_dev *dev,
> +				      unsigned int code, int value)
> +{
> +	if (dev->mt) {
> +		struct input_mt_slot *mtslot = &dev->mt[dev->slot];
> +		unsigned int mtcode = input_mt_abs_map[code] - 1;
> +		int old = mtslot->abs[mtcode];
> +		value = input_defuzz_abs_event(value, old, dev->absfuzz[code]);
> +		if (value == old)
> +			return;
> +		mtslot->abs[mtcode] = value;
> +	}
> +	dev->sync = 0;
> +	if (dev->slot != dev->abs[ABS_MT_SLOT]) {
> +		dev->abs[ABS_MT_SLOT] = dev->slot;
> +		input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
> +	}
> +	input_pass_event(dev, EV_ABS, code, value);
> +}
> +
>  static void input_handle_event(struct input_dev *dev,
>  			       unsigned int type, unsigned int code, int value)
>  {
> @@ -235,11 +240,17 @@ static void input_handle_event(struct input_dev *dev,
>  	case EV_ABS:
>  		if (is_event_supported(code, dev->absbit, ABS_MAX)) {
>  
> -			if (test_bit(code, input_abs_bypass)) {
> -				disposition = INPUT_PASS_TO_HANDLERS;
> +			if (code == ABS_MT_SLOT) {
> +				if (value >= 0 && value < dev->mtsize)
> +					dev->slot = value;
>  				break;
>  			}
>  
> +			if (input_mt_abs_map[code]) {
> +				input_mt_handle_abs_event(dev, code, value);
> +				return;
> +			}
> +
>  			value = input_defuzz_abs_event(value,
>  					dev->abs[code], dev->absfuzz[code]);
>  
> @@ -1278,6 +1289,7 @@ static void input_dev_release(struct device *device)
>  	struct input_dev *dev = to_input_dev(device);
>  
>  	input_ff_destroy(dev);
> +	input_mt_destroy_slots(dev);
>  	kfree(dev);
>  
>  	module_put(THIS_MODULE);
> @@ -1518,6 +1530,46 @@ void input_free_device(struct input_dev *dev)
>  EXPORT_SYMBOL(input_free_device);
>  
>  /**
> + * input_mt_create_slots() - create MT input slots
> + * @dev: input device supporting MT events and finger tracking
> + * @max_slots: maximum number of slots supported by the device
> + *
> + * This function allocates all necessary memory for MT slot handling
> + * in the input device, and adds ABS_MT_SLOT to the device capabilities.
> + */
> +int input_mt_create_slots(struct input_dev *dev, int max_slots)
> +{
> +	struct input_mt_slot *mt;
> +
> +	if (max_slots <= 0)
> +		return 0;
> +	mt = kzalloc(max_slots * sizeof(struct input_mt_slot), GFP_KERNEL);
> +	if (!mt)
> +		return -ENOMEM;
> +
> +	dev->mt = mt;
> +	dev->mtsize = max_slots;
> +	input_set_abs_params(dev, ABS_MT_SLOT, 0, max_slots - 1, 0, 0);
> +	return 0;
> +}
> +EXPORT_SYMBOL(input_mt_create_slots);
> +
> +/**
> + * input_mt_destroy_slots() - frees the MT slots of the input device
> + * @dev: input device with allocated MT slots
> + *
> + * This function is only needed in error path as the input core will
> + * automatically free the MT slots when the device is destroyed.
> + */
> +void input_mt_destroy_slots(struct input_dev *dev)
> +{
> +	kfree(dev->mt);
> +	dev->mt = NULL;
> +	dev->mtsize = 0;
> +}
> +EXPORT_SYMBOL(input_mt_destroy_slots);
> +
> +/**
>   * input_set_capability - mark device as capable of a certain event
>   * @dev: device that is capable of emitting or accepting event
>   * @type: type of the event (EV_KEY, EV_REL, etc...)
> @@ -1926,19 +1978,20 @@ static const struct file_operations input_fops = {
>  	.open = input_open_file,
>  };
>  
> -static void __init input_init_abs_bypass(void)
> +static void __init input_mt_init_maps(void)
>  {
> -	const unsigned int *p;
> -
> -	for (p = input_abs_bypass_init_data; *p; p++)
> -		input_abs_bypass[BIT_WORD(*p)] |= BIT_MASK(*p);
> +	int i;
> +	BUILD_BUG_ON(MT_ABS_SIZE != (typeof(input_mt_abs_map[0]))MT_ABS_SIZE);
> +	BUILD_BUG_ON(ARRAY_SIZE(input_mt_abs_map_init_data) > MT_ABS_SIZE);
> +	for (i = 0; i < ARRAY_SIZE(input_mt_abs_map_init_data); i++)
> +		input_mt_abs_map[input_mt_abs_map_init_data[i]] = i + 1;
>  }
>  
>  static int __init input_init(void)
>  {
>  	int err;
>  
> -	input_init_abs_bypass();
> +	input_mt_init_maps();
>  
>  	err = class_register(&input_class);
>  	if (err) {
> diff --git a/include/linux/input.h b/include/linux/input.h
> index 7ed2251..bea6958 100644
> --- a/include/linux/input.h
> +++ b/include/linux/input.h
> @@ -694,6 +694,7 @@ struct input_absinfo {
>  #define ABS_VOLUME		0x20
>  #define ABS_MISC		0x28
>  
> +#define ABS_MT_SLOT		0x2f	/* MT slot being modified */
>  #define ABS_MT_TOUCH_MAJOR	0x30	/* Major axis of touching ellipse */
>  #define ABS_MT_TOUCH_MINOR	0x31	/* Minor axis (omit if circular) */
>  #define ABS_MT_WIDTH_MAJOR	0x32	/* Major axis of approaching ellipse */
> @@ -814,6 +815,24 @@ struct input_absinfo {
>  #define MT_TOOL_PEN		1
>  
>  /*
> + * MT slot event lists
> + */
> +
> +#define MT_SLOT_ABS_EVENTS {	\
> +	ABS_MT_TOUCH_MAJOR,	\
> +	ABS_MT_TOUCH_MINOR,	\
> +	ABS_MT_WIDTH_MAJOR,	\
> +	ABS_MT_WIDTH_MINOR,	\
> +	ABS_MT_ORIENTATION,	\
> +	ABS_MT_POSITION_X,	\
> +	ABS_MT_POSITION_Y,	\
> +	ABS_MT_TOOL_TYPE,	\
> +	ABS_MT_BLOB_ID,		\
> +	ABS_MT_TRACKING_ID,	\
> +	ABS_MT_PRESSURE,	\
> +}
> +
> +/*
>   * Values describing the status of a force-feedback effect
>   */
>  #define FF_STATUS_STOPPED	0x00
> @@ -1080,6 +1099,9 @@ struct ff_effect {
>   * @sync: set to 1 when there were no new events since last EV_SYNC
>   * @abs: current values for reports from absolute axes
>   * @rep: current values for autorepeat parameters (delay, rate)
> + * @mt: array of MT slots
> + * @mtsize: number of allocated MT slots
> + * @slot: current MT slot
>   * @key: reflects current state of device's keys/buttons
>   * @led: reflects current state of device's LEDs
>   * @snd: reflects current state of sound effects
> @@ -1157,6 +1179,10 @@ struct input_dev {
>  	int abs[ABS_MAX + 1];
>  	int rep[REP_MAX + 1];
>  
> +	struct input_mt_slot *mt;
> +	int mtsize;
> +	int slot;
> +
>  	unsigned long key[BITS_TO_LONGS(KEY_CNT)];
>  	unsigned long led[BITS_TO_LONGS(LED_CNT)];
>  	unsigned long snd[BITS_TO_LONGS(SND_CNT)];
> @@ -1405,6 +1431,11 @@ static inline void input_mt_sync(struct input_dev *dev)
>  	input_event(dev, EV_SYN, SYN_MT_REPORT, 0);
>  }
>  
> +static inline void input_mt_slot(struct input_dev *dev, int slot)
> +{
> +	input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
> +}
> +
>  void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);
>  
>  static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
> @@ -1484,5 +1515,18 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file);
>  int input_ff_create_memless(struct input_dev *dev, void *data,
>  		int (*play_effect)(struct input_dev *, void *, struct ff_effect *));
>  
> +#define MT_ABS_SIZE 11
> +
> +/**
> + * struct input_mt_slot - represents the state of an input MT slot
> + * @abs: current values of ABS_MT axes for this slot
> + */
> +struct input_mt_slot {
> +	int abs[MT_ABS_SIZE];
> +};
> +
> +int input_mt_create_slots(struct input_dev *dev, int max_slots);
> +void input_mt_destroy_slots(struct input_dev *dev);
> +
>  #endif
>  #endif

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkwXCKwACgkQwuRiAT9o608AfwCfT15rbveKL/kCROKk5E7xg81L
zrYAoK8edxq+1HeBDBcHiuP2rDoy4Oi/
=J6e0
-----END PGP SIGNATURE-----
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux