Inter-revision diff: patch 19

Comparing v2 (message) to v1 (message)

--- v2
+++ v1
@@ -1,39 +1,319 @@
-Since commit a7197c2e, the raw report descriptor is available also for
-unclaimed devices. This patch makes it show in the rdesc debugfs node.
+With the input_mt_sync_frame() function in place, there is no longer
+any need to keep the full touch state in the driver. This patch
+removes the slot state and replaces the lookup code with the input-mt
+equivalent. The initialization code is moved to mt_input_configured(),
+to make sure the full HID report has been seen.
 
+Cc: Benjamin Tissoires <benjamin.tissoires@enac.fr>
 Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
 ---
- drivers/hid/hid-debug.c | 12 +++++++++---
- 1 file changed, 9 insertions(+), 3 deletions(-)
+ drivers/hid/hid-multitouch.c | 162 ++++++++++++++++++-------------------------
+ 1 file changed, 66 insertions(+), 96 deletions(-)
 
-diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
-index 01dd9a7..933fff0 100644
---- a/drivers/hid/hid-debug.c
-+++ b/drivers/hid/hid-debug.c
-@@ -911,15 +911,21 @@ static void hid_dump_input_mapping(struct hid_device *hid, struct seq_file *f)
- 
- }
- 
--
- static int hid_debug_rdesc_show(struct seq_file *f, void *p)
- {
- 	struct hid_device *hdev = f->private;
-+	const __u8 *rdesc = hdev->rdesc;
-+	unsigned rsize = hdev->rsize;
- 	int i;
- 
-+	if (!rdesc) {
-+		rdesc = hdev->dev_rdesc;
-+		rsize = hdev->dev_rsize;
+diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
+index b15133c..bd4bc3c 100644
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -52,13 +52,6 @@ MODULE_LICENSE("GPL");
+ #define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 6)
+ #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 8)
+ 
+-struct mt_slot {
+-	__s32 x, y, p, w, h;
+-	__s32 contactid;	/* the device ContactID assigned to this slot */
+-	bool touch_state;	/* is the touch valid? */
+-	bool seen_in_this_frame;/* has this slot been updated */
+-};
+-
+ struct mt_class {
+ 	__s32 name;	/* MT_CLS */
+ 	__s32 quirks;
+@@ -76,7 +69,6 @@ struct mt_fields {
+ };
+ 
+ struct mt_device {
+-	struct mt_slot curdata;	/* placeholder of incoming data */
+ 	struct mt_class mtclass;	/* our mt device class */
+ 	struct mt_fields *fields;	/* temporary placeholder for storing the
+ 					   multitouch fields */
+@@ -93,7 +85,9 @@ struct mt_device {
+ 				* 1 means we should use a serial protocol
+ 				* > 1 means hybrid (multitouch) protocol */
+ 	bool curvalid;		/* is the current contact valid? */
+-	struct mt_slot *slots;
++	__s32 x, y, p, w, h;
++	__s32 contactid;	/* the device ContactID assigned to this slot */
++	bool touch_state;	/* is the touch valid? */
+ };
+ 
+ /* classes of device behavior */
+@@ -128,31 +122,12 @@ struct mt_device {
+ 
+ static int cypress_compute_slot(struct mt_device *td)
+ {
+-	if (td->curdata.contactid != 0 || td->num_received == 0)
+-		return td->curdata.contactid;
++	if (td->contactid != 0 || td->num_received == 0)
++		return td->contactid;
+ 	else
+ 		return -1;
+ }
+ 
+-static int find_slot_from_contactid(struct mt_device *td)
+-{
+-	int i;
+-	for (i = 0; i < td->maxcontacts; ++i) {
+-		if (td->slots[i].contactid == td->curdata.contactid &&
+-			td->slots[i].touch_state)
+-			return i;
+-	}
+-	for (i = 0; i < td->maxcontacts; ++i) {
+-		if (!td->slots[i].seen_in_this_frame &&
+-			!td->slots[i].touch_state)
+-			return i;
+-	}
+-	/* should not occurs. If this happens that means
+-	 * that the device sent more touches that it says
+-	 * in the report descriptor. It is ignored then. */
+-	return -1;
+-}
+-
+ static struct mt_class mt_classes[] = {
+ 	{ .name = MT_CLS_DEFAULT,
+ 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
+@@ -390,7 +365,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ 		case HID_DG_CONTACTID:
+ 			if (!td->maxcontacts)
+ 				td->maxcontacts = MT_DEFAULT_MAXCONTACT;
+-			input_mt_init_slots(hi->input, td->maxcontacts, 0);
+ 			mt_store_field(usage, td, hi);
+ 			td->last_field_index = field->index;
+ 			td->touches_by_report++;
+@@ -464,12 +438,31 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ 	return -1;
+ }
+ 
+-static int mt_compute_slot(struct mt_device *td)
++static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
++
++{
++	struct mt_device *td = hid_get_drvdata(hdev);
++	struct mt_class *cls = &td->mtclass;
++	struct input_dev *input = hi->input;
++	unsigned int flags = 0;
++
++	if (test_bit(INPUT_PROP_POINTER, input->propbit))
++		flags |= INPUT_MT_POINTER;
++	if (test_bit(INPUT_PROP_DIRECT, input->propbit))
++		flags |= INPUT_MT_DIRECT;
++
++	if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
++		flags |= INPUT_MT_DROP_UNUSED;
++
++	input_mt_init_slots(input, td->maxcontacts, flags);
++}
++
++static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
+ {
+ 	__s32 quirks = td->mtclass.quirks;
+ 
+ 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
+-		return td->curdata.contactid;
++		return td->contactid;
+ 
+ 	if (quirks & MT_QUIRK_CYPRESS)
+ 		return cypress_compute_slot(td);
+@@ -478,25 +471,43 @@ static int mt_compute_slot(struct mt_device *td)
+ 		return td->num_received;
+ 
+ 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
+-		return td->curdata.contactid - 1;
++		return td->contactid - 1;
+ 
+-	return find_slot_from_contactid(td);
++	return input_mt_assign_slot_by_id(input, td->contactid);
+ }
+ 
+ /*
+  * this function is called when a whole contact has been processed,
+  * so that it can assign it to a slot and store the data there
+  */
+-static void mt_complete_slot(struct mt_device *td)
++static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
+ {
+-	td->curdata.seen_in_this_frame = true;
+-	if (td->curvalid) {
+-		int slotnum = mt_compute_slot(td);
++	int slot;
+ 
+-		if (slotnum >= 0 && slotnum < td->maxcontacts)
+-			td->slots[slotnum] = td->curdata;
+-	}
+ 	td->num_received++;
++	if (!td->curvalid)
++		return;
++
++	slot = mt_compute_slot(td, input);
++	if (slot < 0 || slot >= td->maxcontacts)
++		return;
++
++	input_mt_slot(input, slot);
++	input_mt_report_slot_state(input, MT_TOOL_FINGER, td->touch_state);
++	if (td->touch_state) {
++		/* this finger is on the screen */
++		int wide = (td->w > td->h);
++		/* divided by two to match visual scale of touch */
++		int major = max(td->w, td->h) >> 1;
++		int minor = min(td->w, td->h) >> 1;
++
++		input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
++		input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
++		input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
++		input_event(input, EV_ABS, ABS_MT_PRESSURE, td->p);
++		input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
++		input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
 +	}
-+
- 	/* dump HID report descriptor */
--	for (i = 0; i < hdev->rsize; i++)
--		seq_printf(f, "%02x ", hdev->rdesc[i]);
-+	for (i = 0; i < rsize; i++)
-+		seq_printf(f, "%02x ", rdesc[i]);
- 	seq_printf(f, "\n\n");
- 
- 	/* dump parsed data and input mappings */
+ }
+ 
+ 
+@@ -504,52 +515,20 @@ static void mt_complete_slot(struct mt_device *td)
+  * this function is called when a whole packet has been received and processed,
+  * so that it can decide what to send to the input layer.
+  */
+-static void mt_emit_event(struct mt_device *td, struct input_dev *input)
++static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
+ {
+-	int i;
+-
+-	for (i = 0; i < td->maxcontacts; ++i) {
+-		struct mt_slot *s = &(td->slots[i]);
+-		if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) &&
+-			!s->seen_in_this_frame) {
+-			s->touch_state = false;
+-		}
+-
+-		input_mt_slot(input, i);
+-		input_mt_report_slot_state(input, MT_TOOL_FINGER,
+-			s->touch_state);
+-		if (s->touch_state) {
+-			/* this finger is on the screen */
+-			int wide = (s->w > s->h);
+-			/* divided by two to match visual scale of touch */
+-			int major = max(s->w, s->h) >> 1;
+-			int minor = min(s->w, s->h) >> 1;
+-
+-			input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
+-			input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
+-			input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
+-			input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
+-			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
+-			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
+-		}
+-		s->seen_in_this_frame = false;
+-
+-	}
+-
+-	input_mt_report_pointer_emulation(input, true);
++	input_mt_sync_frame(input);
+ 	input_sync(input);
+ 	td->num_received = 0;
+ }
+ 
+-
+-
+ static int mt_event(struct hid_device *hid, struct hid_field *field,
+ 				struct hid_usage *usage, __s32 value)
+ {
+ 	struct mt_device *td = hid_get_drvdata(hid);
+ 	__s32 quirks = td->mtclass.quirks;
+ 
+-	if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
++	if (hid->claimed & HID_CLAIMED_INPUT) {
+ 		switch (usage->hid) {
+ 		case HID_DG_INRANGE:
+ 			if (quirks & MT_QUIRK_ALWAYS_VALID)
+@@ -560,29 +539,29 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
+ 		case HID_DG_TIPSWITCH:
+ 			if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
+ 				td->curvalid = value;
+-			td->curdata.touch_state = value;
++			td->touch_state = value;
+ 			break;
+ 		case HID_DG_CONFIDENCE:
+ 			if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
+ 				td->curvalid = value;
+ 			break;
+ 		case HID_DG_CONTACTID:
+-			td->curdata.contactid = value;
++			td->contactid = value;
+ 			break;
+ 		case HID_DG_TIPPRESSURE:
+-			td->curdata.p = value;
++			td->p = value;
+ 			break;
+ 		case HID_GD_X:
+-			td->curdata.x = value;
++			td->x = value;
+ 			break;
+ 		case HID_GD_Y:
+-			td->curdata.y = value;
++			td->y = value;
+ 			break;
+ 		case HID_DG_WIDTH:
+-			td->curdata.w = value;
++			td->w = value;
+ 			break;
+ 		case HID_DG_HEIGHT:
+-			td->curdata.h = value;
++			td->h = value;
+ 			break;
+ 		case HID_DG_CONTACTCOUNT:
+ 			/*
+@@ -602,11 +581,11 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
+ 		}
+ 
+ 		if (usage->hid == td->last_slot_field)
+-			mt_complete_slot(td);
++			mt_complete_slot(td, field->hidinput->input);
+ 
+ 		if (field->index == td->last_field_index
+ 			&& td->num_received >= td->num_expected)
+-			mt_emit_event(td, field->hidinput->input);
++			mt_sync_frame(td, field->hidinput->input);
+ 
+ 	}
+ 
+@@ -733,15 +712,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ 	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
+ 		mt_post_parse_default_settings(td);
+ 
+-	td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
+-				GFP_KERNEL);
+-	if (!td->slots) {
+-		dev_err(&hdev->dev, "cannot allocate multitouch slots\n");
+-		hid_hw_stop(hdev);
+-		ret = -ENOMEM;
+-		goto fail;
+-	}
+-
+ 	ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
+ 
+ 	mt_set_maxcontacts(hdev);
+@@ -772,7 +742,6 @@ static void mt_remove(struct hid_device *hdev)
+ 	struct mt_device *td = hid_get_drvdata(hdev);
+ 	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
+ 	hid_hw_stop(hdev);
+-	kfree(td->slots);
+ 	kfree(td);
+ 	hid_set_drvdata(hdev, NULL);
+ }
+@@ -1085,6 +1054,7 @@ static struct hid_driver mt_driver = {
+ 	.remove = mt_remove,
+ 	.input_mapping = mt_input_mapping,
+ 	.input_mapped = mt_input_mapped,
++	.input_configured = mt_input_configured,
+ 	.feature_mapping = mt_feature_mapping,
+ 	.usage_table = mt_grabbed_usages,
+ 	.event = mt_event,
 -- 
-1.7.12
+1.7.11.4
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help