All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
@ 2011-01-05 17:27 ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input, linux-kernel
  Cc: Benjamin Tissoires

Hi,

these patches is the set for the unified driver hid-multitouch.
I'm putting the flag RFC as I'm still waiting some testers feedback on some devices. But I don't think they will change a lot.

This would be great if this stuff could go into 2.6.38, if it's not too late.

These patches applies on top of Dmitry's next branch.

Cheers,
Benjamin

--

 drivers/hid/Kconfig          |   30 +--
 drivers/hid/Makefile         |    5 +-
 drivers/hid/hid-cando.c      |  274 ----------------------
 drivers/hid/hid-core.c       |    6 +-
 drivers/hid/hid-ids.h        |    7 +
 drivers/hid/hid-input.c      |   10 +-
 drivers/hid/hid-mosart.c     |  275 ----------------------
 drivers/hid/hid-multitouch.c |  526 ++++++++++++++++++++++++++++++++++++++++++
 drivers/hid/hid-quanta.c     |  261 ---------------------
 drivers/hid/hid-stantum.c    |  286 -----------------------
 include/linux/hid.h          |    6 +-
 11 files changed, 559 insertions(+), 1127 deletions(-)



^ permalink raw reply	[flat|nested] 56+ messages in thread

* [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
@ 2011-01-05 17:27 ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input
  Cc: Benjamin Tissoires

Hi,

these patches is the set for the unified driver hid-multitouch.
I'm putting the flag RFC as I'm still waiting some testers feedback on some devices. But I don't think they will change a lot.

This would be great if this stuff could go into 2.6.38, if it's not too late.

These patches applies on top of Dmitry's next branch.

Cheers,
Benjamin

--

 drivers/hid/Kconfig          |   30 +--
 drivers/hid/Makefile         |    5 +-
 drivers/hid/hid-cando.c      |  274 ----------------------
 drivers/hid/hid-core.c       |    6 +-
 drivers/hid/hid-ids.h        |    7 +
 drivers/hid/hid-input.c      |   10 +-
 drivers/hid/hid-mosart.c     |  275 ----------------------
 drivers/hid/hid-multitouch.c |  526 ++++++++++++++++++++++++++++++++++++++++++
 drivers/hid/hid-quanta.c     |  261 ---------------------
 drivers/hid/hid-stantum.c    |  286 -----------------------
 include/linux/hid.h          |    6 +-
 11 files changed, 559 insertions(+), 1127 deletions(-)



^ permalink raw reply	[flat|nested] 56+ messages in thread

* [RFC v2 01/10] hid: add feature_mapping callback
  2011-01-05 17:27 ` Benjamin Tissoires
@ 2011-01-05 17:27   ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input, linux-kernel
  Cc: Benjamin Tissoires

Currently hid doesn't export the features it knows to the specific modules.
Some information can be really important in such features: MosArt and
Cypress devices are by default not in a multitouch mode.
We have to send the value 2 on the right feature.

This patch exports to the module the features report so they can find the
right feature to set up the correct mode.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
---
 drivers/hid/hid-input.c |   10 +++++++++-
 include/linux/hid.h     |    4 ++++
 2 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index bb0b365..07d8cb2 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -287,6 +287,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 		goto ignore;
 	}
 
+	if (field->report_type == HID_FEATURE_REPORT) {
+		if (device->driver->feature_mapping) {
+			device->driver->feature_mapping(device, hidinput, field,
+                                usage);
+		}
+		goto ignore;
+	}
+
 	if (device->driver->input_mapping) {
 		int ret = device->driver->input_mapping(device, hidinput, field,
 				usage, &bit, &max);
@@ -836,7 +844,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 	struct hid_input *hidinput = NULL;
 	struct input_dev *input_dev;
 	int i, j, k;
-	int max_report_type = HID_OUTPUT_REPORT;
+	int max_report_type = HID_FEATURE_REPORT;
 
 	INIT_LIST_HEAD(&hid->inputs);
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index bb0f56f..75303b0 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -593,6 +593,7 @@ struct hid_usage_id {
  * @report_fixup: called before report descriptor parsing (NULL means nop)
  * @input_mapping: invoked on input registering before mapping an usage
  * @input_mapped: invoked on input registering after mapping an usage
+ * @feature_mapping: invoked on feature registering
  * @suspend: invoked on suspend (NULL means nop)
  * @resume: invoked on resume if device was not reset (NULL means nop)
  * @reset_resume: invoked on resume if device was reset (NULL means nop)
@@ -636,6 +637,9 @@ struct hid_driver {
 	int (*input_mapped)(struct hid_device *hdev,
 			struct hid_input *hidinput, struct hid_field *field,
 			struct hid_usage *usage, unsigned long **bit, int *max);
+	void (*feature_mapping)(struct hid_device *hdev,
+ 			struct hid_input *hidinput, struct hid_field *field,
+ 			struct hid_usage *usage);
 #ifdef CONFIG_PM
 	int (*suspend)(struct hid_device *hdev, pm_message_t message);
 	int (*resume)(struct hid_device *hdev);
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 01/10] hid: add feature_mapping callback
@ 2011-01-05 17:27   ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input
  Cc: Benjamin Tissoires

Currently hid doesn't export the features it knows to the specific modules.
Some information can be really important in such features: MosArt and
Cypress devices are by default not in a multitouch mode.
We have to send the value 2 on the right feature.

This patch exports to the module the features report so they can find the
right feature to set up the correct mode.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
---
 drivers/hid/hid-input.c |   10 +++++++++-
 include/linux/hid.h     |    4 ++++
 2 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index bb0b365..07d8cb2 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -287,6 +287,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 		goto ignore;
 	}
 
+	if (field->report_type == HID_FEATURE_REPORT) {
+		if (device->driver->feature_mapping) {
+			device->driver->feature_mapping(device, hidinput, field,
+                                usage);
+		}
+		goto ignore;
+	}
+
 	if (device->driver->input_mapping) {
 		int ret = device->driver->input_mapping(device, hidinput, field,
 				usage, &bit, &max);
@@ -836,7 +844,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 	struct hid_input *hidinput = NULL;
 	struct input_dev *input_dev;
 	int i, j, k;
-	int max_report_type = HID_OUTPUT_REPORT;
+	int max_report_type = HID_FEATURE_REPORT;
 
 	INIT_LIST_HEAD(&hid->inputs);
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index bb0f56f..75303b0 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -593,6 +593,7 @@ struct hid_usage_id {
  * @report_fixup: called before report descriptor parsing (NULL means nop)
  * @input_mapping: invoked on input registering before mapping an usage
  * @input_mapped: invoked on input registering after mapping an usage
+ * @feature_mapping: invoked on feature registering
  * @suspend: invoked on suspend (NULL means nop)
  * @resume: invoked on resume if device was not reset (NULL means nop)
  * @reset_resume: invoked on resume if device was reset (NULL means nop)
@@ -636,6 +637,9 @@ struct hid_driver {
 	int (*input_mapped)(struct hid_device *hdev,
 			struct hid_input *hidinput, struct hid_field *field,
 			struct hid_usage *usage, unsigned long **bit, int *max);
+	void (*feature_mapping)(struct hid_device *hdev,
+ 			struct hid_input *hidinput, struct hid_field *field,
+ 			struct hid_usage *usage);
 #ifdef CONFIG_PM
 	int (*suspend)(struct hid_device *hdev, pm_message_t message);
 	int (*resume)(struct hid_device *hdev);
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 02/10] hid: set HID_MAX_FIELD at 128
  2011-01-05 17:27 ` Benjamin Tissoires
@ 2011-01-05 17:27   ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input, linux-kernel
  Cc: Benjamin Tissoires

Stantums multitouch panels sends more than 64 reports and this results
in not being able to handle all the touches given by this device.

This patch is required to be able to include Stantum panels in the
unified hid-multitouch driver.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
---
 include/linux/hid.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/linux/hid.h b/include/linux/hid.h
index 75303b0..b76af97 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -402,7 +402,7 @@ struct hid_field {
 	__u16 dpad;			/* dpad input code */
 };
 
-#define HID_MAX_FIELDS 64
+#define HID_MAX_FIELDS 128
 
 struct hid_report {
 	struct list_head list;
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 02/10] hid: set HID_MAX_FIELD at 128
@ 2011-01-05 17:27   ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input
  Cc: Benjamin Tissoires

Stantums multitouch panels sends more than 64 reports and this results
in not being able to handle all the touches given by this device.

This patch is required to be able to include Stantum panels in the
unified hid-multitouch driver.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
---
 include/linux/hid.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/linux/hid.h b/include/linux/hid.h
index 75303b0..b76af97 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -402,7 +402,7 @@ struct hid_field {
 	__u16 dpad;			/* dpad input code */
 };
 
-#define HID_MAX_FIELDS 64
+#define HID_MAX_FIELDS 128
 
 struct hid_report {
 	struct list_head list;
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
  2011-01-05 17:27 ` Benjamin Tissoires
@ 2011-01-05 17:27   ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input, linux-kernel
  Cc: Benjamin Tissoires

Created a driver for PixCir based dual-touch panels, including the one
in the Hanvon tablet.  This is done in a code structure aimed at unifying
support for several existing HID multitouch panels.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/Kconfig          |    6 +
 drivers/hid/Makefile         |    1 +
 drivers/hid/hid-core.c       |    2 +
 drivers/hid/hid-ids.h        |    4 +
 drivers/hid/hid-multitouch.c |  434 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 447 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hid/hid-multitouch.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 401acec..6519981 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -285,6 +285,12 @@ config HID_MONTEREY
 	---help---
 	Support for Monterey Genius KB29E.
 
+config HID_MULTITOUCH
+	tristate "HID Multitouch panels"
+	depends on USB_HID
+	---help---
+	Generic support for HID multitouch panels.
+
 config HID_NTRIG
 	tristate "N-Trig touch screen"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index c335605..ec991d4 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
 obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
 obj-$(CONFIG_HID_MOSART)	+= hid-mosart.o
+obj-$(CONFIG_HID_MULTITOUCH)	+= hid-multitouch.o
 obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
 obj-$(CONFIG_HID_ORTEK)		+= hid-ortek.o
 obj-$(CONFIG_HID_PRODIKEYS)	+= hid-prodikeys.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 88668ae..2b4d9b9 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1286,6 +1286,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
@@ -1312,6 +1313,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 0f150c7..17b444b 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -134,6 +134,7 @@
 #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2	0x5577
 
 #define USB_VENDOR_ID_CANDO		0x2087
+#define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH	0x0a01
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
@@ -306,6 +307,9 @@
 #define USB_DEVICE_ID_HANWANG_TABLET_FIRST	0x5000
 #define USB_DEVICE_ID_HANWANG_TABLET_LAST	0x8fff
 
+#define USB_VENDOR_ID_HANVON		0x20b3
+#define USB_DEVICE_ID_HANVON_MULTITOUCH	0x0a18
+
 #define USB_VENDOR_ID_HAPP		0x078b
 #define USB_DEVICE_ID_UGCI_DRIVING	0x0010
 #define USB_DEVICE_ID_UGCI_FLYING	0x0020
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
new file mode 100644
index 0000000..aea0e32
--- /dev/null
+++ b/drivers/hid/hid-multitouch.c
@@ -0,0 +1,434 @@
+/*
+ *  HID driver for multitouch panels
+ *
+ *  Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr>
+ *  Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ *  Copyright (c) 2010-2011 Enac
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/input/mt.h>
+#include "usbhid/usbhid.h"
+
+
+MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
+MODULE_DESCRIPTION("HID multitouch panels");
+MODULE_LICENSE("GPL");
+
+#include "hid-ids.h"
+
+
+struct mt_slot {
+	__s32 x, y, p;
+	__s32 contactid;	/* the device ContactID assigned to this slot */
+	__u16 trkid;	/* the tracking ID that was assigned to this slot */
+	bool valid;	/* did we just get valid contact data for this slot? */
+	bool prev_valid;/* was this slot previously valid/active? */
+};
+
+struct mt_buffer {
+	__s32 x, y, p;
+	__s32 contactid;	/* the device ContactID assigned to this slot */
+};
+
+struct mt_device {
+	struct mt_buffer curdata;	/* placeholder of incoming data */
+	struct mt_class *mtclass;	/* our mt device class */
+	unsigned last_field_index;	/* last field index of the report */
+	unsigned last_slot_field;	/* the last field of a slot */
+	__u16 lasttrkid;	/* the last tracking ID we assigned */
+	__s8 inputmode;		/* InputMode HID feature, -1 if non-existent */
+	__u8 num_received;	/* how many contacts we received */
+	__u8 maxcontact;	/* expected last contact index */
+	bool curvalid;		/* is the current contact valid? */
+	struct mt_slot slots[0];	/* first slot */
+};
+
+struct mt_class {
+	int (*compute_slot)(struct mt_device *);
+	__u8 maxcontacts;
+};
+
+/* classes of device behavior */
+#define MT_CLS_DEFAULT 0
+#define MT_CLS_DUAL1 1
+
+/*
+ * these device-dependent functions determine what slot corresponds
+ * to a valid contact that was just read.
+ */
+
+static int slot_is_contactid(struct mt_device *td)
+{
+	return td->curdata.contactid;
+}
+
+static int find_slot_from_contactid(struct mt_device *td)
+{
+	int i;
+	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+		if (td->slots[i].prev_valid &&
+			td->slots[i].contactid == td->curdata.contactid)
+			return i;
+	}
+	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+		if (!td->slots[i].valid && !td->slots[i].prev_valid)
+			return i;
+	}
+	return -1; /* should not occurs */
+}
+
+struct mt_class mt_classes[] = {
+	{ find_slot_from_contactid, 10 },     /* MT_CLS_DEFAULT */
+	{ slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
+};
+
+static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage)
+{
+	if (usage->hid == HID_DG_INPUTMODE) {
+		struct mt_device *td = hid_get_drvdata(hdev);
+		td->inputmode = field->report->id;
+	}
+}
+
+static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	switch (usage->hid & HID_USAGE_PAGE) {
+
+	case HID_UP_GENDESK:
+		switch (usage->hid) {
+		case HID_GD_X:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_X);
+			input_set_abs_params(hi->input, ABS_MT_POSITION_X,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_X,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_GD_Y:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_Y);
+			input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_Y,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			td->last_slot_field = usage->hid;
+			return 1;
+		}
+		return 0;
+
+	case HID_UP_DIGITIZER:
+		switch (usage->hid) {
+		case HID_DG_INRANGE:
+		case HID_DG_CONFIDENCE:
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_TIPSWITCH:
+			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
+			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_CONTACTID:
+			if (!hi->input->mt)
+				input_mt_init_slots(hi->input,
+						td->mtclass->maxcontacts);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_TIPPRESSURE:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_PRESSURE);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_CONTACTCOUNT:
+			td->last_field_index = field->report->maxfield - 1;
+		case HID_DG_CONTACTMAX:
+			/* we don't set td->last_slot_field as contactcount and
+			 * contact max are global to the report */
+			return -1;
+		}
+		/* let hid-input decide for the others */
+		return 0;
+
+	case 0xff000000:
+		/* we do not want to map these: no input-oriented meaning */
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if (usage->type == EV_KEY || usage->type == EV_ABS)
+		set_bit(usage->type, hi->input->evbit);
+
+	return -1;
+}
+
+/*
+ * 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)
+{
+	if (td->curvalid) {
+		struct mt_slot *slot;
+		int slotnum = td->mtclass->compute_slot(td);
+
+		if (slotnum >= 0 && slotnum <= td->mtclass->maxcontacts - 1) {
+			slot = td->slots + slotnum;
+
+			slot->valid = true;
+			memcpy(slot, &(td->curdata), sizeof(struct mt_buffer));
+		}
+	}
+	td->num_received++;
+}
+
+
+/*
+ * 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)
+{
+	int i;
+
+	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+		struct mt_slot *s = &(td->slots[i]);
+		if (!s->valid) {
+			/*
+			 * this slot does not contain useful data,
+			 * notify its closure if necessary
+			 */
+			if (s->prev_valid) {
+				input_mt_slot(input, i);
+				input_mt_report_slot_state(input,
+					MT_TOOL_FINGER, false);
+				s->prev_valid = false;
+			}
+			continue;
+		}
+		if (!s->prev_valid)
+			s->trkid = td->lasttrkid++;
+
+		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
+		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_PRESSURE, s->p);
+		s->prev_valid = true;
+		s->valid = false;
+
+	}
+
+	input_mt_report_pointer_emulation(input, true);
+	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);
+
+	if (hid->claimed & HID_CLAIMED_INPUT) {
+		switch (usage->hid) {
+		case HID_DG_INRANGE:
+			break;
+		case HID_DG_TIPSWITCH:
+			td->curvalid = value;
+			break;
+		case HID_DG_CONFIDENCE:
+			break;
+		case HID_DG_CONTACTID:
+			td->curdata.contactid = value;
+			break;
+		case HID_DG_TIPPRESSURE:
+			td->curdata.p = value;
+			break;
+		case HID_GD_X:
+			td->curdata.x = value;
+			break;
+		case HID_GD_Y:
+			td->curdata.y = value;
+			break;
+		case HID_DG_CONTACTCOUNT:
+			/*
+			 * We must not overwrite the previous value (some
+			 * devices send one sequence splitted over several
+			 * messages)
+			 */
+			if (value)
+				td->maxcontact = value - 1;
+			break;
+		case HID_DG_CONTACTMAX:
+			break;
+
+		default:
+			/* fallback to the generic hidinput handling */
+			return 0;
+		}
+	}
+
+	if (usage->hid == td->last_slot_field)
+		mt_complete_slot(td);
+
+	if (field->index == td->last_field_index
+		&& td->num_received > td->maxcontact) {
+		struct input_dev *input = field->hidinput->input;
+		mt_emit_event(td, input);
+	}
+
+	/* we have handled the hidinput part, now remains hiddev */
+	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+		hid->hiddev_hid_event(hid, field, usage, value);
+
+	return 1;
+}
+
+static void mt_set_input_mode(struct hid_device *hdev)
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	struct hid_report *r;
+	struct hid_report_enum *re;
+
+	if (td->inputmode < 0)
+		return;
+
+	re = &(hdev->report_enum[HID_FEATURE_REPORT]);
+	r = re->report_id_hash[td->inputmode];
+	if (r) {
+		r->field[0]->value[0] = 0x02;
+		usbhid_submit_report(hdev, r, USB_DIR_OUT);
+	}
+}
+
+static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+	struct mt_device *td;
+	struct mt_class *mtclass = mt_classes + id->driver_data;
+
+	/* This allows the driver to correctly support devices
+	 * that emit events over several HID messages.
+	 */
+	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
+
+	td = kzalloc(sizeof(struct mt_device) +
+				mtclass->maxcontacts * sizeof(struct mt_slot),
+				GFP_KERNEL);
+	if (!td) {
+		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
+		return -ENOMEM;
+	}
+	td->mtclass = mtclass;
+	td->inputmode = -1;
+	hid_set_drvdata(hdev, td);
+
+	ret = hid_parse(hdev);
+	if (ret != 0)
+		goto fail;
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret != 0)
+		goto fail;
+
+	mt_set_input_mode(hdev);
+
+	return 0;
+
+fail:
+	kfree(td);
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int mt_reset_resume(struct hid_device *hdev)
+{
+	mt_set_input_mode(hdev);
+	return 0;
+}
+#endif
+
+static void mt_remove(struct hid_device *hdev)
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	hid_hw_stop(hdev);
+	kfree(td);
+	hid_set_drvdata(hdev, NULL);
+}
+
+static const struct hid_device_id mt_devices[] = {
+
+	/* PixCir-based panels */
+	{ .driver_data = MT_CLS_DUAL1,
+		HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
+			USB_DEVICE_ID_HANVON_MULTITOUCH) },
+	{ .driver_data = MT_CLS_DUAL1,
+		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
+
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, mt_devices);
+
+static const struct hid_usage_id mt_grabbed_usages[] = {
+	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
+	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+};
+
+static struct hid_driver mt_driver = {
+	.name = "hid-multitouch",
+	.id_table = mt_devices,
+	.probe = mt_probe,
+	.remove = mt_remove,
+	.input_mapping = mt_input_mapping,
+	.input_mapped = mt_input_mapped,
+	.feature_mapping = mt_feature_mapping,
+	.usage_table = mt_grabbed_usages,
+	.event = mt_event,
+#ifdef CONFIG_PM
+	.reset_resume = mt_reset_resume,
+#endif
+};
+
+static int __init mt_init(void)
+{
+	return hid_register_driver(&mt_driver);
+}
+
+static void __exit mt_exit(void)
+{
+	hid_unregister_driver(&mt_driver);
+}
+
+module_init(mt_init);
+module_exit(mt_exit);
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
@ 2011-01-05 17:27   ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input
  Cc: Benjamin Tissoires

Created a driver for PixCir based dual-touch panels, including the one
in the Hanvon tablet.  This is done in a code structure aimed at unifying
support for several existing HID multitouch panels.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/Kconfig          |    6 +
 drivers/hid/Makefile         |    1 +
 drivers/hid/hid-core.c       |    2 +
 drivers/hid/hid-ids.h        |    4 +
 drivers/hid/hid-multitouch.c |  434 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 447 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hid/hid-multitouch.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 401acec..6519981 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -285,6 +285,12 @@ config HID_MONTEREY
 	---help---
 	Support for Monterey Genius KB29E.
 
+config HID_MULTITOUCH
+	tristate "HID Multitouch panels"
+	depends on USB_HID
+	---help---
+	Generic support for HID multitouch panels.
+
 config HID_NTRIG
 	tristate "N-Trig touch screen"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index c335605..ec991d4 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
 obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
 obj-$(CONFIG_HID_MOSART)	+= hid-mosart.o
+obj-$(CONFIG_HID_MULTITOUCH)	+= hid-multitouch.o
 obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
 obj-$(CONFIG_HID_ORTEK)		+= hid-ortek.o
 obj-$(CONFIG_HID_PRODIKEYS)	+= hid-prodikeys.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 88668ae..2b4d9b9 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1286,6 +1286,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
@@ -1312,6 +1313,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 0f150c7..17b444b 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -134,6 +134,7 @@
 #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2	0x5577
 
 #define USB_VENDOR_ID_CANDO		0x2087
+#define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH	0x0a01
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
@@ -306,6 +307,9 @@
 #define USB_DEVICE_ID_HANWANG_TABLET_FIRST	0x5000
 #define USB_DEVICE_ID_HANWANG_TABLET_LAST	0x8fff
 
+#define USB_VENDOR_ID_HANVON		0x20b3
+#define USB_DEVICE_ID_HANVON_MULTITOUCH	0x0a18
+
 #define USB_VENDOR_ID_HAPP		0x078b
 #define USB_DEVICE_ID_UGCI_DRIVING	0x0010
 #define USB_DEVICE_ID_UGCI_FLYING	0x0020
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
new file mode 100644
index 0000000..aea0e32
--- /dev/null
+++ b/drivers/hid/hid-multitouch.c
@@ -0,0 +1,434 @@
+/*
+ *  HID driver for multitouch panels
+ *
+ *  Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr>
+ *  Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ *  Copyright (c) 2010-2011 Enac
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/input/mt.h>
+#include "usbhid/usbhid.h"
+
+
+MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
+MODULE_DESCRIPTION("HID multitouch panels");
+MODULE_LICENSE("GPL");
+
+#include "hid-ids.h"
+
+
+struct mt_slot {
+	__s32 x, y, p;
+	__s32 contactid;	/* the device ContactID assigned to this slot */
+	__u16 trkid;	/* the tracking ID that was assigned to this slot */
+	bool valid;	/* did we just get valid contact data for this slot? */
+	bool prev_valid;/* was this slot previously valid/active? */
+};
+
+struct mt_buffer {
+	__s32 x, y, p;
+	__s32 contactid;	/* the device ContactID assigned to this slot */
+};
+
+struct mt_device {
+	struct mt_buffer curdata;	/* placeholder of incoming data */
+	struct mt_class *mtclass;	/* our mt device class */
+	unsigned last_field_index;	/* last field index of the report */
+	unsigned last_slot_field;	/* the last field of a slot */
+	__u16 lasttrkid;	/* the last tracking ID we assigned */
+	__s8 inputmode;		/* InputMode HID feature, -1 if non-existent */
+	__u8 num_received;	/* how many contacts we received */
+	__u8 maxcontact;	/* expected last contact index */
+	bool curvalid;		/* is the current contact valid? */
+	struct mt_slot slots[0];	/* first slot */
+};
+
+struct mt_class {
+	int (*compute_slot)(struct mt_device *);
+	__u8 maxcontacts;
+};
+
+/* classes of device behavior */
+#define MT_CLS_DEFAULT 0
+#define MT_CLS_DUAL1 1
+
+/*
+ * these device-dependent functions determine what slot corresponds
+ * to a valid contact that was just read.
+ */
+
+static int slot_is_contactid(struct mt_device *td)
+{
+	return td->curdata.contactid;
+}
+
+static int find_slot_from_contactid(struct mt_device *td)
+{
+	int i;
+	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+		if (td->slots[i].prev_valid &&
+			td->slots[i].contactid == td->curdata.contactid)
+			return i;
+	}
+	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+		if (!td->slots[i].valid && !td->slots[i].prev_valid)
+			return i;
+	}
+	return -1; /* should not occurs */
+}
+
+struct mt_class mt_classes[] = {
+	{ find_slot_from_contactid, 10 },     /* MT_CLS_DEFAULT */
+	{ slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
+};
+
+static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage)
+{
+	if (usage->hid == HID_DG_INPUTMODE) {
+		struct mt_device *td = hid_get_drvdata(hdev);
+		td->inputmode = field->report->id;
+	}
+}
+
+static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	switch (usage->hid & HID_USAGE_PAGE) {
+
+	case HID_UP_GENDESK:
+		switch (usage->hid) {
+		case HID_GD_X:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_X);
+			input_set_abs_params(hi->input, ABS_MT_POSITION_X,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_X,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_GD_Y:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_Y);
+			input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_Y,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			td->last_slot_field = usage->hid;
+			return 1;
+		}
+		return 0;
+
+	case HID_UP_DIGITIZER:
+		switch (usage->hid) {
+		case HID_DG_INRANGE:
+		case HID_DG_CONFIDENCE:
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_TIPSWITCH:
+			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
+			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_CONTACTID:
+			if (!hi->input->mt)
+				input_mt_init_slots(hi->input,
+						td->mtclass->maxcontacts);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_TIPPRESSURE:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_PRESSURE);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_CONTACTCOUNT:
+			td->last_field_index = field->report->maxfield - 1;
+		case HID_DG_CONTACTMAX:
+			/* we don't set td->last_slot_field as contactcount and
+			 * contact max are global to the report */
+			return -1;
+		}
+		/* let hid-input decide for the others */
+		return 0;
+
+	case 0xff000000:
+		/* we do not want to map these: no input-oriented meaning */
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if (usage->type == EV_KEY || usage->type == EV_ABS)
+		set_bit(usage->type, hi->input->evbit);
+
+	return -1;
+}
+
+/*
+ * 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)
+{
+	if (td->curvalid) {
+		struct mt_slot *slot;
+		int slotnum = td->mtclass->compute_slot(td);
+
+		if (slotnum >= 0 && slotnum <= td->mtclass->maxcontacts - 1) {
+			slot = td->slots + slotnum;
+
+			slot->valid = true;
+			memcpy(slot, &(td->curdata), sizeof(struct mt_buffer));
+		}
+	}
+	td->num_received++;
+}
+
+
+/*
+ * 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)
+{
+	int i;
+
+	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+		struct mt_slot *s = &(td->slots[i]);
+		if (!s->valid) {
+			/*
+			 * this slot does not contain useful data,
+			 * notify its closure if necessary
+			 */
+			if (s->prev_valid) {
+				input_mt_slot(input, i);
+				input_mt_report_slot_state(input,
+					MT_TOOL_FINGER, false);
+				s->prev_valid = false;
+			}
+			continue;
+		}
+		if (!s->prev_valid)
+			s->trkid = td->lasttrkid++;
+
+		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
+		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_PRESSURE, s->p);
+		s->prev_valid = true;
+		s->valid = false;
+
+	}
+
+	input_mt_report_pointer_emulation(input, true);
+	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);
+
+	if (hid->claimed & HID_CLAIMED_INPUT) {
+		switch (usage->hid) {
+		case HID_DG_INRANGE:
+			break;
+		case HID_DG_TIPSWITCH:
+			td->curvalid = value;
+			break;
+		case HID_DG_CONFIDENCE:
+			break;
+		case HID_DG_CONTACTID:
+			td->curdata.contactid = value;
+			break;
+		case HID_DG_TIPPRESSURE:
+			td->curdata.p = value;
+			break;
+		case HID_GD_X:
+			td->curdata.x = value;
+			break;
+		case HID_GD_Y:
+			td->curdata.y = value;
+			break;
+		case HID_DG_CONTACTCOUNT:
+			/*
+			 * We must not overwrite the previous value (some
+			 * devices send one sequence splitted over several
+			 * messages)
+			 */
+			if (value)
+				td->maxcontact = value - 1;
+			break;
+		case HID_DG_CONTACTMAX:
+			break;
+
+		default:
+			/* fallback to the generic hidinput handling */
+			return 0;
+		}
+	}
+
+	if (usage->hid == td->last_slot_field)
+		mt_complete_slot(td);
+
+	if (field->index == td->last_field_index
+		&& td->num_received > td->maxcontact) {
+		struct input_dev *input = field->hidinput->input;
+		mt_emit_event(td, input);
+	}
+
+	/* we have handled the hidinput part, now remains hiddev */
+	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+		hid->hiddev_hid_event(hid, field, usage, value);
+
+	return 1;
+}
+
+static void mt_set_input_mode(struct hid_device *hdev)
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	struct hid_report *r;
+	struct hid_report_enum *re;
+
+	if (td->inputmode < 0)
+		return;
+
+	re = &(hdev->report_enum[HID_FEATURE_REPORT]);
+	r = re->report_id_hash[td->inputmode];
+	if (r) {
+		r->field[0]->value[0] = 0x02;
+		usbhid_submit_report(hdev, r, USB_DIR_OUT);
+	}
+}
+
+static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+	struct mt_device *td;
+	struct mt_class *mtclass = mt_classes + id->driver_data;
+
+	/* This allows the driver to correctly support devices
+	 * that emit events over several HID messages.
+	 */
+	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
+
+	td = kzalloc(sizeof(struct mt_device) +
+				mtclass->maxcontacts * sizeof(struct mt_slot),
+				GFP_KERNEL);
+	if (!td) {
+		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
+		return -ENOMEM;
+	}
+	td->mtclass = mtclass;
+	td->inputmode = -1;
+	hid_set_drvdata(hdev, td);
+
+	ret = hid_parse(hdev);
+	if (ret != 0)
+		goto fail;
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret != 0)
+		goto fail;
+
+	mt_set_input_mode(hdev);
+
+	return 0;
+
+fail:
+	kfree(td);
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int mt_reset_resume(struct hid_device *hdev)
+{
+	mt_set_input_mode(hdev);
+	return 0;
+}
+#endif
+
+static void mt_remove(struct hid_device *hdev)
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	hid_hw_stop(hdev);
+	kfree(td);
+	hid_set_drvdata(hdev, NULL);
+}
+
+static const struct hid_device_id mt_devices[] = {
+
+	/* PixCir-based panels */
+	{ .driver_data = MT_CLS_DUAL1,
+		HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
+			USB_DEVICE_ID_HANVON_MULTITOUCH) },
+	{ .driver_data = MT_CLS_DUAL1,
+		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
+
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, mt_devices);
+
+static const struct hid_usage_id mt_grabbed_usages[] = {
+	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
+	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+};
+
+static struct hid_driver mt_driver = {
+	.name = "hid-multitouch",
+	.id_table = mt_devices,
+	.probe = mt_probe,
+	.remove = mt_remove,
+	.input_mapping = mt_input_mapping,
+	.input_mapped = mt_input_mapped,
+	.feature_mapping = mt_feature_mapping,
+	.usage_table = mt_grabbed_usages,
+	.event = mt_event,
+#ifdef CONFIG_PM
+	.reset_resume = mt_reset_resume,
+#endif
+};
+
+static int __init mt_init(void)
+{
+	return hid_register_driver(&mt_driver);
+}
+
+static void __exit mt_exit(void)
+{
+	hid_unregister_driver(&mt_driver);
+}
+
+module_init(mt_init);
+module_exit(mt_exit);
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 04/10] hid-multitouch: migrated support for Cando panels
  2011-01-05 17:27 ` Benjamin Tissoires
@ 2011-01-05 17:27   ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input, linux-kernel
  Cc: Benjamin Tissoires

Migrated support for Cando dual-touch panels to the new HID multitouch driver.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/Kconfig          |    6 -
 drivers/hid/Makefile         |    1 -
 drivers/hid/hid-cando.c      |  274 ------------------------------------------
 drivers/hid/hid-core.c       |    1 +
 drivers/hid/hid-multitouch.c |   15 +++
 5 files changed, 16 insertions(+), 281 deletions(-)
 delete mode 100644 drivers/hid/hid-cando.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 6519981..faf27c0 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -94,12 +94,6 @@ config HID_BELKIN
 	---help---
 	Support for Belkin Flip KVM and Wireless keyboard.
 
-config HID_CANDO
-	tristate "Cando dual touch panel"
-	depends on USB_HID
-	---help---
-	Support for Cando dual touch panel.
-
 config HID_CHERRY
 	tristate "Cherry Cymotion keyboard" if EMBEDDED
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index ec991d4..1a0190d 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -30,7 +30,6 @@ obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
 obj-$(CONFIG_HID_ACRUX_FF)	+= hid-axff.o
 obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
 obj-$(CONFIG_HID_BELKIN)	+= hid-belkin.o
-obj-$(CONFIG_HID_CANDO)		+= hid-cando.o
 obj-$(CONFIG_HID_CHERRY)	+= hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)	+= hid-chicony.o
 obj-$(CONFIG_HID_CYPRESS)	+= hid-cypress.o
diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c
deleted file mode 100644
index 5925bdc..0000000
--- a/drivers/hid/hid-cando.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- *  HID driver for Cando dual-touch panels
- *
- *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("Cando dual-touch panel");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-struct cando_data {
-	__u16 x, y;
-	__u8 id;
-	__s8 oldest;		/* id of the oldest finger in previous frame */
-	bool valid;		/* valid finger data, or just placeholder? */
-	bool first;		/* is this the first finger in this frame? */
-	__s8 firstid;		/* id of the first finger in the frame */
-	__u16 firstx, firsty;	/* (x, y) of the first finger in the frame */
-};
-
-static int cando_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	switch (usage->hid & HID_USAGE_PAGE) {
-
-	case HID_UP_GENDESK:
-		switch (usage->hid) {
-		case HID_GD_X:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_X);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_X,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		case HID_GD_Y:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_Y);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_Y,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		}
-		return 0;
-
-	case HID_UP_DIGITIZER:
-		switch (usage->hid) {
-		case HID_DG_TIPSWITCH:
-		case HID_DG_CONTACTMAX:
-			return -1;
-		case HID_DG_INRANGE:
-			/* touchscreen emulation */
-			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-			return 1;
-		case HID_DG_CONTACTID:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TRACKING_ID);
-			return 1;
-		}
-		return 0;
-	}
-
-	return 0;
-}
-
-static int cando_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	if (usage->type == EV_KEY || usage->type == EV_ABS)
-		clear_bit(usage->code, *bit);
-
-	return 0;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void cando_filter_event(struct cando_data *td, struct input_dev *input)
-{
-	td->first = !td->first; /* touchscreen emulation */
-
-	if (!td->valid) {
-		/*
-		 * touchscreen emulation: if this is the second finger and
-		 * the first was valid, the first was the oldest; if the
-		 * first was not valid and there was a valid finger in the
-		 * previous frame, this is a release.
-		 */
-		if (td->first) {
-			td->firstid = -1;
-		} else if (td->firstid >= 0) {
-			input_event(input, EV_ABS, ABS_X, td->firstx);
-			input_event(input, EV_ABS, ABS_Y, td->firsty);
-			td->oldest = td->firstid;
-		} else if (td->oldest >= 0) {
-			input_event(input, EV_KEY, BTN_TOUCH, 0);
-			td->oldest = -1;
-		}
-
-		return;
-	}
-	
-	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
-	input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
-	input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
-
-	input_mt_sync(input);
-
-	/*
-	 * touchscreen emulation: if there was no touching finger previously,
-	 * emit touch event
-	 */
-	if (td->oldest < 0) {
-		input_event(input, EV_KEY, BTN_TOUCH, 1);
-		td->oldest = td->id;
-	}
-
-	/*
-	 * touchscreen emulation: if this is the first finger, wait for the
-	 * second; the oldest is then the second if it was the oldest already
-	 * or if there was no first, the first otherwise.
-	 */
-	if (td->first) {
-		td->firstx = td->x;
-		td->firsty = td->y;
-		td->firstid = td->id;
-	} else {
-		int x, y, oldest;
-		if (td->id == td->oldest || td->firstid < 0) {
-			x = td->x;
-			y = td->y;
-			oldest = td->id;
-		} else {
-			x = td->firstx;
-			y = td->firsty;
-			oldest = td->firstid;
-		}
-		input_event(input, EV_ABS, ABS_X, x);
-		input_event(input, EV_ABS, ABS_Y, y);
-		td->oldest = oldest;
-	}
-}
-
-
-static int cando_event(struct hid_device *hid, struct hid_field *field,
-				struct hid_usage *usage, __s32 value)
-{
-	struct cando_data *td = hid_get_drvdata(hid);
-
-	if (hid->claimed & HID_CLAIMED_INPUT) {
-		struct input_dev *input = field->hidinput->input;
-
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-			td->valid = value;
-			break;
-		case HID_DG_CONTACTID:
-			td->id = value;
-			break;
-		case HID_GD_X:
-			td->x = value;
-			break;
-		case HID_GD_Y:
-			td->y = value;
-			cando_filter_event(td, input);
-			break;
-		case HID_DG_TIPSWITCH:
-			/* avoid interference from generic hidinput handling */
-			break;
-
-		default:
-			/* fallback to the generic hidinput handling */
-			return 0;
-		}
-	}
-
-	/* we have handled the hidinput part, now remains hiddev */
-	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-		hid->hiddev_hid_event(hid, field, usage, value);
-
-	return 1;
-}
-
-static int cando_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	int ret;
-	struct cando_data *td;
-
-	td = kmalloc(sizeof(struct cando_data), GFP_KERNEL);
-	if (!td) {
-		dev_err(&hdev->dev, "cannot allocate Cando Touch data\n");
-		return -ENOMEM;
-	}
-	hid_set_drvdata(hdev, td);
-	td->first = false;
-	td->oldest = -1;
-	td->valid = false;
-
-	ret = hid_parse(hdev);
-	if (!ret)
-		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-	if (ret)
-		kfree(td);
-
-	return ret;
-}
-
-static void cando_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-	kfree(hid_get_drvdata(hdev));
-	hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id cando_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
-			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
-			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
-		USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, cando_devices);
-
-static const struct hid_usage_id cando_grabbed_usages[] = {
-	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver cando_driver = {
-	.name = "cando-touch",
-	.id_table = cando_devices,
-	.probe = cando_probe,
-	.remove = cando_remove,
-	.input_mapping = cando_input_mapping,
-	.input_mapped = cando_input_mapped,
-	.usage_table = cando_grabbed_usages,
-	.event = cando_event,
-};
-
-static int __init cando_init(void)
-{
-	return hid_register_driver(&cando_driver);
-}
-
-static void __exit cando_exit(void)
-{
-	hid_unregister_driver(&cando_driver);
-}
-
-module_init(cando_init);
-module_exit(cando_exit);
-
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 2b4d9b9..9f1ab80 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1288,6 +1288,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index aea0e32..374389e 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -64,6 +64,7 @@ struct mt_class {
 /* classes of device behavior */
 #define MT_CLS_DEFAULT 0
 #define MT_CLS_DUAL1 1
+#define MT_CLS_DUAL2 2
 
 /*
  * these device-dependent functions determine what slot corresponds
@@ -75,6 +76,11 @@ static int slot_is_contactid(struct mt_device *td)
 	return td->curdata.contactid;
 }
 
+static int slot_is_contactnumber(struct mt_device *td)
+{
+	return td->num_received;
+}
+
 static int find_slot_from_contactid(struct mt_device *td)
 {
 	int i;
@@ -93,6 +99,7 @@ static int find_slot_from_contactid(struct mt_device *td)
 struct mt_class mt_classes[] = {
 	{ find_slot_from_contactid, 10 },     /* MT_CLS_DEFAULT */
 	{ slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
+	{ slot_is_contactnumber, 2 },         /* MT_CLS_DUAL2 */
 };
 
 static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -396,6 +403,14 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 
+	/* Cando panels */
+	{ .driver_data = MT_CLS_DUAL2,
+		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
+	{ .driver_data = MT_CLS_DUAL2,
+		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
+
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mt_devices);
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 04/10] hid-multitouch: migrated support for Cando panels
@ 2011-01-05 17:27   ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input
  Cc: Benjamin Tissoires

Migrated support for Cando dual-touch panels to the new HID multitouch driver.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/Kconfig          |    6 -
 drivers/hid/Makefile         |    1 -
 drivers/hid/hid-cando.c      |  274 ------------------------------------------
 drivers/hid/hid-core.c       |    1 +
 drivers/hid/hid-multitouch.c |   15 +++
 5 files changed, 16 insertions(+), 281 deletions(-)
 delete mode 100644 drivers/hid/hid-cando.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 6519981..faf27c0 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -94,12 +94,6 @@ config HID_BELKIN
 	---help---
 	Support for Belkin Flip KVM and Wireless keyboard.
 
-config HID_CANDO
-	tristate "Cando dual touch panel"
-	depends on USB_HID
-	---help---
-	Support for Cando dual touch panel.
-
 config HID_CHERRY
 	tristate "Cherry Cymotion keyboard" if EMBEDDED
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index ec991d4..1a0190d 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -30,7 +30,6 @@ obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
 obj-$(CONFIG_HID_ACRUX_FF)	+= hid-axff.o
 obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
 obj-$(CONFIG_HID_BELKIN)	+= hid-belkin.o
-obj-$(CONFIG_HID_CANDO)		+= hid-cando.o
 obj-$(CONFIG_HID_CHERRY)	+= hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)	+= hid-chicony.o
 obj-$(CONFIG_HID_CYPRESS)	+= hid-cypress.o
diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c
deleted file mode 100644
index 5925bdc..0000000
--- a/drivers/hid/hid-cando.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- *  HID driver for Cando dual-touch panels
- *
- *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("Cando dual-touch panel");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-struct cando_data {
-	__u16 x, y;
-	__u8 id;
-	__s8 oldest;		/* id of the oldest finger in previous frame */
-	bool valid;		/* valid finger data, or just placeholder? */
-	bool first;		/* is this the first finger in this frame? */
-	__s8 firstid;		/* id of the first finger in the frame */
-	__u16 firstx, firsty;	/* (x, y) of the first finger in the frame */
-};
-
-static int cando_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	switch (usage->hid & HID_USAGE_PAGE) {
-
-	case HID_UP_GENDESK:
-		switch (usage->hid) {
-		case HID_GD_X:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_X);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_X,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		case HID_GD_Y:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_Y);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_Y,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		}
-		return 0;
-
-	case HID_UP_DIGITIZER:
-		switch (usage->hid) {
-		case HID_DG_TIPSWITCH:
-		case HID_DG_CONTACTMAX:
-			return -1;
-		case HID_DG_INRANGE:
-			/* touchscreen emulation */
-			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-			return 1;
-		case HID_DG_CONTACTID:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TRACKING_ID);
-			return 1;
-		}
-		return 0;
-	}
-
-	return 0;
-}
-
-static int cando_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	if (usage->type == EV_KEY || usage->type == EV_ABS)
-		clear_bit(usage->code, *bit);
-
-	return 0;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void cando_filter_event(struct cando_data *td, struct input_dev *input)
-{
-	td->first = !td->first; /* touchscreen emulation */
-
-	if (!td->valid) {
-		/*
-		 * touchscreen emulation: if this is the second finger and
-		 * the first was valid, the first was the oldest; if the
-		 * first was not valid and there was a valid finger in the
-		 * previous frame, this is a release.
-		 */
-		if (td->first) {
-			td->firstid = -1;
-		} else if (td->firstid >= 0) {
-			input_event(input, EV_ABS, ABS_X, td->firstx);
-			input_event(input, EV_ABS, ABS_Y, td->firsty);
-			td->oldest = td->firstid;
-		} else if (td->oldest >= 0) {
-			input_event(input, EV_KEY, BTN_TOUCH, 0);
-			td->oldest = -1;
-		}
-
-		return;
-	}
-	
-	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
-	input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
-	input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
-
-	input_mt_sync(input);
-
-	/*
-	 * touchscreen emulation: if there was no touching finger previously,
-	 * emit touch event
-	 */
-	if (td->oldest < 0) {
-		input_event(input, EV_KEY, BTN_TOUCH, 1);
-		td->oldest = td->id;
-	}
-
-	/*
-	 * touchscreen emulation: if this is the first finger, wait for the
-	 * second; the oldest is then the second if it was the oldest already
-	 * or if there was no first, the first otherwise.
-	 */
-	if (td->first) {
-		td->firstx = td->x;
-		td->firsty = td->y;
-		td->firstid = td->id;
-	} else {
-		int x, y, oldest;
-		if (td->id == td->oldest || td->firstid < 0) {
-			x = td->x;
-			y = td->y;
-			oldest = td->id;
-		} else {
-			x = td->firstx;
-			y = td->firsty;
-			oldest = td->firstid;
-		}
-		input_event(input, EV_ABS, ABS_X, x);
-		input_event(input, EV_ABS, ABS_Y, y);
-		td->oldest = oldest;
-	}
-}
-
-
-static int cando_event(struct hid_device *hid, struct hid_field *field,
-				struct hid_usage *usage, __s32 value)
-{
-	struct cando_data *td = hid_get_drvdata(hid);
-
-	if (hid->claimed & HID_CLAIMED_INPUT) {
-		struct input_dev *input = field->hidinput->input;
-
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-			td->valid = value;
-			break;
-		case HID_DG_CONTACTID:
-			td->id = value;
-			break;
-		case HID_GD_X:
-			td->x = value;
-			break;
-		case HID_GD_Y:
-			td->y = value;
-			cando_filter_event(td, input);
-			break;
-		case HID_DG_TIPSWITCH:
-			/* avoid interference from generic hidinput handling */
-			break;
-
-		default:
-			/* fallback to the generic hidinput handling */
-			return 0;
-		}
-	}
-
-	/* we have handled the hidinput part, now remains hiddev */
-	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-		hid->hiddev_hid_event(hid, field, usage, value);
-
-	return 1;
-}
-
-static int cando_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	int ret;
-	struct cando_data *td;
-
-	td = kmalloc(sizeof(struct cando_data), GFP_KERNEL);
-	if (!td) {
-		dev_err(&hdev->dev, "cannot allocate Cando Touch data\n");
-		return -ENOMEM;
-	}
-	hid_set_drvdata(hdev, td);
-	td->first = false;
-	td->oldest = -1;
-	td->valid = false;
-
-	ret = hid_parse(hdev);
-	if (!ret)
-		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-	if (ret)
-		kfree(td);
-
-	return ret;
-}
-
-static void cando_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-	kfree(hid_get_drvdata(hdev));
-	hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id cando_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
-			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
-			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
-		USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, cando_devices);
-
-static const struct hid_usage_id cando_grabbed_usages[] = {
-	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver cando_driver = {
-	.name = "cando-touch",
-	.id_table = cando_devices,
-	.probe = cando_probe,
-	.remove = cando_remove,
-	.input_mapping = cando_input_mapping,
-	.input_mapped = cando_input_mapped,
-	.usage_table = cando_grabbed_usages,
-	.event = cando_event,
-};
-
-static int __init cando_init(void)
-{
-	return hid_register_driver(&cando_driver);
-}
-
-static void __exit cando_exit(void)
-{
-	hid_unregister_driver(&cando_driver);
-}
-
-module_init(cando_init);
-module_exit(cando_exit);
-
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 2b4d9b9..9f1ab80 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1288,6 +1288,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index aea0e32..374389e 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -64,6 +64,7 @@ struct mt_class {
 /* classes of device behavior */
 #define MT_CLS_DEFAULT 0
 #define MT_CLS_DUAL1 1
+#define MT_CLS_DUAL2 2
 
 /*
  * these device-dependent functions determine what slot corresponds
@@ -75,6 +76,11 @@ static int slot_is_contactid(struct mt_device *td)
 	return td->curdata.contactid;
 }
 
+static int slot_is_contactnumber(struct mt_device *td)
+{
+	return td->num_received;
+}
+
 static int find_slot_from_contactid(struct mt_device *td)
 {
 	int i;
@@ -93,6 +99,7 @@ static int find_slot_from_contactid(struct mt_device *td)
 struct mt_class mt_classes[] = {
 	{ find_slot_from_contactid, 10 },     /* MT_CLS_DEFAULT */
 	{ slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
+	{ slot_is_contactnumber, 2 },         /* MT_CLS_DUAL2 */
 };
 
 static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -396,6 +403,14 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 
+	/* Cando panels */
+	{ .driver_data = MT_CLS_DUAL2,
+		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
+	{ .driver_data = MT_CLS_DUAL2,
+		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
+
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mt_devices);
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 05/10] hid-multitouch: Add support for Cando 10.1" panels
  2011-01-05 17:27 ` Benjamin Tissoires
@ 2011-01-05 17:27   ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input, linux-kernel
  Cc: Benjamin Tissoires, Davide Ammirata

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Davide Ammirata <webmaster@davidea.it>
---
 drivers/hid/hid-ids.h        |    1 +
 drivers/hid/hid-multitouch.c |    3 +++
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 17b444b..70dd0fd 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -136,6 +136,7 @@
 #define USB_VENDOR_ID_CANDO		0x2087
 #define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH	0x0a01
+#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1 0x0a02
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
 
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 374389e..9edbf5d 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -409,6 +409,9 @@ static const struct hid_device_id mt_devices[] = {
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
 	{ .driver_data = MT_CLS_DUAL2,
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+			USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
+	{ .driver_data = MT_CLS_DUAL2,
+		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 
 	{ }
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 05/10] hid-multitouch: Add support for Cando 10.1" panels
@ 2011-01-05 17:27   ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input
  Cc: Benjamin Tissoires, Davide Ammirata

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Davide Ammirata <webmaster@davidea.it>
---
 drivers/hid/hid-ids.h        |    1 +
 drivers/hid/hid-multitouch.c |    3 +++
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 17b444b..70dd0fd 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -136,6 +136,7 @@
 #define USB_VENDOR_ID_CANDO		0x2087
 #define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH	0x0a01
+#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1 0x0a02
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
 
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 374389e..9edbf5d 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -409,6 +409,9 @@ static const struct hid_device_id mt_devices[] = {
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
 	{ .driver_data = MT_CLS_DUAL2,
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+			USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
+	{ .driver_data = MT_CLS_DUAL2,
+		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 
 	{ }
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 06/10] hid-multitouch: added support for Cypress TrueTouch panels
  2011-01-05 17:27 ` Benjamin Tissoires
@ 2011-01-05 17:27   ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input, linux-kernel
  Cc: Benjamin Tissoires

Added support for Cypress TrueTouch panels, which detect up to 10 fingers

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/hid-core.c       |    1 +
 drivers/hid/hid-ids.h        |    1 +
 drivers/hid/hid-multitouch.c |   15 +++++++++++++++
 3 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 9f1ab80..1dcb4b0 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1299,6 +1299,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 70dd0fd..d8b0b3f 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -181,6 +181,7 @@
 #define USB_DEVICE_ID_CYPRESS_BARCODE_1	0xde61
 #define USB_DEVICE_ID_CYPRESS_BARCODE_2	0xde64
 #define USB_DEVICE_ID_CYPRESS_BARCODE_3	0xbca1
+#define USB_DEVICE_ID_CYPRESS_TRUETOUCH	0xc001
 
 #define USB_VENDOR_ID_DEALEXTREAME	0x10c5
 #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701	0x819a
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 9edbf5d..f9d537e 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -65,6 +65,7 @@ struct mt_class {
 #define MT_CLS_DEFAULT 0
 #define MT_CLS_DUAL1 1
 #define MT_CLS_DUAL2 2
+#define MT_CLS_CYPRESS 3
 
 /*
  * these device-dependent functions determine what slot corresponds
@@ -81,6 +82,14 @@ static int slot_is_contactnumber(struct mt_device *td)
 	return td->num_received;
 }
 
+static int cypress_compute_slot(struct mt_device *td)
+{
+	if (td->curdata.contactid != 0 || td->num_received == 0)
+		return td->curdata.contactid;
+	else
+		return -1;
+}
+
 static int find_slot_from_contactid(struct mt_device *td)
 {
 	int i;
@@ -100,6 +109,7 @@ struct mt_class mt_classes[] = {
 	{ find_slot_from_contactid, 10 },     /* MT_CLS_DEFAULT */
 	{ slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
 	{ slot_is_contactnumber, 2 },         /* MT_CLS_DUAL2 */
+	{ cypress_compute_slot, 10 },         /* MT_CLS_CYPRESS */
 };
 
 static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -414,6 +424,11 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 
+	/* Cypress panel */
+	{ .driver_data = MT_CLS_CYPRESS,
+		HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
+			USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
+
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mt_devices);
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 06/10] hid-multitouch: added support for Cypress TrueTouch panels
@ 2011-01-05 17:27   ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input
  Cc: Benjamin Tissoires

Added support for Cypress TrueTouch panels, which detect up to 10 fingers

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/hid-core.c       |    1 +
 drivers/hid/hid-ids.h        |    1 +
 drivers/hid/hid-multitouch.c |   15 +++++++++++++++
 3 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 9f1ab80..1dcb4b0 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1299,6 +1299,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 70dd0fd..d8b0b3f 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -181,6 +181,7 @@
 #define USB_DEVICE_ID_CYPRESS_BARCODE_1	0xde61
 #define USB_DEVICE_ID_CYPRESS_BARCODE_2	0xde64
 #define USB_DEVICE_ID_CYPRESS_BARCODE_3	0xbca1
+#define USB_DEVICE_ID_CYPRESS_TRUETOUCH	0xc001
 
 #define USB_VENDOR_ID_DEALEXTREAME	0x10c5
 #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701	0x819a
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 9edbf5d..f9d537e 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -65,6 +65,7 @@ struct mt_class {
 #define MT_CLS_DEFAULT 0
 #define MT_CLS_DUAL1 1
 #define MT_CLS_DUAL2 2
+#define MT_CLS_CYPRESS 3
 
 /*
  * these device-dependent functions determine what slot corresponds
@@ -81,6 +82,14 @@ static int slot_is_contactnumber(struct mt_device *td)
 	return td->num_received;
 }
 
+static int cypress_compute_slot(struct mt_device *td)
+{
+	if (td->curdata.contactid != 0 || td->num_received == 0)
+		return td->curdata.contactid;
+	else
+		return -1;
+}
+
 static int find_slot_from_contactid(struct mt_device *td)
 {
 	int i;
@@ -100,6 +109,7 @@ struct mt_class mt_classes[] = {
 	{ find_slot_from_contactid, 10 },     /* MT_CLS_DEFAULT */
 	{ slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
 	{ slot_is_contactnumber, 2 },         /* MT_CLS_DUAL2 */
+	{ cypress_compute_slot, 10 },         /* MT_CLS_CYPRESS */
 };
 
 static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -414,6 +424,11 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 
+	/* Cypress panel */
+	{ .driver_data = MT_CLS_CYPRESS,
+		HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
+			USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
+
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mt_devices);
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 07/10] hid-multitouch: migrated support for MosArt panels
  2011-01-05 17:27 ` Benjamin Tissoires
@ 2011-01-05 17:27   ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input, linux-kernel
  Cc: Benjamin Tissoires

Migrated support for MosArt dual-touch panels to the unified driver.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/Kconfig          |    6 -
 drivers/hid/Makefile         |    1 -
 drivers/hid/hid-mosart.c     |  275 ------------------------------------------
 drivers/hid/hid-multitouch.c |   15 +++
 4 files changed, 15 insertions(+), 282 deletions(-)
 delete mode 100644 drivers/hid/hid-mosart.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index faf27c0..74c6bf5 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -266,12 +266,6 @@ config HID_MICROSOFT
 	---help---
 	Support for Microsoft devices that are not fully compliant with HID standard.
 
-config HID_MOSART
-	tristate "MosArt dual-touch panels"
-	depends on USB_HID
-	---help---
-	Support for MosArt dual-touch panels.
-
 config HID_MONTEREY
 	tristate "Monterey Genius KB29E keyboard" if EMBEDDED
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 1a0190d..28144cb 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -44,7 +44,6 @@ obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
 obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
 obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
-obj-$(CONFIG_HID_MOSART)	+= hid-mosart.o
 obj-$(CONFIG_HID_MULTITOUCH)	+= hid-multitouch.o
 obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
 obj-$(CONFIG_HID_ORTEK)		+= hid-ortek.o
diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c
deleted file mode 100644
index ac5421d..0000000
--- a/drivers/hid/hid-mosart.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- *  HID driver for the multitouch panel on the ASUS EeePC T91MT
- *
- *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
- *  Copyright (c) 2010 Teemu Tuominen <teemu.tuominen@cybercom.com>
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include "usbhid/usbhid.h"
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("MosArt dual-touch panel");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-struct mosart_data {
-	__u16 x, y;
-	__u8 id;
-	bool valid;		/* valid finger data, or just placeholder? */
-	bool first;		/* is this the first finger in this frame? */
-	bool activity_now;	/* at least one active finger in this frame? */
-	bool activity;		/* at least one active finger previously? */
-};
-
-static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	switch (usage->hid & HID_USAGE_PAGE) {
-
-	case HID_UP_GENDESK:
-		switch (usage->hid) {
-		case HID_GD_X:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_X);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_X,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		case HID_GD_Y:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_Y);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_Y,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		}
-		return 0;
-
-	case HID_UP_DIGITIZER:
-		switch (usage->hid) {
-		case HID_DG_CONFIDENCE:
-		case HID_DG_TIPSWITCH:
-		case HID_DG_INPUTMODE:
-		case HID_DG_DEVICEINDEX:
-		case HID_DG_CONTACTCOUNT:
-		case HID_DG_CONTACTMAX:
-		case HID_DG_TIPPRESSURE:
-		case HID_DG_WIDTH:
-		case HID_DG_HEIGHT:
-			return -1;
-		case HID_DG_INRANGE:
-			/* touchscreen emulation */
-			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-			return 1;
-
-		case HID_DG_CONTACTID:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TRACKING_ID);
-			return 1;
-
-		}
-		return 0;
-
-	case 0xff000000:
-		/* ignore HID features */
-		return -1;
-	}
-
-	return 0;
-}
-
-static int mosart_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	if (usage->type == EV_KEY || usage->type == EV_ABS)
-		clear_bit(usage->code, *bit);
-
-	return 0;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void mosart_filter_event(struct mosart_data *td, struct input_dev *input)
-{
-	td->first = !td->first; /* touchscreen emulation */
-
-	if (!td->valid) {
-		/*
-		 * touchscreen emulation: if no finger in this frame is valid
-		 * and there previously was finger activity, this is a release
-		 */ 
-		if (!td->first && !td->activity_now && td->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 0);
-			td->activity = false;
-		}
-		return;
-	}
-
-	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
-	input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
-	input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
-
-	input_mt_sync(input);
-	td->valid = false;
-
-	/* touchscreen emulation: if first active finger in this frame... */
-	if (!td->activity_now) {
-		/* if there was no previous activity, emit touch event */
-		if (!td->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 1);
-			td->activity = true;
-		}
-		td->activity_now = true;
-		/* and in any case this is our preferred finger */
-		input_event(input, EV_ABS, ABS_X, td->x);
-		input_event(input, EV_ABS, ABS_Y, td->y);
-	}
-}
-
-
-static int mosart_event(struct hid_device *hid, struct hid_field *field,
-				struct hid_usage *usage, __s32 value)
-{
-	struct mosart_data *td = hid_get_drvdata(hid);
-
-	if (hid->claimed & HID_CLAIMED_INPUT) {
-		struct input_dev *input = field->hidinput->input;
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-			td->valid = !!value;
-			break;
-		case HID_GD_X:
-			td->x = value;
-			break;
-		case HID_GD_Y:
-			td->y = value;
-			mosart_filter_event(td, input);
-			break;
-		case HID_DG_CONTACTID:
-			td->id = value;
-			break;
-		case HID_DG_CONTACTCOUNT:
-			/* touch emulation: this is the last field in a frame */
-			td->first = false;
-			td->activity_now = false;
-			break;
-		case HID_DG_CONFIDENCE:
-		case HID_DG_TIPSWITCH:
-			/* avoid interference from generic hidinput handling */
-			break;
-
-		default:
-			/* fallback to the generic hidinput handling */
-			return 0;
-		}
-	}
-
-	/* we have handled the hidinput part, now remains hiddev */
-	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-		hid->hiddev_hid_event(hid, field, usage, value);
-
-	return 1;
-}
-
-static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	int ret;
-	struct mosart_data *td;
-
-
-	td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL);
-	if (!td) {
-		dev_err(&hdev->dev, "cannot allocate MosArt data\n");
-		return -ENOMEM;
-	}
-	td->valid = false;
-	td->activity = false;
-	td->activity_now = false;
-	td->first = false;
-	hid_set_drvdata(hdev, td);
-
-	/* currently, it's better to have one evdev device only */
-#if 0
-	hdev->quirks |= HID_QUIRK_MULTI_INPUT;
-#endif
-
-	ret = hid_parse(hdev);
-	if (ret == 0)
-		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-	if (ret == 0) {
-		struct hid_report_enum *re = hdev->report_enum
-						+ HID_FEATURE_REPORT;
-		struct hid_report *r = re->report_id_hash[7];
-
-		r->field[0]->value[0] = 0x02;
-		usbhid_submit_report(hdev, r, USB_DIR_OUT);
-	} else 
-		kfree(td);
-
-	return ret;
-}
-
-static void mosart_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-	kfree(hid_get_drvdata(hdev));
-	hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id mosart_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, mosart_devices);
-
-static const struct hid_usage_id mosart_grabbed_usages[] = {
-	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver mosart_driver = {
-	.name = "mosart",
-	.id_table = mosart_devices,
-	.probe = mosart_probe,
-	.remove = mosart_remove,
-	.input_mapping = mosart_input_mapping,
-	.input_mapped = mosart_input_mapped,
-	.usage_table = mosart_grabbed_usages,
-	.event = mosart_event,
-};
-
-static int __init mosart_init(void)
-{
-	return hid_register_driver(&mosart_driver);
-}
-
-static void __exit mosart_exit(void)
-{
-	hid_unregister_driver(&mosart_driver);
-}
-
-module_init(mosart_init);
-module_exit(mosart_exit);
-
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index f9d537e..d3574ab 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -66,6 +66,7 @@ struct mt_class {
 #define MT_CLS_DUAL1 1
 #define MT_CLS_DUAL2 2
 #define MT_CLS_CYPRESS 3
+#define MT_CLS_MOSART 4
 
 /*
  * these device-dependent functions determine what slot corresponds
@@ -90,6 +91,11 @@ static int cypress_compute_slot(struct mt_device *td)
 		return -1;
 }
 
+static int slot_is_contactid_minus_one(struct mt_device *td)
+{
+	return td->curdata.contactid - 1;
+}
+
 static int find_slot_from_contactid(struct mt_device *td)
 {
 	int i;
@@ -110,6 +116,7 @@ struct mt_class mt_classes[] = {
 	{ slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
 	{ slot_is_contactnumber, 2 },         /* MT_CLS_DUAL2 */
 	{ cypress_compute_slot, 10 },         /* MT_CLS_CYPRESS */
+	{ slot_is_contactid_minus_one, 2 },   /* MT_CLS_MOSART */
 };
 
 static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -429,6 +436,14 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
 			USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
 
+	/* MosArt panels */
+	{ .driver_data = MT_CLS_MOSART,
+		HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
+			USB_DEVICE_ID_ASUS_T91MT)},
+	{ .driver_data = MT_CLS_MOSART,
+		HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
+			USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
+
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mt_devices);
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 07/10] hid-multitouch: migrated support for MosArt panels
@ 2011-01-05 17:27   ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input
  Cc: Benjamin Tissoires

Migrated support for MosArt dual-touch panels to the unified driver.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/Kconfig          |    6 -
 drivers/hid/Makefile         |    1 -
 drivers/hid/hid-mosart.c     |  275 ------------------------------------------
 drivers/hid/hid-multitouch.c |   15 +++
 4 files changed, 15 insertions(+), 282 deletions(-)
 delete mode 100644 drivers/hid/hid-mosart.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index faf27c0..74c6bf5 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -266,12 +266,6 @@ config HID_MICROSOFT
 	---help---
 	Support for Microsoft devices that are not fully compliant with HID standard.
 
-config HID_MOSART
-	tristate "MosArt dual-touch panels"
-	depends on USB_HID
-	---help---
-	Support for MosArt dual-touch panels.
-
 config HID_MONTEREY
 	tristate "Monterey Genius KB29E keyboard" if EMBEDDED
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 1a0190d..28144cb 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -44,7 +44,6 @@ obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
 obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
 obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
-obj-$(CONFIG_HID_MOSART)	+= hid-mosart.o
 obj-$(CONFIG_HID_MULTITOUCH)	+= hid-multitouch.o
 obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
 obj-$(CONFIG_HID_ORTEK)		+= hid-ortek.o
diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c
deleted file mode 100644
index ac5421d..0000000
--- a/drivers/hid/hid-mosart.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- *  HID driver for the multitouch panel on the ASUS EeePC T91MT
- *
- *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
- *  Copyright (c) 2010 Teemu Tuominen <teemu.tuominen@cybercom.com>
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include "usbhid/usbhid.h"
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("MosArt dual-touch panel");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-struct mosart_data {
-	__u16 x, y;
-	__u8 id;
-	bool valid;		/* valid finger data, or just placeholder? */
-	bool first;		/* is this the first finger in this frame? */
-	bool activity_now;	/* at least one active finger in this frame? */
-	bool activity;		/* at least one active finger previously? */
-};
-
-static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	switch (usage->hid & HID_USAGE_PAGE) {
-
-	case HID_UP_GENDESK:
-		switch (usage->hid) {
-		case HID_GD_X:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_X);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_X,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		case HID_GD_Y:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_Y);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_Y,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		}
-		return 0;
-
-	case HID_UP_DIGITIZER:
-		switch (usage->hid) {
-		case HID_DG_CONFIDENCE:
-		case HID_DG_TIPSWITCH:
-		case HID_DG_INPUTMODE:
-		case HID_DG_DEVICEINDEX:
-		case HID_DG_CONTACTCOUNT:
-		case HID_DG_CONTACTMAX:
-		case HID_DG_TIPPRESSURE:
-		case HID_DG_WIDTH:
-		case HID_DG_HEIGHT:
-			return -1;
-		case HID_DG_INRANGE:
-			/* touchscreen emulation */
-			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-			return 1;
-
-		case HID_DG_CONTACTID:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TRACKING_ID);
-			return 1;
-
-		}
-		return 0;
-
-	case 0xff000000:
-		/* ignore HID features */
-		return -1;
-	}
-
-	return 0;
-}
-
-static int mosart_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	if (usage->type == EV_KEY || usage->type == EV_ABS)
-		clear_bit(usage->code, *bit);
-
-	return 0;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void mosart_filter_event(struct mosart_data *td, struct input_dev *input)
-{
-	td->first = !td->first; /* touchscreen emulation */
-
-	if (!td->valid) {
-		/*
-		 * touchscreen emulation: if no finger in this frame is valid
-		 * and there previously was finger activity, this is a release
-		 */ 
-		if (!td->first && !td->activity_now && td->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 0);
-			td->activity = false;
-		}
-		return;
-	}
-
-	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
-	input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
-	input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
-
-	input_mt_sync(input);
-	td->valid = false;
-
-	/* touchscreen emulation: if first active finger in this frame... */
-	if (!td->activity_now) {
-		/* if there was no previous activity, emit touch event */
-		if (!td->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 1);
-			td->activity = true;
-		}
-		td->activity_now = true;
-		/* and in any case this is our preferred finger */
-		input_event(input, EV_ABS, ABS_X, td->x);
-		input_event(input, EV_ABS, ABS_Y, td->y);
-	}
-}
-
-
-static int mosart_event(struct hid_device *hid, struct hid_field *field,
-				struct hid_usage *usage, __s32 value)
-{
-	struct mosart_data *td = hid_get_drvdata(hid);
-
-	if (hid->claimed & HID_CLAIMED_INPUT) {
-		struct input_dev *input = field->hidinput->input;
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-			td->valid = !!value;
-			break;
-		case HID_GD_X:
-			td->x = value;
-			break;
-		case HID_GD_Y:
-			td->y = value;
-			mosart_filter_event(td, input);
-			break;
-		case HID_DG_CONTACTID:
-			td->id = value;
-			break;
-		case HID_DG_CONTACTCOUNT:
-			/* touch emulation: this is the last field in a frame */
-			td->first = false;
-			td->activity_now = false;
-			break;
-		case HID_DG_CONFIDENCE:
-		case HID_DG_TIPSWITCH:
-			/* avoid interference from generic hidinput handling */
-			break;
-
-		default:
-			/* fallback to the generic hidinput handling */
-			return 0;
-		}
-	}
-
-	/* we have handled the hidinput part, now remains hiddev */
-	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-		hid->hiddev_hid_event(hid, field, usage, value);
-
-	return 1;
-}
-
-static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	int ret;
-	struct mosart_data *td;
-
-
-	td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL);
-	if (!td) {
-		dev_err(&hdev->dev, "cannot allocate MosArt data\n");
-		return -ENOMEM;
-	}
-	td->valid = false;
-	td->activity = false;
-	td->activity_now = false;
-	td->first = false;
-	hid_set_drvdata(hdev, td);
-
-	/* currently, it's better to have one evdev device only */
-#if 0
-	hdev->quirks |= HID_QUIRK_MULTI_INPUT;
-#endif
-
-	ret = hid_parse(hdev);
-	if (ret == 0)
-		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-	if (ret == 0) {
-		struct hid_report_enum *re = hdev->report_enum
-						+ HID_FEATURE_REPORT;
-		struct hid_report *r = re->report_id_hash[7];
-
-		r->field[0]->value[0] = 0x02;
-		usbhid_submit_report(hdev, r, USB_DIR_OUT);
-	} else 
-		kfree(td);
-
-	return ret;
-}
-
-static void mosart_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-	kfree(hid_get_drvdata(hdev));
-	hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id mosart_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, mosart_devices);
-
-static const struct hid_usage_id mosart_grabbed_usages[] = {
-	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver mosart_driver = {
-	.name = "mosart",
-	.id_table = mosart_devices,
-	.probe = mosart_probe,
-	.remove = mosart_remove,
-	.input_mapping = mosart_input_mapping,
-	.input_mapped = mosart_input_mapped,
-	.usage_table = mosart_grabbed_usages,
-	.event = mosart_event,
-};
-
-static int __init mosart_init(void)
-{
-	return hid_register_driver(&mosart_driver);
-}
-
-static void __exit mosart_exit(void)
-{
-	hid_unregister_driver(&mosart_driver);
-}
-
-module_init(mosart_init);
-module_exit(mosart_exit);
-
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index f9d537e..d3574ab 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -66,6 +66,7 @@ struct mt_class {
 #define MT_CLS_DUAL1 1
 #define MT_CLS_DUAL2 2
 #define MT_CLS_CYPRESS 3
+#define MT_CLS_MOSART 4
 
 /*
  * these device-dependent functions determine what slot corresponds
@@ -90,6 +91,11 @@ static int cypress_compute_slot(struct mt_device *td)
 		return -1;
 }
 
+static int slot_is_contactid_minus_one(struct mt_device *td)
+{
+	return td->curdata.contactid - 1;
+}
+
 static int find_slot_from_contactid(struct mt_device *td)
 {
 	int i;
@@ -110,6 +116,7 @@ struct mt_class mt_classes[] = {
 	{ slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
 	{ slot_is_contactnumber, 2 },         /* MT_CLS_DUAL2 */
 	{ cypress_compute_slot, 10 },         /* MT_CLS_CYPRESS */
+	{ slot_is_contactid_minus_one, 2 },   /* MT_CLS_MOSART */
 };
 
 static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -429,6 +436,14 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
 			USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
 
+	/* MosArt panels */
+	{ .driver_data = MT_CLS_MOSART,
+		HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
+			USB_DEVICE_ID_ASUS_T91MT)},
+	{ .driver_data = MT_CLS_MOSART,
+		HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
+			USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
+
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mt_devices);
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 08/10] hid-multitouch: migrated support for Quanta dual-touch panels
  2011-01-05 17:27 ` Benjamin Tissoires
@ 2011-01-05 17:27   ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input, linux-kernel
  Cc: Benjamin Tissoires

Migrated support for Quanta dual-touch panels to the unified driver.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/Kconfig          |    6 -
 drivers/hid/Makefile         |    1 -
 drivers/hid/hid-multitouch.c |    8 ++
 drivers/hid/hid-quanta.c     |  261 ------------------------------------------
 4 files changed, 8 insertions(+), 268 deletions(-)
 delete mode 100644 drivers/hid/hid-quanta.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 74c6bf5..989444f 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -370,12 +370,6 @@ config HID_PICOLCD_LEDS
 	---help---
 	  Provide access to PicoLCD's GPO pins via leds class.
 
-config HID_QUANTA
-	tristate "Quanta Optical Touch panels"
-	depends on USB_HID
-	---help---
-	Support for Quanta Optical Touch dual-touch panels.
-
 config HID_ROCCAT
 	tristate "Roccat special event support"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 28144cb..f8b4d95 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -48,7 +48,6 @@ obj-$(CONFIG_HID_MULTITOUCH)	+= hid-multitouch.o
 obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
 obj-$(CONFIG_HID_ORTEK)		+= hid-ortek.o
 obj-$(CONFIG_HID_PRODIKEYS)	+= hid-prodikeys.o
-obj-$(CONFIG_HID_QUANTA)	+= hid-quanta.o
 obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index d3574ab..f5fa2c6 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -420,6 +420,14 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 
+	/* Quanta panels */
+	{ .driver_data = MT_CLS_DUAL1,
+		HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
+			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
+	{ .driver_data = MT_CLS_DUAL1,
+		HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
+			USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
+
 	/* Cando panels */
 	{ .driver_data = MT_CLS_DUAL2,
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
diff --git a/drivers/hid/hid-quanta.c b/drivers/hid/hid-quanta.c
deleted file mode 100644
index 54d3db5..0000000
--- a/drivers/hid/hid-quanta.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- *  HID driver for Quanta Optical Touch dual-touch panels
- *
- *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("Quanta dual-touch panel");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-struct quanta_data {
-	__u16 x, y;
-	__u8 id;
-	bool valid;		/* valid finger data, or just placeholder? */
-	bool first;		/* is this the first finger in this frame? */
-	bool activity_now;	/* at least one active finger in this frame? */
-	bool activity;		/* at least one active finger previously? */
-};
-
-static int quanta_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	switch (usage->hid & HID_USAGE_PAGE) {
-
-	case HID_UP_GENDESK:
-		switch (usage->hid) {
-		case HID_GD_X:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_X);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_X,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		case HID_GD_Y:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_Y);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_Y,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		}
-		return 0;
-
-	case HID_UP_DIGITIZER:
-		switch (usage->hid) {
-		case HID_DG_CONFIDENCE:
-		case HID_DG_TIPSWITCH:
-		case HID_DG_INPUTMODE:
-		case HID_DG_DEVICEINDEX:
-		case HID_DG_CONTACTCOUNT:
-		case HID_DG_CONTACTMAX:
-		case HID_DG_TIPPRESSURE:
-		case HID_DG_WIDTH:
-		case HID_DG_HEIGHT:
-			return -1;
-		case HID_DG_INRANGE:
-			/* touchscreen emulation */
-			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-			return 1;
-		case HID_DG_CONTACTID:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TRACKING_ID);
-			return 1;
-		}
-		return 0;
-
-	case 0xff000000:
-		/* ignore vendor-specific features */
-		return -1;
-	}
-
-	return 0;
-}
-
-static int quanta_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	if (usage->type == EV_KEY || usage->type == EV_ABS)
-		clear_bit(usage->code, *bit);
-
-	return 0;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void quanta_filter_event(struct quanta_data *td, struct input_dev *input)
-{
-	
-	td->first = !td->first; /* touchscreen emulation */
-
-	if (!td->valid) {
-		/*
-		 * touchscreen emulation: if no finger in this frame is valid
-		 * and there previously was finger activity, this is a release
-		 */ 
-		if (!td->first && !td->activity_now && td->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 0);
-			td->activity = false;
-		}
-		return;
-	}
-
-	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
-	input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
-	input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
-
-	input_mt_sync(input);
-	td->valid = false;
-
-	/* touchscreen emulation: if first active finger in this frame... */
-	if (!td->activity_now) {
-		/* if there was no previous activity, emit touch event */
-		if (!td->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 1);
-			td->activity = true;
-		}
-		td->activity_now = true;
-		/* and in any case this is our preferred finger */
-		input_event(input, EV_ABS, ABS_X, td->x);
-		input_event(input, EV_ABS, ABS_Y, td->y);
-	}
-}
-
-
-static int quanta_event(struct hid_device *hid, struct hid_field *field,
-				struct hid_usage *usage, __s32 value)
-{
-	struct quanta_data *td = hid_get_drvdata(hid);
-
-	if (hid->claimed & HID_CLAIMED_INPUT) {
-		struct input_dev *input = field->hidinput->input;
-
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-			td->valid = !!value;
-			break;
-		case HID_GD_X:
-			td->x = value;
-			break;
-		case HID_GD_Y:
-			td->y = value;
-			quanta_filter_event(td, input);
-			break;
-		case HID_DG_CONTACTID:
-			td->id = value;
-			break;
-		case HID_DG_CONTACTCOUNT:
-			/* touch emulation: this is the last field in a frame */
-			td->first = false;
-			td->activity_now = false;
-			break;
-		case HID_DG_CONFIDENCE:
-		case HID_DG_TIPSWITCH:
-			/* avoid interference from generic hidinput handling */
-			break;
-
-		default:
-			/* fallback to the generic hidinput handling */
-			return 0;
-		}
-	}
-
-	/* we have handled the hidinput part, now remains hiddev */
-	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-		hid->hiddev_hid_event(hid, field, usage, value);
-
-	return 1;
-}
-
-static int quanta_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	int ret;
-	struct quanta_data *td;
-
-	td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL);
-	if (!td) {
-		dev_err(&hdev->dev, "cannot allocate Quanta Touch data\n");
-		return -ENOMEM;
-	}
-	td->valid = false;
-	td->activity = false;
-	td->activity_now = false;
-	td->first = false;
-	hid_set_drvdata(hdev, td);
-
-	ret = hid_parse(hdev);
-	if (!ret)
-		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-	if (ret)
-		kfree(td);
-
-	return ret;
-}
-
-static void quanta_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-	kfree(hid_get_drvdata(hdev));
-	hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id quanta_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
-			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
-			USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, quanta_devices);
-
-static const struct hid_usage_id quanta_grabbed_usages[] = {
-	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver quanta_driver = {
-	.name = "quanta-touch",
-	.id_table = quanta_devices,
-	.probe = quanta_probe,
-	.remove = quanta_remove,
-	.input_mapping = quanta_input_mapping,
-	.input_mapped = quanta_input_mapped,
-	.usage_table = quanta_grabbed_usages,
-	.event = quanta_event,
-};
-
-static int __init quanta_init(void)
-{
-	return hid_register_driver(&quanta_driver);
-}
-
-static void __exit quanta_exit(void)
-{
-	hid_unregister_driver(&quanta_driver);
-}
-
-module_init(quanta_init);
-module_exit(quanta_exit);
-
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 08/10] hid-multitouch: migrated support for Quanta dual-touch panels
@ 2011-01-05 17:27   ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input
  Cc: Benjamin Tissoires

Migrated support for Quanta dual-touch panels to the unified driver.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/Kconfig          |    6 -
 drivers/hid/Makefile         |    1 -
 drivers/hid/hid-multitouch.c |    8 ++
 drivers/hid/hid-quanta.c     |  261 ------------------------------------------
 4 files changed, 8 insertions(+), 268 deletions(-)
 delete mode 100644 drivers/hid/hid-quanta.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 74c6bf5..989444f 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -370,12 +370,6 @@ config HID_PICOLCD_LEDS
 	---help---
 	  Provide access to PicoLCD's GPO pins via leds class.
 
-config HID_QUANTA
-	tristate "Quanta Optical Touch panels"
-	depends on USB_HID
-	---help---
-	Support for Quanta Optical Touch dual-touch panels.
-
 config HID_ROCCAT
 	tristate "Roccat special event support"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 28144cb..f8b4d95 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -48,7 +48,6 @@ obj-$(CONFIG_HID_MULTITOUCH)	+= hid-multitouch.o
 obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
 obj-$(CONFIG_HID_ORTEK)		+= hid-ortek.o
 obj-$(CONFIG_HID_PRODIKEYS)	+= hid-prodikeys.o
-obj-$(CONFIG_HID_QUANTA)	+= hid-quanta.o
 obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index d3574ab..f5fa2c6 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -420,6 +420,14 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 
+	/* Quanta panels */
+	{ .driver_data = MT_CLS_DUAL1,
+		HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
+			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
+	{ .driver_data = MT_CLS_DUAL1,
+		HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
+			USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
+
 	/* Cando panels */
 	{ .driver_data = MT_CLS_DUAL2,
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
diff --git a/drivers/hid/hid-quanta.c b/drivers/hid/hid-quanta.c
deleted file mode 100644
index 54d3db5..0000000
--- a/drivers/hid/hid-quanta.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- *  HID driver for Quanta Optical Touch dual-touch panels
- *
- *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("Quanta dual-touch panel");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-struct quanta_data {
-	__u16 x, y;
-	__u8 id;
-	bool valid;		/* valid finger data, or just placeholder? */
-	bool first;		/* is this the first finger in this frame? */
-	bool activity_now;	/* at least one active finger in this frame? */
-	bool activity;		/* at least one active finger previously? */
-};
-
-static int quanta_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	switch (usage->hid & HID_USAGE_PAGE) {
-
-	case HID_UP_GENDESK:
-		switch (usage->hid) {
-		case HID_GD_X:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_X);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_X,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		case HID_GD_Y:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_Y);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_Y,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		}
-		return 0;
-
-	case HID_UP_DIGITIZER:
-		switch (usage->hid) {
-		case HID_DG_CONFIDENCE:
-		case HID_DG_TIPSWITCH:
-		case HID_DG_INPUTMODE:
-		case HID_DG_DEVICEINDEX:
-		case HID_DG_CONTACTCOUNT:
-		case HID_DG_CONTACTMAX:
-		case HID_DG_TIPPRESSURE:
-		case HID_DG_WIDTH:
-		case HID_DG_HEIGHT:
-			return -1;
-		case HID_DG_INRANGE:
-			/* touchscreen emulation */
-			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-			return 1;
-		case HID_DG_CONTACTID:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TRACKING_ID);
-			return 1;
-		}
-		return 0;
-
-	case 0xff000000:
-		/* ignore vendor-specific features */
-		return -1;
-	}
-
-	return 0;
-}
-
-static int quanta_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	if (usage->type == EV_KEY || usage->type == EV_ABS)
-		clear_bit(usage->code, *bit);
-
-	return 0;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void quanta_filter_event(struct quanta_data *td, struct input_dev *input)
-{
-	
-	td->first = !td->first; /* touchscreen emulation */
-
-	if (!td->valid) {
-		/*
-		 * touchscreen emulation: if no finger in this frame is valid
-		 * and there previously was finger activity, this is a release
-		 */ 
-		if (!td->first && !td->activity_now && td->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 0);
-			td->activity = false;
-		}
-		return;
-	}
-
-	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
-	input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
-	input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
-
-	input_mt_sync(input);
-	td->valid = false;
-
-	/* touchscreen emulation: if first active finger in this frame... */
-	if (!td->activity_now) {
-		/* if there was no previous activity, emit touch event */
-		if (!td->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 1);
-			td->activity = true;
-		}
-		td->activity_now = true;
-		/* and in any case this is our preferred finger */
-		input_event(input, EV_ABS, ABS_X, td->x);
-		input_event(input, EV_ABS, ABS_Y, td->y);
-	}
-}
-
-
-static int quanta_event(struct hid_device *hid, struct hid_field *field,
-				struct hid_usage *usage, __s32 value)
-{
-	struct quanta_data *td = hid_get_drvdata(hid);
-
-	if (hid->claimed & HID_CLAIMED_INPUT) {
-		struct input_dev *input = field->hidinput->input;
-
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-			td->valid = !!value;
-			break;
-		case HID_GD_X:
-			td->x = value;
-			break;
-		case HID_GD_Y:
-			td->y = value;
-			quanta_filter_event(td, input);
-			break;
-		case HID_DG_CONTACTID:
-			td->id = value;
-			break;
-		case HID_DG_CONTACTCOUNT:
-			/* touch emulation: this is the last field in a frame */
-			td->first = false;
-			td->activity_now = false;
-			break;
-		case HID_DG_CONFIDENCE:
-		case HID_DG_TIPSWITCH:
-			/* avoid interference from generic hidinput handling */
-			break;
-
-		default:
-			/* fallback to the generic hidinput handling */
-			return 0;
-		}
-	}
-
-	/* we have handled the hidinput part, now remains hiddev */
-	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-		hid->hiddev_hid_event(hid, field, usage, value);
-
-	return 1;
-}
-
-static int quanta_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	int ret;
-	struct quanta_data *td;
-
-	td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL);
-	if (!td) {
-		dev_err(&hdev->dev, "cannot allocate Quanta Touch data\n");
-		return -ENOMEM;
-	}
-	td->valid = false;
-	td->activity = false;
-	td->activity_now = false;
-	td->first = false;
-	hid_set_drvdata(hdev, td);
-
-	ret = hid_parse(hdev);
-	if (!ret)
-		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-	if (ret)
-		kfree(td);
-
-	return ret;
-}
-
-static void quanta_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-	kfree(hid_get_drvdata(hdev));
-	hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id quanta_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
-			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
-			USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, quanta_devices);
-
-static const struct hid_usage_id quanta_grabbed_usages[] = {
-	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver quanta_driver = {
-	.name = "quanta-touch",
-	.id_table = quanta_devices,
-	.probe = quanta_probe,
-	.remove = quanta_remove,
-	.input_mapping = quanta_input_mapping,
-	.input_mapped = quanta_input_mapped,
-	.usage_table = quanta_grabbed_usages,
-	.event = quanta_event,
-};
-
-static int __init quanta_init(void)
-{
-	return hid_register_driver(&quanta_driver);
-}
-
-static void __exit quanta_exit(void)
-{
-	hid_unregister_driver(&quanta_driver);
-}
-
-module_init(quanta_init);
-module_exit(quanta_exit);
-
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 09/10] hid-mulitouch: added support for the 'Sensing Win7-TwoFinger'
  2011-01-05 17:27 ` Benjamin Tissoires
@ 2011-01-05 17:27   ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input, linux-kernel
  Cc: Benjamin Tissoires

Added support for the 'Sensing Win7-TwoFinger' panel by GeneralTouch found on some tablets.

Because of conflicting VID/PID, this conflicts with previous support for some single-touch panels by GeneralTouch

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/hid-core.c       |    2 +-
 drivers/hid/hid-ids.h        |    1 +
 drivers/hid/hid-multitouch.c |    5 +++++
 3 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 1dcb4b0..addaaf5 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1310,6 +1310,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
@@ -1613,7 +1614,6 @@ static const struct hid_device_id hid_ignore_list[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index d8b0b3f..5cdbdb4 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -227,6 +227,7 @@
 #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR	0x0002
 
 #define USB_VENDOR_ID_GENERAL_TOUCH	0x0dfc
+#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001
 
 #define USB_VENDOR_ID_GLAB		0x06c2
 #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index f5fa2c6..deb996d 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -439,6 +439,11 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 
+	/* GeneralTouch panel */
+	{ .driver_data = MT_CLS_DUAL2,
+		HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
+			USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
+
 	/* Cypress panel */
 	{ .driver_data = MT_CLS_CYPRESS,
 		HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 09/10] hid-mulitouch: added support for the 'Sensing Win7-TwoFinger'
@ 2011-01-05 17:27   ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input
  Cc: Benjamin Tissoires

Added support for the 'Sensing Win7-TwoFinger' panel by GeneralTouch found on some tablets.

Because of conflicting VID/PID, this conflicts with previous support for some single-touch panels by GeneralTouch

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/hid-core.c       |    2 +-
 drivers/hid/hid-ids.h        |    1 +
 drivers/hid/hid-multitouch.c |    5 +++++
 3 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 1dcb4b0..addaaf5 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1310,6 +1310,7 @@ static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
@@ -1613,7 +1614,6 @@ static const struct hid_device_id hid_ignore_list[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index d8b0b3f..5cdbdb4 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -227,6 +227,7 @@
 #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR	0x0002
 
 #define USB_VENDOR_ID_GENERAL_TOUCH	0x0dfc
+#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001
 
 #define USB_VENDOR_ID_GLAB		0x06c2
 #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index f5fa2c6..deb996d 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -439,6 +439,11 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 
+	/* GeneralTouch panel */
+	{ .driver_data = MT_CLS_DUAL2,
+		HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
+			USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
+
 	/* Cypress panel */
 	{ .driver_data = MT_CLS_CYPRESS,
 		HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 10/10] hid-multitouch: migrated support for Stantum panels
  2011-01-05 17:27 ` Benjamin Tissoires
@ 2011-01-05 17:27   ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input, linux-kernel
  Cc: Benjamin Tissoires

Migrated support for Stantum panels to the unified driver.
(Requires patch named "hid: set HID_MAX_FIELDS at 128")

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/Kconfig          |    6 -
 drivers/hid/Makefile         |    1 -
 drivers/hid/hid-multitouch.c |   35 +++++-
 drivers/hid/hid-stantum.c    |  286 ------------------------------------------
 4 files changed, 33 insertions(+), 295 deletions(-)
 delete mode 100644 drivers/hid/hid-stantum.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 989444f..8024a28 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -404,12 +404,6 @@ config HID_SONY
 	---help---
 	Support for Sony PS3 controller.
 
-config HID_STANTUM
-	tristate "Stantum multitouch panel"
-	depends on USB_HID
-	---help---
-	Support for Stantum multitouch panel.
-
 config HID_SUNPLUS
 	tristate "Sunplus wireless desktop"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index f8b4d95..f0484f5 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -57,7 +57,6 @@ obj-$(CONFIG_HID_ROCCAT_PYRA)	+= hid-roccat-pyra.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
 obj-$(CONFIG_HID_SONY)		+= hid-sony.o
-obj-$(CONFIG_HID_STANTUM)	+= hid-stantum.o
 obj-$(CONFIG_HID_SUNPLUS)	+= hid-sunplus.o
 obj-$(CONFIG_HID_GREENASIA)	+= hid-gaff.o
 obj-$(CONFIG_HID_THRUSTMASTER)	+= hid-tmff.o
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index deb996d..dc74d04 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -31,7 +31,7 @@ MODULE_LICENSE("GPL");
 
 
 struct mt_slot {
-	__s32 x, y, p;
+	__s32 x, y, p, w, h;
 	__s32 contactid;	/* the device ContactID assigned to this slot */
 	__u16 trkid;	/* the tracking ID that was assigned to this slot */
 	bool valid;	/* did we just get valid contact data for this slot? */
@@ -39,7 +39,7 @@ struct mt_slot {
 };
 
 struct mt_buffer {
-	__s32 x, y, p;
+	__s32 x, y, p, w, h;
 	__s32 contactid;	/* the device ContactID assigned to this slot */
 };
 
@@ -181,6 +181,18 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 						td->mtclass->maxcontacts);
 			td->last_slot_field = usage->hid;
 			return 1;
+		case HID_DG_WIDTH:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MAJOR);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_HEIGHT:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MINOR);
+			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
+					1, 1, 0, 0);
+			td->last_slot_field = usage->hid;
+			return 1;
 		case HID_DG_TIPPRESSURE:
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_PRESSURE);
@@ -266,6 +278,8 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
 		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_PRESSURE, s->p);
+		input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w);
+		input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h);
 		s->prev_valid = true;
 		s->valid = false;
 
@@ -304,6 +318,12 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
 		case HID_GD_Y:
 			td->curdata.y = value;
 			break;
+		case HID_DG_WIDTH:
+			td->curdata.w = value;
+			break;
+		case HID_DG_HEIGHT:
+			td->curdata.h = value;
+			break;
 		case HID_DG_CONTACTCOUNT:
 			/*
 			 * We must not overwrite the previous value (some
@@ -457,6 +477,17 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
 			USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
 
+	/* Stantum panels */
+	{ .driver_data = MT_CLS_DEFAULT,
+		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+			USB_DEVICE_ID_MTP)},
+	{ .driver_data = MT_CLS_DEFAULT,
+		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+			USB_DEVICE_ID_MTP_STM)},
+	{ .driver_data = MT_CLS_DEFAULT,
+		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+			USB_DEVICE_ID_MTP_SITRONIX)},
+
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mt_devices);
diff --git a/drivers/hid/hid-stantum.c b/drivers/hid/hid-stantum.c
deleted file mode 100644
index 3171be2..0000000
--- a/drivers/hid/hid-stantum.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- *  HID driver for Stantum multitouch panels
- *
- *  Copyright (c) 2009 Stephane Chatty <chatty@enac.fr>
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("Stantum HID multitouch panels");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-struct stantum_data {
-	__s32 x, y, z, w, h;	/* x, y, pressure, width, height */
-	__u16 id;		/* touch id */
-	bool valid;		/* valid finger data, or just placeholder? */
-	bool first;		/* first finger in the HID packet? */
-	bool activity;		/* at least one active finger so far? */
-};
-
-static int stantum_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	switch (usage->hid & HID_USAGE_PAGE) {
-
-	case HID_UP_GENDESK:
-		switch (usage->hid) {
-		case HID_GD_X:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_X);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_X,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		case HID_GD_Y:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_Y);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_Y,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		}
-		return 0;
-
-	case HID_UP_DIGITIZER:
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-		case HID_DG_CONFIDENCE:
-		case HID_DG_INPUTMODE:
-		case HID_DG_DEVICEINDEX:
-		case HID_DG_CONTACTCOUNT:
-		case HID_DG_CONTACTMAX:
-			return -1;
-
-		case HID_DG_TIPSWITCH:
-			/* touchscreen emulation */
-			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-			return 1;
-
-		case HID_DG_WIDTH:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TOUCH_MAJOR);
-			return 1;
-		case HID_DG_HEIGHT:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TOUCH_MINOR);
-			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
-					1, 1, 0, 0);
-			return 1;
-		case HID_DG_TIPPRESSURE:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_PRESSURE);
-			return 1;
-
-		case HID_DG_CONTACTID:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TRACKING_ID);
-			return 1;
-
-		}
-		return 0;
-
-	case 0xff000000:
-		/* no input-oriented meaning */
-		return -1;
-	}
-
-	return 0;
-}
-
-static int stantum_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	if (usage->type == EV_KEY || usage->type == EV_ABS)
-		clear_bit(usage->code, *bit);
-
-	return 0;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void stantum_filter_event(struct stantum_data *sd,
-					struct input_dev *input)
-{
-	bool wide;
-
-	if (!sd->valid) {
-		/*
-		 * touchscreen emulation: if the first finger is not valid and
-		 * there previously was finger activity, this is a release
-		 */
-		if (sd->first && sd->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 0);
-			sd->activity = false;
-		}
-		return;
-	}
-
-	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, sd->id);
-	input_event(input, EV_ABS, ABS_MT_POSITION_X, sd->x);
-	input_event(input, EV_ABS, ABS_MT_POSITION_Y, sd->y);
-
-	wide = (sd->w > sd->h);
-	input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
-	input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, wide ? sd->w : sd->h);
-	input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, wide ? sd->h : sd->w);
-
-	input_event(input, EV_ABS, ABS_MT_PRESSURE, sd->z);
-
-	input_mt_sync(input);
-	sd->valid = false;
-
-	/* touchscreen emulation */
-	if (sd->first) {
-		if (!sd->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 1);
-			sd->activity = true;
-		}
-		input_event(input, EV_ABS, ABS_X, sd->x);
-		input_event(input, EV_ABS, ABS_Y, sd->y);
-	}
-	sd->first = false;
-}
-
-
-static int stantum_event(struct hid_device *hid, struct hid_field *field,
-				struct hid_usage *usage, __s32 value)
-{
-	struct stantum_data *sd = hid_get_drvdata(hid);
-
-	if (hid->claimed & HID_CLAIMED_INPUT) {
-		struct input_dev *input = field->hidinput->input;
-
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-			/* this is the last field in a finger */
-			stantum_filter_event(sd, input);
-			break;
-		case HID_DG_WIDTH:
-			sd->w = value;
-			break;
-		case HID_DG_HEIGHT:
-			sd->h = value;
-			break;
-		case HID_GD_X:
-			sd->x = value;
-			break;
-		case HID_GD_Y:
-			sd->y = value;
-			break;
-		case HID_DG_TIPPRESSURE:
-			sd->z = value;
-			break;
-		case HID_DG_CONTACTID:
-			sd->id = value;
-			break;
-		case HID_DG_CONFIDENCE:
-			sd->valid = !!value;
-			break;
-		case 0xff000002:
-			/* this comes only before the first finger */
-			sd->first = true;
-			break;
-
-		default:
-			/* ignore the others */
-			return 1;
-		}
-	}
-
-	/* we have handled the hidinput part, now remains hiddev */
-	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-		hid->hiddev_hid_event(hid, field, usage, value);
-
-	return 1;
-}
-
-static int stantum_probe(struct hid_device *hdev,
-				const struct hid_device_id *id)
-{
-	int ret;
-	struct stantum_data *sd;
-
-	sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL);
-	if (!sd) {
-		dev_err(&hdev->dev, "cannot allocate Stantum data\n");
-		return -ENOMEM;
-	}
-	sd->valid = false;
-	sd->first = false;
-	sd->activity = false;
-	hid_set_drvdata(hdev, sd);
-
-	ret = hid_parse(hdev);
-	if (!ret)
-		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-	if (ret)
-		kfree(sd);
-
-	return ret;
-}
-
-static void stantum_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-	kfree(hid_get_drvdata(hdev));
-	hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id stantum_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, stantum_devices);
-
-static const struct hid_usage_id stantum_grabbed_usages[] = {
-	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver stantum_driver = {
-	.name = "stantum",
-	.id_table = stantum_devices,
-	.probe = stantum_probe,
-	.remove = stantum_remove,
-	.input_mapping = stantum_input_mapping,
-	.input_mapped = stantum_input_mapped,
-	.usage_table = stantum_grabbed_usages,
-	.event = stantum_event,
-};
-
-static int __init stantum_init(void)
-{
-	return hid_register_driver(&stantum_driver);
-}
-
-static void __exit stantum_exit(void)
-{
-	hid_unregister_driver(&stantum_driver);
-}
-
-module_init(stantum_init);
-module_exit(stantum_exit);
-
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [RFC v2 10/10] hid-multitouch: migrated support for Stantum panels
@ 2011-01-05 17:27   ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-05 17:27 UTC (permalink / raw)
  To: Stephane Chatty, Henrik Rydberg, Dmitry Torokhov, Jiri Kosina,
	linux-input
  Cc: Benjamin Tissoires

Migrated support for Stantum panels to the unified driver.
(Requires patch named "hid: set HID_MAX_FIELDS at 128")

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Stéphane Chatty <chatty@enac.fr>
---
 drivers/hid/Kconfig          |    6 -
 drivers/hid/Makefile         |    1 -
 drivers/hid/hid-multitouch.c |   35 +++++-
 drivers/hid/hid-stantum.c    |  286 ------------------------------------------
 4 files changed, 33 insertions(+), 295 deletions(-)
 delete mode 100644 drivers/hid/hid-stantum.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 989444f..8024a28 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -404,12 +404,6 @@ config HID_SONY
 	---help---
 	Support for Sony PS3 controller.
 
-config HID_STANTUM
-	tristate "Stantum multitouch panel"
-	depends on USB_HID
-	---help---
-	Support for Stantum multitouch panel.
-
 config HID_SUNPLUS
 	tristate "Sunplus wireless desktop"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index f8b4d95..f0484f5 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -57,7 +57,6 @@ obj-$(CONFIG_HID_ROCCAT_PYRA)	+= hid-roccat-pyra.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
 obj-$(CONFIG_HID_SONY)		+= hid-sony.o
-obj-$(CONFIG_HID_STANTUM)	+= hid-stantum.o
 obj-$(CONFIG_HID_SUNPLUS)	+= hid-sunplus.o
 obj-$(CONFIG_HID_GREENASIA)	+= hid-gaff.o
 obj-$(CONFIG_HID_THRUSTMASTER)	+= hid-tmff.o
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index deb996d..dc74d04 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -31,7 +31,7 @@ MODULE_LICENSE("GPL");
 
 
 struct mt_slot {
-	__s32 x, y, p;
+	__s32 x, y, p, w, h;
 	__s32 contactid;	/* the device ContactID assigned to this slot */
 	__u16 trkid;	/* the tracking ID that was assigned to this slot */
 	bool valid;	/* did we just get valid contact data for this slot? */
@@ -39,7 +39,7 @@ struct mt_slot {
 };
 
 struct mt_buffer {
-	__s32 x, y, p;
+	__s32 x, y, p, w, h;
 	__s32 contactid;	/* the device ContactID assigned to this slot */
 };
 
@@ -181,6 +181,18 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 						td->mtclass->maxcontacts);
 			td->last_slot_field = usage->hid;
 			return 1;
+		case HID_DG_WIDTH:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MAJOR);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_HEIGHT:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MINOR);
+			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
+					1, 1, 0, 0);
+			td->last_slot_field = usage->hid;
+			return 1;
 		case HID_DG_TIPPRESSURE:
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_PRESSURE);
@@ -266,6 +278,8 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
 		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_PRESSURE, s->p);
+		input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w);
+		input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h);
 		s->prev_valid = true;
 		s->valid = false;
 
@@ -304,6 +318,12 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
 		case HID_GD_Y:
 			td->curdata.y = value;
 			break;
+		case HID_DG_WIDTH:
+			td->curdata.w = value;
+			break;
+		case HID_DG_HEIGHT:
+			td->curdata.h = value;
+			break;
 		case HID_DG_CONTACTCOUNT:
 			/*
 			 * We must not overwrite the previous value (some
@@ -457,6 +477,17 @@ static const struct hid_device_id mt_devices[] = {
 		HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
 			USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
 
+	/* Stantum panels */
+	{ .driver_data = MT_CLS_DEFAULT,
+		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+			USB_DEVICE_ID_MTP)},
+	{ .driver_data = MT_CLS_DEFAULT,
+		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+			USB_DEVICE_ID_MTP_STM)},
+	{ .driver_data = MT_CLS_DEFAULT,
+		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+			USB_DEVICE_ID_MTP_SITRONIX)},
+
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mt_devices);
diff --git a/drivers/hid/hid-stantum.c b/drivers/hid/hid-stantum.c
deleted file mode 100644
index 3171be2..0000000
--- a/drivers/hid/hid-stantum.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- *  HID driver for Stantum multitouch panels
- *
- *  Copyright (c) 2009 Stephane Chatty <chatty@enac.fr>
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("Stantum HID multitouch panels");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-struct stantum_data {
-	__s32 x, y, z, w, h;	/* x, y, pressure, width, height */
-	__u16 id;		/* touch id */
-	bool valid;		/* valid finger data, or just placeholder? */
-	bool first;		/* first finger in the HID packet? */
-	bool activity;		/* at least one active finger so far? */
-};
-
-static int stantum_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	switch (usage->hid & HID_USAGE_PAGE) {
-
-	case HID_UP_GENDESK:
-		switch (usage->hid) {
-		case HID_GD_X:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_X);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_X,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		case HID_GD_Y:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_Y);
-			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_Y,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
-			return 1;
-		}
-		return 0;
-
-	case HID_UP_DIGITIZER:
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-		case HID_DG_CONFIDENCE:
-		case HID_DG_INPUTMODE:
-		case HID_DG_DEVICEINDEX:
-		case HID_DG_CONTACTCOUNT:
-		case HID_DG_CONTACTMAX:
-			return -1;
-
-		case HID_DG_TIPSWITCH:
-			/* touchscreen emulation */
-			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-			return 1;
-
-		case HID_DG_WIDTH:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TOUCH_MAJOR);
-			return 1;
-		case HID_DG_HEIGHT:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TOUCH_MINOR);
-			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
-					1, 1, 0, 0);
-			return 1;
-		case HID_DG_TIPPRESSURE:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_PRESSURE);
-			return 1;
-
-		case HID_DG_CONTACTID:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TRACKING_ID);
-			return 1;
-
-		}
-		return 0;
-
-	case 0xff000000:
-		/* no input-oriented meaning */
-		return -1;
-	}
-
-	return 0;
-}
-
-static int stantum_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	if (usage->type == EV_KEY || usage->type == EV_ABS)
-		clear_bit(usage->code, *bit);
-
-	return 0;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void stantum_filter_event(struct stantum_data *sd,
-					struct input_dev *input)
-{
-	bool wide;
-
-	if (!sd->valid) {
-		/*
-		 * touchscreen emulation: if the first finger is not valid and
-		 * there previously was finger activity, this is a release
-		 */
-		if (sd->first && sd->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 0);
-			sd->activity = false;
-		}
-		return;
-	}
-
-	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, sd->id);
-	input_event(input, EV_ABS, ABS_MT_POSITION_X, sd->x);
-	input_event(input, EV_ABS, ABS_MT_POSITION_Y, sd->y);
-
-	wide = (sd->w > sd->h);
-	input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
-	input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, wide ? sd->w : sd->h);
-	input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, wide ? sd->h : sd->w);
-
-	input_event(input, EV_ABS, ABS_MT_PRESSURE, sd->z);
-
-	input_mt_sync(input);
-	sd->valid = false;
-
-	/* touchscreen emulation */
-	if (sd->first) {
-		if (!sd->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 1);
-			sd->activity = true;
-		}
-		input_event(input, EV_ABS, ABS_X, sd->x);
-		input_event(input, EV_ABS, ABS_Y, sd->y);
-	}
-	sd->first = false;
-}
-
-
-static int stantum_event(struct hid_device *hid, struct hid_field *field,
-				struct hid_usage *usage, __s32 value)
-{
-	struct stantum_data *sd = hid_get_drvdata(hid);
-
-	if (hid->claimed & HID_CLAIMED_INPUT) {
-		struct input_dev *input = field->hidinput->input;
-
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-			/* this is the last field in a finger */
-			stantum_filter_event(sd, input);
-			break;
-		case HID_DG_WIDTH:
-			sd->w = value;
-			break;
-		case HID_DG_HEIGHT:
-			sd->h = value;
-			break;
-		case HID_GD_X:
-			sd->x = value;
-			break;
-		case HID_GD_Y:
-			sd->y = value;
-			break;
-		case HID_DG_TIPPRESSURE:
-			sd->z = value;
-			break;
-		case HID_DG_CONTACTID:
-			sd->id = value;
-			break;
-		case HID_DG_CONFIDENCE:
-			sd->valid = !!value;
-			break;
-		case 0xff000002:
-			/* this comes only before the first finger */
-			sd->first = true;
-			break;
-
-		default:
-			/* ignore the others */
-			return 1;
-		}
-	}
-
-	/* we have handled the hidinput part, now remains hiddev */
-	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-		hid->hiddev_hid_event(hid, field, usage, value);
-
-	return 1;
-}
-
-static int stantum_probe(struct hid_device *hdev,
-				const struct hid_device_id *id)
-{
-	int ret;
-	struct stantum_data *sd;
-
-	sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL);
-	if (!sd) {
-		dev_err(&hdev->dev, "cannot allocate Stantum data\n");
-		return -ENOMEM;
-	}
-	sd->valid = false;
-	sd->first = false;
-	sd->activity = false;
-	hid_set_drvdata(hdev, sd);
-
-	ret = hid_parse(hdev);
-	if (!ret)
-		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-
-	if (ret)
-		kfree(sd);
-
-	return ret;
-}
-
-static void stantum_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-	kfree(hid_get_drvdata(hdev));
-	hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id stantum_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, stantum_devices);
-
-static const struct hid_usage_id stantum_grabbed_usages[] = {
-	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver stantum_driver = {
-	.name = "stantum",
-	.id_table = stantum_devices,
-	.probe = stantum_probe,
-	.remove = stantum_remove,
-	.input_mapping = stantum_input_mapping,
-	.input_mapped = stantum_input_mapped,
-	.usage_table = stantum_grabbed_usages,
-	.event = stantum_event,
-};
-
-static int __init stantum_init(void)
-{
-	return hid_register_driver(&stantum_driver);
-}
-
-static void __exit stantum_exit(void)
-{
-	hid_unregister_driver(&stantum_driver);
-}
-
-module_init(stantum_init);
-module_exit(stantum_exit);
-
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
  2011-01-05 17:27 ` Benjamin Tissoires
                   ` (10 preceding siblings ...)
  (?)
@ 2011-01-05 17:49 ` Henrik Rydberg
  2011-01-06 15:08     ` Benjamin Tissoires
  -1 siblings, 1 reply; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-05 17:49 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

Hi Benjamin,

> these patches is the set for the unified driver hid-multitouch.
> I'm putting the flag RFC as I'm still waiting some testers feedback on some devices. But I don't think they will change a lot.

This will be an interesting read, thank you very much for the patches.

> This would be great if this stuff could go into 2.6.38, if it's not too late.

The merge window just opened, which generally means the work for
2.6.38 is done. On top of that, we would expect some changes and
further testing, and limited time from everybody involved. Given that
also additional drivers should be added, which might affect the
general solution, it seems like a good idea to let this mature over
time, such that it is ready for the 2.6.39 merge window.

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
  2011-01-05 17:49 ` [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification Henrik Rydberg
@ 2011-01-06 15:08     ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-06 15:08 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

Hi Henrik,

thanks for the future review ;)

Well, patches n° 3,4,5,6 and 7 are only those sent by Stéphane and
reviewed by you 3 months ago with small changes:
  - I took into account most of your comments
  - I inserted suspend/resume support
  - I implemented a way to find out the end of a mt report.

Patch 1 (hid: add feature_mapping callback) is new but not very
dangerous I think: it only adds a hook. Thanks to it, I could retrieve
the magic number which is device-specific.

Patch 2 (hid: set HID_MAX_FIELD at 128) may need further discussions
(but is required to use Stantum panels)

the last patches only introduce support for 3 devices, 1 of them is
new for the kernel.

The point is that currently we have users that want to have a proper
support for their device (PixCir, Cypress TrueTouch and GeneralTouch),
and it's a shame to ask them to wait for 3 more months.

Maybe a solution would be to make what we can here during this merge
window to add support for at least the new devices. Then, in 2.6.39
and above, we could still migrate other devices, and eventually modify
some lines in the code.

Jiri, Dmitry, what do you think?

Cheers,
Benjamin



On Wed, Jan 5, 2011 at 6:49 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
> Hi Benjamin,
>
>> these patches is the set for the unified driver hid-multitouch.
>> I'm putting the flag RFC as I'm still waiting some testers feedback on some devices. But I don't think they will change a lot.
>
> This will be an interesting read, thank you very much for the patches.
>
>> This would be great if this stuff could go into 2.6.38, if it's not too late.
>
> The merge window just opened, which generally means the work for
> 2.6.38 is done. On top of that, we would expect some changes and
> further testing, and limited time from everybody involved.
> Given that
> also additional drivers should be added, which might affect the
> general solution, it seems like a good idea to let this mature over
> time, such that it is ready for the 2.6.39 merge window.
>
> Thanks,
> Henrik

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
@ 2011-01-06 15:08     ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-06 15:08 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

Hi Henrik,

thanks for the future review ;)

Well, patches n° 3,4,5,6 and 7 are only those sent by Stéphane and
reviewed by you 3 months ago with small changes:
  - I took into account most of your comments
  - I inserted suspend/resume support
  - I implemented a way to find out the end of a mt report.

Patch 1 (hid: add feature_mapping callback) is new but not very
dangerous I think: it only adds a hook. Thanks to it, I could retrieve
the magic number which is device-specific.

Patch 2 (hid: set HID_MAX_FIELD at 128) may need further discussions
(but is required to use Stantum panels)

the last patches only introduce support for 3 devices, 1 of them is
new for the kernel.

The point is that currently we have users that want to have a proper
support for their device (PixCir, Cypress TrueTouch and GeneralTouch),
and it's a shame to ask them to wait for 3 more months.

Maybe a solution would be to make what we can here during this merge
window to add support for at least the new devices. Then, in 2.6.39
and above, we could still migrate other devices, and eventually modify
some lines in the code.

Jiri, Dmitry, what do you think?

Cheers,
Benjamin



On Wed, Jan 5, 2011 at 6:49 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
> Hi Benjamin,
>
>> these patches is the set for the unified driver hid-multitouch.
>> I'm putting the flag RFC as I'm still waiting some testers feedback on some devices. But I don't think they will change a lot.
>
> This will be an interesting read, thank you very much for the patches.
>
>> This would be great if this stuff could go into 2.6.38, if it's not too late.
>
> The merge window just opened, which generally means the work for
> 2.6.38 is done. On top of that, we would expect some changes and
> further testing, and limited time from everybody involved.
> Given that
> also additional drivers should be added, which might affect the
> general solution, it seems like a good idea to let this mature over
> time, such that it is ready for the 2.6.39 merge window.
>
> Thanks,
> Henrik
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
  2011-01-06 15:08     ` Benjamin Tissoires
@ 2011-01-06 15:11       ` Jiri Kosina
  -1 siblings, 0 replies; 56+ messages in thread
From: Jiri Kosina @ 2011-01-06 15:11 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Henrik Rydberg, Stephane Chatty, Dmitry Torokhov, linux-input,
	linux-kernel

On Thu, 6 Jan 2011, Benjamin Tissoires wrote:

> Hi Henrik,
> 
> thanks for the future review ;)
> 
> Well, patches n° 3,4,5,6 and 7 are only those sent by Stéphane and
> reviewed by you 3 months ago with small changes:
>   - I took into account most of your comments
>   - I inserted suspend/resume support
>   - I implemented a way to find out the end of a mt report.
> 
> Patch 1 (hid: add feature_mapping callback) is new but not very
> dangerous I think: it only adds a hook. Thanks to it, I could retrieve
> the magic number which is device-specific.
> 
> Patch 2 (hid: set HID_MAX_FIELD at 128) may need further discussions
> (but is required to use Stantum panels)
> 
> the last patches only introduce support for 3 devices, 1 of them is
> new for the kernel.
> 
> The point is that currently we have users that want to have a proper
> support for their device (PixCir, Cypress TrueTouch and GeneralTouch),
> and it's a shame to ask them to wait for 3 more months.
> 
> Maybe a solution would be to make what we can here during this merge
> window to add support for at least the new devices. Then, in 2.6.39
> and above, we could still migrate other devices, and eventually modify
> some lines in the code.
> 
> Jiri, Dmitry, what do you think?

I still have to go through the patchset, my backlog has grown very badly 
recently, sorry.

In case the patchset doesn't impose danger of regressions for already 
existing devices, we could merge this new 'unified' driver only for newly 
supported devices, and finish the unification in 2.6.39.

-- 
Jiri Kosina
SUSE Labs, Novell Inc.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
@ 2011-01-06 15:11       ` Jiri Kosina
  0 siblings, 0 replies; 56+ messages in thread
From: Jiri Kosina @ 2011-01-06 15:11 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Henrik Rydberg, Stephane Chatty, Dmitry Torokhov, linux-input,
	linux-kernel

On Thu, 6 Jan 2011, Benjamin Tissoires wrote:

> Hi Henrik,
> 
> thanks for the future review ;)
> 
> Well, patches n° 3,4,5,6 and 7 are only those sent by Stéphane and
> reviewed by you 3 months ago with small changes:
>   - I took into account most of your comments
>   - I inserted suspend/resume support
>   - I implemented a way to find out the end of a mt report.
> 
> Patch 1 (hid: add feature_mapping callback) is new but not very
> dangerous I think: it only adds a hook. Thanks to it, I could retrieve
> the magic number which is device-specific.
> 
> Patch 2 (hid: set HID_MAX_FIELD at 128) may need further discussions
> (but is required to use Stantum panels)
> 
> the last patches only introduce support for 3 devices, 1 of them is
> new for the kernel.
> 
> The point is that currently we have users that want to have a proper
> support for their device (PixCir, Cypress TrueTouch and GeneralTouch),
> and it's a shame to ask them to wait for 3 more months.
> 
> Maybe a solution would be to make what we can here during this merge
> window to add support for at least the new devices. Then, in 2.6.39
> and above, we could still migrate other devices, and eventually modify
> some lines in the code.
> 
> Jiri, Dmitry, what do you think?

I still have to go through the patchset, my backlog has grown very badly 
recently, sorry.

In case the patchset doesn't impose danger of regressions for already 
existing devices, we could merge this new 'unified' driver only for newly 
supported devices, and finish the unification in 2.6.39.

-- 
Jiri Kosina
SUSE Labs, Novell Inc.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
  2011-01-06 15:11       ` Jiri Kosina
  (?)
@ 2011-01-06 16:04       ` Henrik Rydberg
  2011-01-06 16:08         ` Benjamin Tissoires
  -1 siblings, 1 reply; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-06 16:04 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Benjamin Tissoires, Stephane Chatty, Dmitry Torokhov,
	linux-input, linux-kernel

> > The point is that currently we have users that want to have a proper
> > support for their device (PixCir, Cypress TrueTouch and GeneralTouch),
> > and it's a shame to ask them to wait for 3 more months.

That is understandable, but for the future, please bear in mind that
submitting patches in the merge window is the worst possible time
within that three-month period.

> > Maybe a solution would be to make what we can here during this merge
> > window to add support for at least the new devices. Then, in 2.6.39
> > and above, we could still migrate other devices, and eventually modify
> > some lines in the code.
> > 
> > Jiri, Dmitry, what do you think?
> 
> I still have to go through the patchset, my backlog has grown very badly 
> recently, sorry.
> 
> In case the patchset doesn't impose danger of regressions for already 
> existing devices, we could merge this new 'unified' driver only for newly 
> supported devices, and finish the unification in 2.6.39.

Sounds reasonable.

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
  2011-01-06 16:04       ` Henrik Rydberg
@ 2011-01-06 16:08         ` Benjamin Tissoires
  2011-01-06 17:28           ` Henrik Rydberg
  2011-01-06 23:26           ` Jiri Kosina
  0 siblings, 2 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-06 16:08 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Jiri Kosina, Stephane Chatty, Dmitry Torokhov, linux-input, linux-kernel

On Thu, Jan 6, 2011 at 5:04 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
>> > The point is that currently we have users that want to have a proper
>> > support for their device (PixCir, Cypress TrueTouch and GeneralTouch),
>> > and it's a shame to ask them to wait for 3 more months.
>
> That is understandable, but for the future, please bear in mind that
> submitting patches in the merge window is the worst possible time
> within that three-month period.
>
>> > Maybe a solution would be to make what we can here during this merge
>> > window to add support for at least the new devices. Then, in 2.6.39
>> > and above, we could still migrate other devices, and eventually modify
>> > some lines in the code.
>> >
>> > Jiri, Dmitry, what do you think?
>>
>> I still have to go through the patchset, my backlog has grown very badly
>> recently, sorry.
>>
>> In case the patchset doesn't impose danger of regressions for already
>> existing devices, we could merge this new 'unified' driver only for newly
>> supported devices, and finish the unification in 2.6.39.
>
> Sounds reasonable.

Thanks Henrik and Jiri.

Do you want me to send a new patchset with only the new devices?

Benjamin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 01/10] hid: add feature_mapping callback
  2011-01-05 17:27   ` Benjamin Tissoires
  (?)
@ 2011-01-06 16:22   ` Henrik Rydberg
  2011-01-07  9:44     ` Benjamin Tissoires
  -1 siblings, 1 reply; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-06 16:22 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Wed, Jan 05, 2011 at 06:27:39PM +0100, Benjamin Tissoires wrote:
> Currently hid doesn't export the features it knows to the specific modules.
> Some information can be really important in such features: MosArt and
> Cypress devices are by default not in a multitouch mode.
> We have to send the value 2 on the right feature.
> 
> This patch exports to the module the features report so they can find the
> right feature to set up the correct mode.
> 
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
> ---
>  drivers/hid/hid-input.c |   10 +++++++++-
>  include/linux/hid.h     |    4 ++++
>  2 files changed, 13 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index bb0b365..07d8cb2 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -287,6 +287,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
>  		goto ignore;
>  	}
>  
> +	if (field->report_type == HID_FEATURE_REPORT) {
> +		if (device->driver->feature_mapping) {
> +			device->driver->feature_mapping(device, hidinput, field,
> +                                usage);
> +		}
> +		goto ignore;
> +	}
> +
>  	if (device->driver->input_mapping) {
>  		int ret = device->driver->input_mapping(device, hidinput, field,
>  				usage, &bit, &max);
> @@ -836,7 +844,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
>  	struct hid_input *hidinput = NULL;
>  	struct input_dev *input_dev;
>  	int i, j, k;
> -	int max_report_type = HID_OUTPUT_REPORT;
> +	int max_report_type = HID_FEATURE_REPORT;

Doing it this way conflicts with the HID_QUIRK_SKIP_OUTPUT_REPORTS quirk.

>  
>  	INIT_LIST_HEAD(&hid->inputs);
>  
> diff --git a/include/linux/hid.h b/include/linux/hid.h
> index bb0f56f..75303b0 100644
> --- a/include/linux/hid.h
> +++ b/include/linux/hid.h
> @@ -593,6 +593,7 @@ struct hid_usage_id {
>   * @report_fixup: called before report descriptor parsing (NULL means nop)
>   * @input_mapping: invoked on input registering before mapping an usage
>   * @input_mapped: invoked on input registering after mapping an usage
> + * @feature_mapping: invoked on feature registering
>   * @suspend: invoked on suspend (NULL means nop)
>   * @resume: invoked on resume if device was not reset (NULL means nop)
>   * @reset_resume: invoked on resume if device was reset (NULL means nop)
> @@ -636,6 +637,9 @@ struct hid_driver {
>  	int (*input_mapped)(struct hid_device *hdev,
>  			struct hid_input *hidinput, struct hid_field *field,
>  			struct hid_usage *usage, unsigned long **bit, int *max);
> +	void (*feature_mapping)(struct hid_device *hdev,
> + 			struct hid_input *hidinput, struct hid_field *field,
> + 			struct hid_usage *usage);
>  #ifdef CONFIG_PM
>  	int (*suspend)(struct hid_device *hdev, pm_message_t message);
>  	int (*resume)(struct hid_device *hdev);

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 02/10] hid: set HID_MAX_FIELD at 128
  2011-01-05 17:27   ` Benjamin Tissoires
  (?)
@ 2011-01-06 16:28   ` Henrik Rydberg
  -1 siblings, 0 replies; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-06 16:28 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Wed, Jan 05, 2011 at 06:27:40PM +0100, Benjamin Tissoires wrote:
> Stantums multitouch panels sends more than 64 reports and this results
> in not being able to handle all the touches given by this device.
> 
> This patch is required to be able to include Stantum panels in the
> unified hid-multitouch driver.
> 
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>

This one could go in anytime, it seems.

Acked-by: Henrik Rydberg <rydberg@euromail.se>

Henrik

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
  2011-01-05 17:27   ` Benjamin Tissoires
@ 2011-01-06 17:25     ` Henrik Rydberg
  -1 siblings, 0 replies; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-06 17:25 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Wed, Jan 05, 2011 at 06:27:41PM +0100, Benjamin Tissoires wrote:
> Created a driver for PixCir based dual-touch panels, including the one
> in the Hanvon tablet.  This is done in a code structure aimed at unifying
> support for several existing HID multitouch panels.
> 
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
> Signed-off-by: Stéphane Chatty <chatty@enac.fr>
> ---
>  drivers/hid/Kconfig          |    6 +
>  drivers/hid/Makefile         |    1 +
>  drivers/hid/hid-core.c       |    2 +
>  drivers/hid/hid-ids.h        |    4 +
>  drivers/hid/hid-multitouch.c |  434 ++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 447 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hid/hid-multitouch.c
> 
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 401acec..6519981 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -285,6 +285,12 @@ config HID_MONTEREY
>  	---help---
>  	Support for Monterey Genius KB29E.
>  
> +config HID_MULTITOUCH
> +	tristate "HID Multitouch panels"
> +	depends on USB_HID
> +	---help---
> +	Generic support for HID multitouch panels.
> +

Please provide a bit more information under this config option. The
usual "what should I do", and roughly what devices are supported.

>  config HID_NTRIG
>  	tristate "N-Trig touch screen"
>  	depends on USB_HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index c335605..ec991d4 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -46,6 +46,7 @@ obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
>  obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
>  obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
>  obj-$(CONFIG_HID_MOSART)	+= hid-mosart.o
> +obj-$(CONFIG_HID_MULTITOUCH)	+= hid-multitouch.o
>  obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
>  obj-$(CONFIG_HID_ORTEK)		+= hid-ortek.o
>  obj-$(CONFIG_HID_PRODIKEYS)	+= hid-prodikeys.o
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index 88668ae..2b4d9b9 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -1286,6 +1286,7 @@ static const struct hid_device_id hid_blacklist[] = {
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
> @@ -1312,6 +1313,7 @@ static const struct hid_device_id hid_blacklist[] = {
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 0f150c7..17b444b 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -134,6 +134,7 @@
>  #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2	0x5577
>  
>  #define USB_VENDOR_ID_CANDO		0x2087
> +#define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703
>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH	0x0a01
>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
> @@ -306,6 +307,9 @@
>  #define USB_DEVICE_ID_HANWANG_TABLET_FIRST	0x5000
>  #define USB_DEVICE_ID_HANWANG_TABLET_LAST	0x8fff
>  
> +#define USB_VENDOR_ID_HANVON		0x20b3
> +#define USB_DEVICE_ID_HANVON_MULTITOUCH	0x0a18
> +
>  #define USB_VENDOR_ID_HAPP		0x078b
>  #define USB_DEVICE_ID_UGCI_DRIVING	0x0010
>  #define USB_DEVICE_ID_UGCI_FLYING	0x0020
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> new file mode 100644
> index 0000000..aea0e32
> --- /dev/null
> +++ b/drivers/hid/hid-multitouch.c
> @@ -0,0 +1,434 @@
> +/*
> + *  HID driver for multitouch panels
> + *
> + *  Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr>
> + *  Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
> + *  Copyright (c) 2010-2011 Enac
> + *
> + */
> +
> +/*
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the Free
> + * Software Foundation; either version 2 of the License, or (at your option)
> + * any later version.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/hid.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/usb.h>
> +#include <linux/input/mt.h>
> +#include "usbhid/usbhid.h"
> +
> +
> +MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
> +MODULE_DESCRIPTION("HID multitouch panels");
> +MODULE_LICENSE("GPL");
> +
> +#include "hid-ids.h"
> +
> +
> +struct mt_slot {
> +	__s32 x, y, p;
> +	__s32 contactid;	/* the device ContactID assigned to this slot */
> +	__u16 trkid;	/* the tracking ID that was assigned to this slot */
> +	bool valid;	/* did we just get valid contact data for this slot? */
> +	bool prev_valid;/* was this slot previously valid/active? */
> +};

The trkid and prev_valid are no longer needed. The touch state seems to be missing.

> +
> +struct mt_buffer {
> +	__s32 x, y, p;
> +	__s32 contactid;	/* the device ContactID assigned to this slot */
> +};

The only different to mt_slot are the valid and touch field, which is
also needed for incoming data. I'd say those should be merged.

> +
> +struct mt_device {
> +	struct mt_buffer curdata;	/* placeholder of incoming data */
> +	struct mt_class *mtclass;	/* our mt device class */
> +	unsigned last_field_index;	/* last field index of the report */
> +	unsigned last_slot_field;	/* the last field of a slot */
> +	__u16 lasttrkid;	/* the last tracking ID we assigned */

No longer needed.

> +	__s8 inputmode;		/* InputMode HID feature, -1 if non-existent */
> +	__u8 num_received;	/* how many contacts we received */
> +	__u8 maxcontact;	/* expected last contact index */
> +	bool curvalid;		/* is the current contact valid? */

This value should probably be a mt_slot struct as well.

> +	struct mt_slot slots[0];	/* first slot */
> +};
> +
> +struct mt_class {
> +	int (*compute_slot)(struct mt_device *);
> +	__u8 maxcontacts;
> +};

I imagine maxcontacts could be variable for devices within the same
class. Perhaps it should be a member of the device instead? The
resolution and fuzz could be added here as well.

> +
> +/* classes of device behavior */
> +#define MT_CLS_DEFAULT 0
> +#define MT_CLS_DUAL1 1
> +
> +/*
> + * these device-dependent functions determine what slot corresponds
> + * to a valid contact that was just read.
> + */
> +
> +static int slot_is_contactid(struct mt_device *td)
> +{
> +	return td->curdata.contactid;
> +}
> +
> +static int find_slot_from_contactid(struct mt_device *td)
> +{
> +	int i;
> +	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
> +		if (td->slots[i].prev_valid &&

Why prev_valid? Ought to be valid, right?

> +			td->slots[i].contactid == td->curdata.contactid)
> +			return i;
> +	}
> +	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
> +		if (!td->slots[i].valid && !td->slots[i].prev_valid)
> +			return i;

Simplifaction here too without the prev_valid.

> +	}
> +	return -1; /* should not occurs */

And what should happen if it does?

> +}
> +
> +struct mt_class mt_classes[] = {
> +	{ find_slot_from_contactid, 10 },     /* MT_CLS_DEFAULT */
> +	{ slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
> +};

It seems likely that this will become a device-specific list, rather than classes.

> +
> +static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
> +		struct hid_field *field, struct hid_usage *usage)
> +{
> +	if (usage->hid == HID_DG_INPUTMODE) {
> +		struct mt_device *td = hid_get_drvdata(hdev);
> +		td->inputmode = field->report->id;
> +	}
> +}
> +
> +static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
> +		struct hid_field *field, struct hid_usage *usage,
> +		unsigned long **bit, int *max)
> +{
> +	struct mt_device *td = hid_get_drvdata(hdev);
> +	switch (usage->hid & HID_USAGE_PAGE) {
> +
> +	case HID_UP_GENDESK:
> +		switch (usage->hid) {
> +		case HID_GD_X:
> +			hid_map_usage(hi, usage, bit, max,
> +					EV_ABS, ABS_MT_POSITION_X);
> +			input_set_abs_params(hi->input, ABS_MT_POSITION_X,
> +						field->logical_minimum,
> +						field->logical_maximum, 0, 0);
> +			/* touchscreen emulation */
> +			input_set_abs_params(hi->input, ABS_X,
> +						field->logical_minimum,
> +						field->logical_maximum, 0, 0);
> +			td->last_slot_field = usage->hid;
> +			return 1;
> +		case HID_GD_Y:
> +			hid_map_usage(hi, usage, bit, max,
> +					EV_ABS, ABS_MT_POSITION_Y);
> +			input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
> +						field->logical_minimum,
> +						field->logical_maximum, 0, 0);
> +			/* touchscreen emulation */
> +			input_set_abs_params(hi->input, ABS_Y,
> +						field->logical_minimum,
> +						field->logical_maximum, 0, 0);
> +			td->last_slot_field = usage->hid;
> +			return 1;
> +		}
> +		return 0;

Nice solution to the end-of-data issue. It would be good if the input
setup was abstracted into a function like in hid-egalax, to simplify
further additions.

> +
> +	case HID_UP_DIGITIZER:
> +		switch (usage->hid) {
> +		case HID_DG_INRANGE:
> +		case HID_DG_CONFIDENCE:
> +			td->last_slot_field = usage->hid;
> +			return 1;

The inrange field has meaning for some drivers, I think these should be split.

> +		case HID_DG_TIPSWITCH:
> +			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
> +			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
> +			td->last_slot_field = usage->hid;
> +			return 1;
> +		case HID_DG_CONTACTID:
> +			if (!hi->input->mt)

This test can be dropped now.

> +				input_mt_init_slots(hi->input,
> +						td->mtclass->maxcontacts);

Maxcontacts should probably take the hid description into account as well.

> +			td->last_slot_field = usage->hid;
> +			return 1;
> +		case HID_DG_TIPPRESSURE:
> +			hid_map_usage(hi, usage, bit, max,
> +					EV_ABS, ABS_MT_PRESSURE);
> +			td->last_slot_field = usage->hid;
> +			return 1;

And ABS_PRESSURE.

> +		case HID_DG_CONTACTCOUNT:
> +			td->last_field_index = field->report->maxfield - 1;

A fall-through here does not seem very useful.

> +		case HID_DG_CONTACTMAX:
> +			/* we don't set td->last_slot_field as contactcount and
> +			 * contact max are global to the report */
> +			return -1;
> +		}
> +		/* let hid-input decide for the others */
> +		return 0;
> +
> +	case 0xff000000:
> +		/* we do not want to map these: no input-oriented meaning */
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
> +		struct hid_field *field, struct hid_usage *usage,
> +		unsigned long **bit, int *max)
> +{
> +	if (usage->type == EV_KEY || usage->type == EV_ABS)
> +		set_bit(usage->type, hi->input->evbit);
> +
> +	return -1;
> +}

There are some hid drivers that need to setup fuzz in order to work
properly. We should either add it to hid core or use the same bypass as
in hid-egalax and hid-3m-pct.

> +
> +/*
> + * 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)
> +{
> +	if (td->curvalid) {
> +		struct mt_slot *slot;
> +		int slotnum = td->mtclass->compute_slot(td);
> +
> +		if (slotnum >= 0 && slotnum <= td->mtclass->maxcontacts - 1) {

Please use "< maxcontacts".

> +			slot = td->slots + slotnum;
> +
> +			slot->valid = true;
> +			memcpy(slot, &(td->curdata), sizeof(struct mt_buffer));

Valid is not always true for sure, and touch should be in here as
well. A simple copy of the current data into the right slot will
suffice - the validity will be copied too.

> +		}
> +	}
> +	td->num_received++;
> +}
> +
> +
> +/*
> + * 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)
> +{
> +	int i;
> +
> +	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
> +		struct mt_slot *s = &(td->slots[i]);
> +		if (!s->valid) {
> +			/*
> +			 * this slot does not contain useful data,
> +			 * notify its closure if necessary
> +			 */
> +			if (s->prev_valid) {
> +				input_mt_slot(input, i);
> +				input_mt_report_slot_state(input,
> +					MT_TOOL_FINGER, false);
> +				s->prev_valid = false;
> +			}
> +			continue;
> +		}
> +		if (!s->prev_valid)
> +			s->trkid = td->lasttrkid++;

Most of the above can be removed.

> +
> +		input_mt_slot(input, i);
> +		input_mt_report_slot_state(input, MT_TOOL_FINGER, true);

"true" here should simply be slot->touch state.

> +		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_PRESSURE, s->p);
> +		s->prev_valid = true;
> +		s->valid = false;

Invalidating the data of a tracked slots seems wrong. If the device
sends tracked data properly, no special consideration is needed - it
will get cleared when appropriate. Other cases could be dealt with
separately.

> +
> +	}
> +
> +	input_mt_report_pointer_emulation(input, true);
> +	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);
> +
> +	if (hid->claimed & HID_CLAIMED_INPUT) {
> +		switch (usage->hid) {
> +		case HID_DG_INRANGE:
> +			break;

Egalax uses this field as validity.

> +		case HID_DG_TIPSWITCH:
> +			td->curvalid = value;

Most drivers seem to use this as touch state.

> +			break;
> +		case HID_DG_CONFIDENCE:
> +			break;
> +		case HID_DG_CONTACTID:
> +			td->curdata.contactid = value;
> +			break;
> +		case HID_DG_TIPPRESSURE:
> +			td->curdata.p = value;
> +			break;
> +		case HID_GD_X:
> +			td->curdata.x = value;
> +			break;
> +		case HID_GD_Y:
> +			td->curdata.y = value;
> +			break;
> +		case HID_DG_CONTACTCOUNT:
> +			/*
> +			 * We must not overwrite the previous value (some
> +			 * devices send one sequence splitted over several
> +			 * messages)
> +			 */
> +			if (value)
> +				td->maxcontact = value - 1;

Is td->maxcontact ever reset? And why not num_expected or something
instead of maxcontact - odd semantics.

> +			break;
> +		case HID_DG_CONTACTMAX:
> +			break;

This one was filtered already.

> +
> +		default:
> +			/* fallback to the generic hidinput handling */
> +			return 0;
> +		}
> +	}
> +
> +	if (usage->hid == td->last_slot_field)
> +		mt_complete_slot(td);
> +
> +	if (field->index == td->last_field_index
> +		&& td->num_received > td->maxcontact) {
> +		struct input_dev *input = field->hidinput->input;

No need to declare a temp variable for one access.

> +		mt_emit_event(td, input);

Resetting expected countact count here would be good.

> +	}
> +
> +	/* we have handled the hidinput part, now remains hiddev */
> +	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
> +		hid->hiddev_hid_event(hid, field, usage, value);
> +
> +	return 1;
> +}
> +
> +static void mt_set_input_mode(struct hid_device *hdev)
> +{
> +	struct mt_device *td = hid_get_drvdata(hdev);
> +	struct hid_report *r;
> +	struct hid_report_enum *re;
> +
> +	if (td->inputmode < 0)
> +		return;
> +
> +	re = &(hdev->report_enum[HID_FEATURE_REPORT]);
> +	r = re->report_id_hash[td->inputmode];
> +	if (r) {
> +		r->field[0]->value[0] = 0x02;
> +		usbhid_submit_report(hdev, r, USB_DIR_OUT);
> +	}
> +}

Nice reduction.

> +
> +static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
> +{
> +	int ret;
> +	struct mt_device *td;
> +	struct mt_class *mtclass = mt_classes + id->driver_data;
> +
> +	/* This allows the driver to correctly support devices
> +	 * that emit events over several HID messages.
> +	 */
> +	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
> +
> +	td = kzalloc(sizeof(struct mt_device) +
> +				mtclass->maxcontacts * sizeof(struct mt_slot),
> +				GFP_KERNEL);
> +	if (!td) {
> +		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
> +		return -ENOMEM;
> +	}
> +	td->mtclass = mtclass;
> +	td->inputmode = -1;
> +	hid_set_drvdata(hdev, td);
> +
> +	ret = hid_parse(hdev);
> +	if (ret != 0)
> +		goto fail;
> +
> +	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> +	if (ret != 0)
> +		goto fail;
> +
> +	mt_set_input_mode(hdev);
> +
> +	return 0;
> +
> +fail:
> +	kfree(td);
> +	return ret;
> +}
> +
> +#ifdef CONFIG_PM
> +static int mt_reset_resume(struct hid_device *hdev)
> +{
> +	mt_set_input_mode(hdev);
> +	return 0;
> +}
> +#endif
> +
> +static void mt_remove(struct hid_device *hdev)
> +{
> +	struct mt_device *td = hid_get_drvdata(hdev);
> +	hid_hw_stop(hdev);
> +	kfree(td);
> +	hid_set_drvdata(hdev, NULL);
> +}
> +
> +static const struct hid_device_id mt_devices[] = {
> +
> +	/* PixCir-based panels */
> +	{ .driver_data = MT_CLS_DUAL1,
> +		HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
> +			USB_DEVICE_ID_HANVON_MULTITOUCH) },
> +	{ .driver_data = MT_CLS_DUAL1,
> +		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
> +			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
> +
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(hid, mt_devices);
> +
> +static const struct hid_usage_id mt_grabbed_usages[] = {
> +	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
> +	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
> +};
> +
> +static struct hid_driver mt_driver = {
> +	.name = "hid-multitouch",
> +	.id_table = mt_devices,
> +	.probe = mt_probe,
> +	.remove = mt_remove,
> +	.input_mapping = mt_input_mapping,
> +	.input_mapped = mt_input_mapped,
> +	.feature_mapping = mt_feature_mapping,
> +	.usage_table = mt_grabbed_usages,
> +	.event = mt_event,
> +#ifdef CONFIG_PM
> +	.reset_resume = mt_reset_resume,
> +#endif
> +};
> +
> +static int __init mt_init(void)
> +{
> +	return hid_register_driver(&mt_driver);
> +}
> +
> +static void __exit mt_exit(void)
> +{
> +	hid_unregister_driver(&mt_driver);
> +}
> +
> +module_init(mt_init);
> +module_exit(mt_exit);
> -- 
> 1.7.3.4
> 

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
@ 2011-01-06 17:25     ` Henrik Rydberg
  0 siblings, 0 replies; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-06 17:25 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Wed, Jan 05, 2011 at 06:27:41PM +0100, Benjamin Tissoires wrote:
> Created a driver for PixCir based dual-touch panels, including the one
> in the Hanvon tablet.  This is done in a code structure aimed at unifying
> support for several existing HID multitouch panels.
> 
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
> Signed-off-by: Stéphane Chatty <chatty@enac.fr>
> ---
>  drivers/hid/Kconfig          |    6 +
>  drivers/hid/Makefile         |    1 +
>  drivers/hid/hid-core.c       |    2 +
>  drivers/hid/hid-ids.h        |    4 +
>  drivers/hid/hid-multitouch.c |  434 ++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 447 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hid/hid-multitouch.c
> 
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 401acec..6519981 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -285,6 +285,12 @@ config HID_MONTEREY
>  	---help---
>  	Support for Monterey Genius KB29E.
>  
> +config HID_MULTITOUCH
> +	tristate "HID Multitouch panels"
> +	depends on USB_HID
> +	---help---
> +	Generic support for HID multitouch panels.
> +

Please provide a bit more information under this config option. The
usual "what should I do", and roughly what devices are supported.

>  config HID_NTRIG
>  	tristate "N-Trig touch screen"
>  	depends on USB_HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index c335605..ec991d4 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -46,6 +46,7 @@ obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
>  obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
>  obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
>  obj-$(CONFIG_HID_MOSART)	+= hid-mosart.o
> +obj-$(CONFIG_HID_MULTITOUCH)	+= hid-multitouch.o
>  obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
>  obj-$(CONFIG_HID_ORTEK)		+= hid-ortek.o
>  obj-$(CONFIG_HID_PRODIKEYS)	+= hid-prodikeys.o
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index 88668ae..2b4d9b9 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -1286,6 +1286,7 @@ static const struct hid_device_id hid_blacklist[] = {
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
> @@ -1312,6 +1313,7 @@ static const struct hid_device_id hid_blacklist[] = {
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 0f150c7..17b444b 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -134,6 +134,7 @@
>  #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2	0x5577
>  
>  #define USB_VENDOR_ID_CANDO		0x2087
> +#define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703
>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH	0x0a01
>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
> @@ -306,6 +307,9 @@
>  #define USB_DEVICE_ID_HANWANG_TABLET_FIRST	0x5000
>  #define USB_DEVICE_ID_HANWANG_TABLET_LAST	0x8fff
>  
> +#define USB_VENDOR_ID_HANVON		0x20b3
> +#define USB_DEVICE_ID_HANVON_MULTITOUCH	0x0a18
> +
>  #define USB_VENDOR_ID_HAPP		0x078b
>  #define USB_DEVICE_ID_UGCI_DRIVING	0x0010
>  #define USB_DEVICE_ID_UGCI_FLYING	0x0020
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> new file mode 100644
> index 0000000..aea0e32
> --- /dev/null
> +++ b/drivers/hid/hid-multitouch.c
> @@ -0,0 +1,434 @@
> +/*
> + *  HID driver for multitouch panels
> + *
> + *  Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr>
> + *  Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
> + *  Copyright (c) 2010-2011 Enac
> + *
> + */
> +
> +/*
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the Free
> + * Software Foundation; either version 2 of the License, or (at your option)
> + * any later version.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/hid.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/usb.h>
> +#include <linux/input/mt.h>
> +#include "usbhid/usbhid.h"
> +
> +
> +MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
> +MODULE_DESCRIPTION("HID multitouch panels");
> +MODULE_LICENSE("GPL");
> +
> +#include "hid-ids.h"
> +
> +
> +struct mt_slot {
> +	__s32 x, y, p;
> +	__s32 contactid;	/* the device ContactID assigned to this slot */
> +	__u16 trkid;	/* the tracking ID that was assigned to this slot */
> +	bool valid;	/* did we just get valid contact data for this slot? */
> +	bool prev_valid;/* was this slot previously valid/active? */
> +};

The trkid and prev_valid are no longer needed. The touch state seems to be missing.

> +
> +struct mt_buffer {
> +	__s32 x, y, p;
> +	__s32 contactid;	/* the device ContactID assigned to this slot */
> +};

The only different to mt_slot are the valid and touch field, which is
also needed for incoming data. I'd say those should be merged.

> +
> +struct mt_device {
> +	struct mt_buffer curdata;	/* placeholder of incoming data */
> +	struct mt_class *mtclass;	/* our mt device class */
> +	unsigned last_field_index;	/* last field index of the report */
> +	unsigned last_slot_field;	/* the last field of a slot */
> +	__u16 lasttrkid;	/* the last tracking ID we assigned */

No longer needed.

> +	__s8 inputmode;		/* InputMode HID feature, -1 if non-existent */
> +	__u8 num_received;	/* how many contacts we received */
> +	__u8 maxcontact;	/* expected last contact index */
> +	bool curvalid;		/* is the current contact valid? */

This value should probably be a mt_slot struct as well.

> +	struct mt_slot slots[0];	/* first slot */
> +};
> +
> +struct mt_class {
> +	int (*compute_slot)(struct mt_device *);
> +	__u8 maxcontacts;
> +};

I imagine maxcontacts could be variable for devices within the same
class. Perhaps it should be a member of the device instead? The
resolution and fuzz could be added here as well.

> +
> +/* classes of device behavior */
> +#define MT_CLS_DEFAULT 0
> +#define MT_CLS_DUAL1 1
> +
> +/*
> + * these device-dependent functions determine what slot corresponds
> + * to a valid contact that was just read.
> + */
> +
> +static int slot_is_contactid(struct mt_device *td)
> +{
> +	return td->curdata.contactid;
> +}
> +
> +static int find_slot_from_contactid(struct mt_device *td)
> +{
> +	int i;
> +	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
> +		if (td->slots[i].prev_valid &&

Why prev_valid? Ought to be valid, right?

> +			td->slots[i].contactid == td->curdata.contactid)
> +			return i;
> +	}
> +	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
> +		if (!td->slots[i].valid && !td->slots[i].prev_valid)
> +			return i;

Simplifaction here too without the prev_valid.

> +	}
> +	return -1; /* should not occurs */

And what should happen if it does?

> +}
> +
> +struct mt_class mt_classes[] = {
> +	{ find_slot_from_contactid, 10 },     /* MT_CLS_DEFAULT */
> +	{ slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
> +};

It seems likely that this will become a device-specific list, rather than classes.

> +
> +static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
> +		struct hid_field *field, struct hid_usage *usage)
> +{
> +	if (usage->hid == HID_DG_INPUTMODE) {
> +		struct mt_device *td = hid_get_drvdata(hdev);
> +		td->inputmode = field->report->id;
> +	}
> +}
> +
> +static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
> +		struct hid_field *field, struct hid_usage *usage,
> +		unsigned long **bit, int *max)
> +{
> +	struct mt_device *td = hid_get_drvdata(hdev);
> +	switch (usage->hid & HID_USAGE_PAGE) {
> +
> +	case HID_UP_GENDESK:
> +		switch (usage->hid) {
> +		case HID_GD_X:
> +			hid_map_usage(hi, usage, bit, max,
> +					EV_ABS, ABS_MT_POSITION_X);
> +			input_set_abs_params(hi->input, ABS_MT_POSITION_X,
> +						field->logical_minimum,
> +						field->logical_maximum, 0, 0);
> +			/* touchscreen emulation */
> +			input_set_abs_params(hi->input, ABS_X,
> +						field->logical_minimum,
> +						field->logical_maximum, 0, 0);
> +			td->last_slot_field = usage->hid;
> +			return 1;
> +		case HID_GD_Y:
> +			hid_map_usage(hi, usage, bit, max,
> +					EV_ABS, ABS_MT_POSITION_Y);
> +			input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
> +						field->logical_minimum,
> +						field->logical_maximum, 0, 0);
> +			/* touchscreen emulation */
> +			input_set_abs_params(hi->input, ABS_Y,
> +						field->logical_minimum,
> +						field->logical_maximum, 0, 0);
> +			td->last_slot_field = usage->hid;
> +			return 1;
> +		}
> +		return 0;

Nice solution to the end-of-data issue. It would be good if the input
setup was abstracted into a function like in hid-egalax, to simplify
further additions.

> +
> +	case HID_UP_DIGITIZER:
> +		switch (usage->hid) {
> +		case HID_DG_INRANGE:
> +		case HID_DG_CONFIDENCE:
> +			td->last_slot_field = usage->hid;
> +			return 1;

The inrange field has meaning for some drivers, I think these should be split.

> +		case HID_DG_TIPSWITCH:
> +			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
> +			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
> +			td->last_slot_field = usage->hid;
> +			return 1;
> +		case HID_DG_CONTACTID:
> +			if (!hi->input->mt)

This test can be dropped now.

> +				input_mt_init_slots(hi->input,
> +						td->mtclass->maxcontacts);

Maxcontacts should probably take the hid description into account as well.

> +			td->last_slot_field = usage->hid;
> +			return 1;
> +		case HID_DG_TIPPRESSURE:
> +			hid_map_usage(hi, usage, bit, max,
> +					EV_ABS, ABS_MT_PRESSURE);
> +			td->last_slot_field = usage->hid;
> +			return 1;

And ABS_PRESSURE.

> +		case HID_DG_CONTACTCOUNT:
> +			td->last_field_index = field->report->maxfield - 1;

A fall-through here does not seem very useful.

> +		case HID_DG_CONTACTMAX:
> +			/* we don't set td->last_slot_field as contactcount and
> +			 * contact max are global to the report */
> +			return -1;
> +		}
> +		/* let hid-input decide for the others */
> +		return 0;
> +
> +	case 0xff000000:
> +		/* we do not want to map these: no input-oriented meaning */
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
> +		struct hid_field *field, struct hid_usage *usage,
> +		unsigned long **bit, int *max)
> +{
> +	if (usage->type == EV_KEY || usage->type == EV_ABS)
> +		set_bit(usage->type, hi->input->evbit);
> +
> +	return -1;
> +}

There are some hid drivers that need to setup fuzz in order to work
properly. We should either add it to hid core or use the same bypass as
in hid-egalax and hid-3m-pct.

> +
> +/*
> + * 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)
> +{
> +	if (td->curvalid) {
> +		struct mt_slot *slot;
> +		int slotnum = td->mtclass->compute_slot(td);
> +
> +		if (slotnum >= 0 && slotnum <= td->mtclass->maxcontacts - 1) {

Please use "< maxcontacts".

> +			slot = td->slots + slotnum;
> +
> +			slot->valid = true;
> +			memcpy(slot, &(td->curdata), sizeof(struct mt_buffer));

Valid is not always true for sure, and touch should be in here as
well. A simple copy of the current data into the right slot will
suffice - the validity will be copied too.

> +		}
> +	}
> +	td->num_received++;
> +}
> +
> +
> +/*
> + * 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)
> +{
> +	int i;
> +
> +	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
> +		struct mt_slot *s = &(td->slots[i]);
> +		if (!s->valid) {
> +			/*
> +			 * this slot does not contain useful data,
> +			 * notify its closure if necessary
> +			 */
> +			if (s->prev_valid) {
> +				input_mt_slot(input, i);
> +				input_mt_report_slot_state(input,
> +					MT_TOOL_FINGER, false);
> +				s->prev_valid = false;
> +			}
> +			continue;
> +		}
> +		if (!s->prev_valid)
> +			s->trkid = td->lasttrkid++;

Most of the above can be removed.

> +
> +		input_mt_slot(input, i);
> +		input_mt_report_slot_state(input, MT_TOOL_FINGER, true);

"true" here should simply be slot->touch state.

> +		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_PRESSURE, s->p);
> +		s->prev_valid = true;
> +		s->valid = false;

Invalidating the data of a tracked slots seems wrong. If the device
sends tracked data properly, no special consideration is needed - it
will get cleared when appropriate. Other cases could be dealt with
separately.

> +
> +	}
> +
> +	input_mt_report_pointer_emulation(input, true);
> +	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);
> +
> +	if (hid->claimed & HID_CLAIMED_INPUT) {
> +		switch (usage->hid) {
> +		case HID_DG_INRANGE:
> +			break;

Egalax uses this field as validity.

> +		case HID_DG_TIPSWITCH:
> +			td->curvalid = value;

Most drivers seem to use this as touch state.

> +			break;
> +		case HID_DG_CONFIDENCE:
> +			break;
> +		case HID_DG_CONTACTID:
> +			td->curdata.contactid = value;
> +			break;
> +		case HID_DG_TIPPRESSURE:
> +			td->curdata.p = value;
> +			break;
> +		case HID_GD_X:
> +			td->curdata.x = value;
> +			break;
> +		case HID_GD_Y:
> +			td->curdata.y = value;
> +			break;
> +		case HID_DG_CONTACTCOUNT:
> +			/*
> +			 * We must not overwrite the previous value (some
> +			 * devices send one sequence splitted over several
> +			 * messages)
> +			 */
> +			if (value)
> +				td->maxcontact = value - 1;

Is td->maxcontact ever reset? And why not num_expected or something
instead of maxcontact - odd semantics.

> +			break;
> +		case HID_DG_CONTACTMAX:
> +			break;

This one was filtered already.

> +
> +		default:
> +			/* fallback to the generic hidinput handling */
> +			return 0;
> +		}
> +	}
> +
> +	if (usage->hid == td->last_slot_field)
> +		mt_complete_slot(td);
> +
> +	if (field->index == td->last_field_index
> +		&& td->num_received > td->maxcontact) {
> +		struct input_dev *input = field->hidinput->input;

No need to declare a temp variable for one access.

> +		mt_emit_event(td, input);

Resetting expected countact count here would be good.

> +	}
> +
> +	/* we have handled the hidinput part, now remains hiddev */
> +	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
> +		hid->hiddev_hid_event(hid, field, usage, value);
> +
> +	return 1;
> +}
> +
> +static void mt_set_input_mode(struct hid_device *hdev)
> +{
> +	struct mt_device *td = hid_get_drvdata(hdev);
> +	struct hid_report *r;
> +	struct hid_report_enum *re;
> +
> +	if (td->inputmode < 0)
> +		return;
> +
> +	re = &(hdev->report_enum[HID_FEATURE_REPORT]);
> +	r = re->report_id_hash[td->inputmode];
> +	if (r) {
> +		r->field[0]->value[0] = 0x02;
> +		usbhid_submit_report(hdev, r, USB_DIR_OUT);
> +	}
> +}

Nice reduction.

> +
> +static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
> +{
> +	int ret;
> +	struct mt_device *td;
> +	struct mt_class *mtclass = mt_classes + id->driver_data;
> +
> +	/* This allows the driver to correctly support devices
> +	 * that emit events over several HID messages.
> +	 */
> +	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
> +
> +	td = kzalloc(sizeof(struct mt_device) +
> +				mtclass->maxcontacts * sizeof(struct mt_slot),
> +				GFP_KERNEL);
> +	if (!td) {
> +		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
> +		return -ENOMEM;
> +	}
> +	td->mtclass = mtclass;
> +	td->inputmode = -1;
> +	hid_set_drvdata(hdev, td);
> +
> +	ret = hid_parse(hdev);
> +	if (ret != 0)
> +		goto fail;
> +
> +	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> +	if (ret != 0)
> +		goto fail;
> +
> +	mt_set_input_mode(hdev);
> +
> +	return 0;
> +
> +fail:
> +	kfree(td);
> +	return ret;
> +}
> +
> +#ifdef CONFIG_PM
> +static int mt_reset_resume(struct hid_device *hdev)
> +{
> +	mt_set_input_mode(hdev);
> +	return 0;
> +}
> +#endif
> +
> +static void mt_remove(struct hid_device *hdev)
> +{
> +	struct mt_device *td = hid_get_drvdata(hdev);
> +	hid_hw_stop(hdev);
> +	kfree(td);
> +	hid_set_drvdata(hdev, NULL);
> +}
> +
> +static const struct hid_device_id mt_devices[] = {
> +
> +	/* PixCir-based panels */
> +	{ .driver_data = MT_CLS_DUAL1,
> +		HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
> +			USB_DEVICE_ID_HANVON_MULTITOUCH) },
> +	{ .driver_data = MT_CLS_DUAL1,
> +		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
> +			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
> +
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(hid, mt_devices);
> +
> +static const struct hid_usage_id mt_grabbed_usages[] = {
> +	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
> +	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
> +};
> +
> +static struct hid_driver mt_driver = {
> +	.name = "hid-multitouch",
> +	.id_table = mt_devices,
> +	.probe = mt_probe,
> +	.remove = mt_remove,
> +	.input_mapping = mt_input_mapping,
> +	.input_mapped = mt_input_mapped,
> +	.feature_mapping = mt_feature_mapping,
> +	.usage_table = mt_grabbed_usages,
> +	.event = mt_event,
> +#ifdef CONFIG_PM
> +	.reset_resume = mt_reset_resume,
> +#endif
> +};
> +
> +static int __init mt_init(void)
> +{
> +	return hid_register_driver(&mt_driver);
> +}
> +
> +static void __exit mt_exit(void)
> +{
> +	hid_unregister_driver(&mt_driver);
> +}
> +
> +module_init(mt_init);
> +module_exit(mt_exit);
> -- 
> 1.7.3.4
> 

Thanks,
Henrik
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
  2011-01-06 16:08         ` Benjamin Tissoires
@ 2011-01-06 17:28           ` Henrik Rydberg
  2011-01-06 23:26           ` Jiri Kosina
  1 sibling, 0 replies; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-06 17:28 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Jiri Kosina, Stephane Chatty, Dmitry Torokhov, linux-input, linux-kernel

On Thu, Jan 06, 2011 at 05:08:39PM +0100, Benjamin Tissoires wrote:
> On Thu, Jan 6, 2011 at 5:04 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
> >> > The point is that currently we have users that want to have a proper
> >> > support for their device (PixCir, Cypress TrueTouch and GeneralTouch),
> >> > and it's a shame to ask them to wait for 3 more months.
> >
> > That is understandable, but for the future, please bear in mind that
> > submitting patches in the merge window is the worst possible time
> > within that three-month period.
> >
> >> > Maybe a solution would be to make what we can here during this merge
> >> > window to add support for at least the new devices. Then, in 2.6.39
> >> > and above, we could still migrate other devices, and eventually modify
> >> > some lines in the code.
> >> >
> >> > Jiri, Dmitry, what do you think?
> >>
> >> I still have to go through the patchset, my backlog has grown very badly
> >> recently, sorry.
> >>
> >> In case the patchset doesn't impose danger of regressions for already
> >> existing devices, we could merge this new 'unified' driver only for newly
> >> supported devices, and finish the unification in 2.6.39.
> >
> > Sounds reasonable.
> 
> Thanks Henrik and Jiri.
> 
> Do you want me to send a new patchset with only the new devices?

Yes, please do. Thanks again for doing this, it is going to be
great. I sent comments for the main driver, and will hold off the rest
for the next round, then.

Cheers,
Henrik

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
  2011-01-06 16:08         ` Benjamin Tissoires
  2011-01-06 17:28           ` Henrik Rydberg
@ 2011-01-06 23:26           ` Jiri Kosina
  1 sibling, 0 replies; 56+ messages in thread
From: Jiri Kosina @ 2011-01-06 23:26 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Henrik Rydberg, Stephane Chatty, Dmitry Torokhov, linux-input,
	linux-kernel

On Thu, 6 Jan 2011, Benjamin Tissoires wrote:

> >> I still have to go through the patchset, my backlog has grown very 
> >> badly recently, sorry.
> >>
> >> In case the patchset doesn't impose danger of regressions for already
> >> existing devices, we could merge this new 'unified' driver only for newly
> >> supported devices, and finish the unification in 2.6.39.
> >
> > Sounds reasonable.
> 
> Thanks Henrik and Jiri.
> 
> Do you want me to send a new patchset with only the new devices?

Yes, that would be best. And we will finish the thing up in .39 (you can 
start sending me the patches any time once you have finished the 
separation, I'll put the into separate branch queued for .39).

And thanks for doing this Benjamin, I am really looking forward to the 
unified driver.

-- 
Jiri Kosina
SUSE Labs, Novell Inc.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
  2011-01-06 15:11       ` Jiri Kosina
@ 2011-01-07  1:14         ` Dmitry Torokhov
  -1 siblings, 0 replies; 56+ messages in thread
From: Dmitry Torokhov @ 2011-01-07  1:14 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Benjamin Tissoires, Henrik Rydberg, Stephane Chatty, linux-input,
	linux-kernel

On Thu, Jan 06, 2011 at 04:11:46PM +0100, Jiri Kosina wrote:
> On Thu, 6 Jan 2011, Benjamin Tissoires wrote:
> 
> > Hi Henrik,
> > 
> > thanks for the future review ;)
> > 
> > Well, patches n° 3,4,5,6 and 7 are only those sent by Stéphane and
> > reviewed by you 3 months ago with small changes:
> >   - I took into account most of your comments
> >   - I inserted suspend/resume support
> >   - I implemented a way to find out the end of a mt report.
> > 
> > Patch 1 (hid: add feature_mapping callback) is new but not very
> > dangerous I think: it only adds a hook. Thanks to it, I could retrieve
> > the magic number which is device-specific.
> > 
> > Patch 2 (hid: set HID_MAX_FIELD at 128) may need further discussions
> > (but is required to use Stantum panels)
> > 
> > the last patches only introduce support for 3 devices, 1 of them is
> > new for the kernel.
> > 
> > The point is that currently we have users that want to have a proper
> > support for their device (PixCir, Cypress TrueTouch and GeneralTouch),
> > and it's a shame to ask them to wait for 3 more months.
> > 
> > Maybe a solution would be to make what we can here during this merge
> > window to add support for at least the new devices. Then, in 2.6.39
> > and above, we could still migrate other devices, and eventually modify
> > some lines in the code.
> > 
> > Jiri, Dmitry, what do you think?
> 
> I still have to go through the patchset, my backlog has grown very badly 
> recently, sorry.
> 
> In case the patchset doesn't impose danger of regressions for already 
> existing devices, we could merge this new 'unified' driver only for newly 
> supported devices, and finish the unification in 2.6.39.
> 

Yep, let's merge the dirver and all new devices in this round and then
get ready to convert already supported devices in next window.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
@ 2011-01-07  1:14         ` Dmitry Torokhov
  0 siblings, 0 replies; 56+ messages in thread
From: Dmitry Torokhov @ 2011-01-07  1:14 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Benjamin Tissoires, Henrik Rydberg, Stephane Chatty, linux-input,
	linux-kernel

On Thu, Jan 06, 2011 at 04:11:46PM +0100, Jiri Kosina wrote:
> On Thu, 6 Jan 2011, Benjamin Tissoires wrote:
> 
> > Hi Henrik,
> > 
> > thanks for the future review ;)
> > 
> > Well, patches n° 3,4,5,6 and 7 are only those sent by Stéphane and
> > reviewed by you 3 months ago with small changes:
> >   - I took into account most of your comments
> >   - I inserted suspend/resume support
> >   - I implemented a way to find out the end of a mt report.
> > 
> > Patch 1 (hid: add feature_mapping callback) is new but not very
> > dangerous I think: it only adds a hook. Thanks to it, I could retrieve
> > the magic number which is device-specific.
> > 
> > Patch 2 (hid: set HID_MAX_FIELD at 128) may need further discussions
> > (but is required to use Stantum panels)
> > 
> > the last patches only introduce support for 3 devices, 1 of them is
> > new for the kernel.
> > 
> > The point is that currently we have users that want to have a proper
> > support for their device (PixCir, Cypress TrueTouch and GeneralTouch),
> > and it's a shame to ask them to wait for 3 more months.
> > 
> > Maybe a solution would be to make what we can here during this merge
> > window to add support for at least the new devices. Then, in 2.6.39
> > and above, we could still migrate other devices, and eventually modify
> > some lines in the code.
> > 
> > Jiri, Dmitry, what do you think?
> 
> I still have to go through the patchset, my backlog has grown very badly 
> recently, sorry.
> 
> In case the patchset doesn't impose danger of regressions for already 
> existing devices, we could merge this new 'unified' driver only for newly 
> supported devices, and finish the unification in 2.6.39.
> 

Yep, let's merge the dirver and all new devices in this round and then
get ready to convert already supported devices in next window.

-- 
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
  2011-01-06 17:25     ` Henrik Rydberg
@ 2011-01-07  9:38       ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-07  9:38 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Thu, Jan 6, 2011 at 6:25 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
> On Wed, Jan 05, 2011 at 06:27:41PM +0100, Benjamin Tissoires wrote:
>> Created a driver for PixCir based dual-touch panels, including the one
>> in the Hanvon tablet.  This is done in a code structure aimed at unifying
>> support for several existing HID multitouch panels.
>>
>> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
>> Signed-off-by: Stéphane Chatty <chatty@enac.fr>
>> ---
>>  drivers/hid/Kconfig          |    6 +
>>  drivers/hid/Makefile         |    1 +
>>  drivers/hid/hid-core.c       |    2 +
>>  drivers/hid/hid-ids.h        |    4 +
>>  drivers/hid/hid-multitouch.c |  434 ++++++++++++++++++++++++++++++++++++++++++
>>  5 files changed, 447 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/hid/hid-multitouch.c
>>
>> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
>> index 401acec..6519981 100644
>> --- a/drivers/hid/Kconfig
>> +++ b/drivers/hid/Kconfig
>> @@ -285,6 +285,12 @@ config HID_MONTEREY
>>       ---help---
>>       Support for Monterey Genius KB29E.
>>
>> +config HID_MULTITOUCH
>> +     tristate "HID Multitouch panels"
>> +     depends on USB_HID
>> +     ---help---
>> +     Generic support for HID multitouch panels.
>> +
>
> Please provide a bit more information under this config option. The
> usual "what should I do", and roughly what devices are supported.

Will try, but don't hesitate to send one if you feel in a good mood for writing.

I can propose:

+        ---help---
+          Generic support for HID multitouch panels.
+          Currently supported panels are:
+          - PixCir touchscreen
+          - Cypress TrueTouch
+          - 'Sensing Win7-TwoFinger' panel by GeneralTouch

>
>>  config HID_NTRIG
>>       tristate "N-Trig touch screen"
>>       depends on USB_HID
>> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
>> index c335605..ec991d4 100644
>> --- a/drivers/hid/Makefile
>> +++ b/drivers/hid/Makefile
>> @@ -46,6 +46,7 @@ obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
>>  obj-$(CONFIG_HID_MICROSOFT)  += hid-microsoft.o
>>  obj-$(CONFIG_HID_MONTEREY)   += hid-monterey.o
>>  obj-$(CONFIG_HID_MOSART)     += hid-mosart.o
>> +obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o
>>  obj-$(CONFIG_HID_NTRIG)              += hid-ntrig.o
>>  obj-$(CONFIG_HID_ORTEK)              += hid-ortek.o
>>  obj-$(CONFIG_HID_PRODIKEYS)  += hid-prodikeys.o
>> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
>> index 88668ae..2b4d9b9 100644
>> --- a/drivers/hid/hid-core.c
>> +++ b/drivers/hid/hid-core.c
>> @@ -1286,6 +1286,7 @@ static const struct hid_device_id hid_blacklist[] = {
>>       { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
>> +     { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
>> @@ -1312,6 +1313,7 @@ static const struct hid_device_id hid_blacklist[] = {
>>       { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
>> +     { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
>> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
>> index 0f150c7..17b444b 100644
>> --- a/drivers/hid/hid-ids.h
>> +++ b/drivers/hid/hid-ids.h
>> @@ -134,6 +134,7 @@
>>  #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2    0x5577
>>
>>  #define USB_VENDOR_ID_CANDO          0x2087
>> +#define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703
>>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH      0x0a01
>>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
>>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
>> @@ -306,6 +307,9 @@
>>  #define USB_DEVICE_ID_HANWANG_TABLET_FIRST   0x5000
>>  #define USB_DEVICE_ID_HANWANG_TABLET_LAST    0x8fff
>>
>> +#define USB_VENDOR_ID_HANVON         0x20b3
>> +#define USB_DEVICE_ID_HANVON_MULTITOUCH      0x0a18
>> +
>>  #define USB_VENDOR_ID_HAPP           0x078b
>>  #define USB_DEVICE_ID_UGCI_DRIVING   0x0010
>>  #define USB_DEVICE_ID_UGCI_FLYING    0x0020
>> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
>> new file mode 100644
>> index 0000000..aea0e32
>> --- /dev/null
>> +++ b/drivers/hid/hid-multitouch.c
>> @@ -0,0 +1,434 @@
>> +/*
>> + *  HID driver for multitouch panels
>> + *
>> + *  Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr>
>> + *  Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
>> + *  Copyright (c) 2010-2011 Enac
>> + *
>> + */
>> +
>> +/*
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License as published by the Free
>> + * Software Foundation; either version 2 of the License, or (at your option)
>> + * any later version.
>> + */
>> +
>> +#include <linux/device.h>
>> +#include <linux/hid.h>
>> +#include <linux/module.h>
>> +#include <linux/slab.h>
>> +#include <linux/usb.h>
>> +#include <linux/input/mt.h>
>> +#include "usbhid/usbhid.h"
>> +
>> +
>> +MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
>> +MODULE_DESCRIPTION("HID multitouch panels");
>> +MODULE_LICENSE("GPL");
>> +
>> +#include "hid-ids.h"
>> +
>> +
>> +struct mt_slot {
>> +     __s32 x, y, p;
>> +     __s32 contactid;        /* the device ContactID assigned to this slot */
>> +     __u16 trkid;    /* the tracking ID that was assigned to this slot */
>> +     bool valid;     /* did we just get valid contact data for this slot? */
>> +     bool prev_valid;/* was this slot previously valid/active? */
>> +};
>
> The trkid and prev_valid are no longer needed. The touch state seems to be missing.

Concerning the trkid, agree.
I can assure you that prev_valid is needed by at least the Cypress
device. In a sense, it has the same problem than mt protocol A: it
does not send the release information except when the last finger has
been released. This gymnastic is thus required.

I think that the misunderstanding comes from the name. We have this 2
flags (valid and prev_valid) to tell whether the device sent data
during this report or the previous one. It's not the same meaning that
the touch you're talking about. For Cypress device, those 2 flags are
mandatory.

Maybe introducing data + prev_data + touch (3 flags instead of 2->
touch can go into mt_buffer, and data and prev_data only in mt_slot as
they are not given by the device) is clearer.


>
>> +
>> +struct mt_buffer {
>> +     __s32 x, y, p;
>> +     __s32 contactid;        /* the device ContactID assigned to this slot */
>> +};
>
> The only different to mt_slot are the valid and touch field, which is
> also needed for incoming data. I'd say those should be merged.
>

Well, the point is that the buffer and the slot have 2 different meanings:
one is the incoming data, the other is the processed data. It strikes
us to have only one struct as the slot contains extra information for
it to be processed.

>> +
>> +struct mt_device {
>> +     struct mt_buffer curdata;       /* placeholder of incoming data */
>> +     struct mt_class *mtclass;       /* our mt device class */
>> +     unsigned last_field_index;      /* last field index of the report */
>> +     unsigned last_slot_field;       /* the last field of a slot */
>> +     __u16 lasttrkid;        /* the last tracking ID we assigned */
>
> No longer needed.

agree (I must have read your patch too quickly).

>
>> +     __s8 inputmode;         /* InputMode HID feature, -1 if non-existent */
>> +     __u8 num_received;      /* how many contacts we received */
>> +     __u8 maxcontact;        /* expected last contact index */
>> +     bool curvalid;          /* is the current contact valid? */
>
> This value should probably be a mt_slot struct as well.

I was bothering too. Renaming the field (see above) may solve the
problem: we have curvalid (or curdata with the name I propose) which
is only needed for algorithm reasons, and touch that goes into
mt_buffer as it comes from the device.

>
>> +     struct mt_slot slots[0];        /* first slot */
>> +};
>> +
>> +struct mt_class {
>> +     int (*compute_slot)(struct mt_device *);
>> +     __u8 maxcontacts;
>> +};
>
> I imagine maxcontacts could be variable for devices within the same
> class. Perhaps it should be a member of the device instead? The
> resolution and fuzz could be added here as well.

resolution and fuzz: I let you implement it (when adding egalax or
3m). But isn't it something we can't get from the report descriptors?

concerning the device vs. class, currently, we have only seen classes
(one or more device sharing the same behavior), but we didn't bother
about resolution and fuzz.
It would be a shame to have to duplicate the mt_class (or mt_device),
one by vendorID/deviceID, as many devices may share the same
properties (at least those that have been manufactured by the same
company and that behave the same way: cando, stantum, etc...).
I also like the concept of default class as it will help people easily
adding devices.

>
>> +
>> +/* classes of device behavior */
>> +#define MT_CLS_DEFAULT 0
>> +#define MT_CLS_DUAL1 1
>> +
>> +/*
>> + * these device-dependent functions determine what slot corresponds
>> + * to a valid contact that was just read.
>> + */
>> +
>> +static int slot_is_contactid(struct mt_device *td)
>> +{
>> +     return td->curdata.contactid;
>> +}
>> +
>> +static int find_slot_from_contactid(struct mt_device *td)
>> +{
>> +     int i;
>> +     for (i = 0; i < td->mtclass->maxcontacts; ++i) {
>> +             if (td->slots[i].prev_valid &&
>
> Why prev_valid? Ought to be valid, right?

Because the code resets valid after each sending -> implementation dependent.

>
>> +                     td->slots[i].contactid == td->curdata.contactid)
>> +                     return i;
>> +     }
>> +     for (i = 0; i < td->mtclass->maxcontacts; ++i) {
>> +             if (!td->slots[i].valid && !td->slots[i].prev_valid)
>> +                     return i;
>
> Simplifaction here too without the prev_valid.

Related to current implementation too

>
>> +     }
>> +     return -1; /* should not occurs */
>
> And what should happen if it does?

good question. This would means that the device sent more touches that
it says in the report descriptor. It is ignored then.
Will add a comment.

>
>> +}
>> +
>> +struct mt_class mt_classes[] = {
>> +     { find_slot_from_contactid, 10 },     /* MT_CLS_DEFAULT */
>> +     { slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
>> +};
>
> It seems likely that this will become a device-specific list, rather than classes.

see above. Maybe we should add this patch with classes, and when
resolution and fuzz are added, we may turn it into devices if
required.

>
>> +
>> +static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
>> +             struct hid_field *field, struct hid_usage *usage)
>> +{
>> +     if (usage->hid == HID_DG_INPUTMODE) {
>> +             struct mt_device *td = hid_get_drvdata(hdev);
>> +             td->inputmode = field->report->id;
>> +     }
>> +}
>> +
>> +static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
>> +             struct hid_field *field, struct hid_usage *usage,
>> +             unsigned long **bit, int *max)
>> +{
>> +     struct mt_device *td = hid_get_drvdata(hdev);
>> +     switch (usage->hid & HID_USAGE_PAGE) {
>> +
>> +     case HID_UP_GENDESK:
>> +             switch (usage->hid) {
>> +             case HID_GD_X:
>> +                     hid_map_usage(hi, usage, bit, max,
>> +                                     EV_ABS, ABS_MT_POSITION_X);
>> +                     input_set_abs_params(hi->input, ABS_MT_POSITION_X,
>> +                                             field->logical_minimum,
>> +                                             field->logical_maximum, 0, 0);
>> +                     /* touchscreen emulation */
>> +                     input_set_abs_params(hi->input, ABS_X,
>> +                                             field->logical_minimum,
>> +                                             field->logical_maximum, 0, 0);
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>> +             case HID_GD_Y:
>> +                     hid_map_usage(hi, usage, bit, max,
>> +                                     EV_ABS, ABS_MT_POSITION_Y);
>> +                     input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
>> +                                             field->logical_minimum,
>> +                                             field->logical_maximum, 0, 0);
>> +                     /* touchscreen emulation */
>> +                     input_set_abs_params(hi->input, ABS_Y,
>> +                                             field->logical_minimum,
>> +                                             field->logical_maximum, 0, 0);
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>> +             }
>> +             return 0;
>
> Nice solution to the end-of-data issue. It would be good if the input
> setup was abstracted into a function like in hid-egalax, to simplify
> further additions.

thanks.
I was not very happy in making this abstraction for just one line of
code. I thought you could do it when adding the additions.

>
>> +
>> +     case HID_UP_DIGITIZER:
>> +             switch (usage->hid) {
>> +             case HID_DG_INRANGE:
>> +             case HID_DG_CONFIDENCE:
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>
> The inrange field has meaning for some drivers, I think these should be split.

if you want.

>
>> +             case HID_DG_TIPSWITCH:
>> +                     hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
>> +                     input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>> +             case HID_DG_CONTACTID:
>> +                     if (!hi->input->mt)
>
> This test can be dropped now.

will do

>
>> +                             input_mt_init_slots(hi->input,
>> +                                             td->mtclass->maxcontacts);
>
> Maxcontacts should probably take the hid description into account as well.

I don't understand your point here

>
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>> +             case HID_DG_TIPPRESSURE:
>> +                     hid_map_usage(hi, usage, bit, max,
>> +                                     EV_ABS, ABS_MT_PRESSURE);
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>
> And ABS_PRESSURE.

I thought that the mouse emulation was restricted to X and Y.

>
>> +             case HID_DG_CONTACTCOUNT:
>> +                     td->last_field_index = field->report->maxfield - 1;
>
> A fall-through here does not seem very useful.

ok

>
>> +             case HID_DG_CONTACTMAX:
>> +                     /* we don't set td->last_slot_field as contactcount and
>> +                      * contact max are global to the report */
>> +                     return -1;
>> +             }
>> +             /* let hid-input decide for the others */
>> +             return 0;
>> +
>> +     case 0xff000000:
>> +             /* we do not want to map these: no input-oriented meaning */
>> +             return -1;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
>> +             struct hid_field *field, struct hid_usage *usage,
>> +             unsigned long **bit, int *max)
>> +{
>> +     if (usage->type == EV_KEY || usage->type == EV_ABS)
>> +             set_bit(usage->type, hi->input->evbit);
>> +
>> +     return -1;
>> +}
>
> There are some hid drivers that need to setup fuzz in order to work
> properly. We should either add it to hid core or use the same bypass as
> in hid-egalax and hid-3m-pct.

Can I let you do this in further updates? (for the new devices and
those I sent, this works out of the box)

>
>> +
>> +/*
>> + * 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)
>> +{
>> +     if (td->curvalid) {
>> +             struct mt_slot *slot;
>> +             int slotnum = td->mtclass->compute_slot(td);
>> +
>> +             if (slotnum >= 0 && slotnum <= td->mtclass->maxcontacts - 1) {
>
> Please use "< maxcontacts".

oops

>
>> +                     slot = td->slots + slotnum;
>> +
>> +                     slot->valid = true;
>> +                     memcpy(slot, &(td->curdata), sizeof(struct mt_buffer));
>
> Valid is not always true for sure, and touch should be in here as
> well. A simple copy of the current data into the right slot will
> suffice - the validity will be copied too.

see curvalid/valid/prev_valid proposal above

>
>> +             }
>> +     }
>> +     td->num_received++;
>> +}
>> +
>> +
>> +/*
>> + * 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)
>> +{
>> +     int i;
>> +
>> +     for (i = 0; i < td->mtclass->maxcontacts; ++i) {
>> +             struct mt_slot *s = &(td->slots[i]);
>> +             if (!s->valid) {
>> +                     /*
>> +                      * this slot does not contain useful data,
>> +                      * notify its closure if necessary
>> +                      */
>> +                     if (s->prev_valid) {
>> +                             input_mt_slot(input, i);
>> +                             input_mt_report_slot_state(input,
>> +                                     MT_TOOL_FINGER, false);
>> +                             s->prev_valid = false;
>> +                     }
>> +                     continue;
>> +             }
>> +             if (!s->prev_valid)
>> +                     s->trkid = td->lasttrkid++;
>
> Most of the above can be removed.

Cypress device does not sends touch information when a touch is
released. This piece of code is required for devices that behave the
same way.

>
>> +
>> +             input_mt_slot(input, i);
>> +             input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
>
> "true" here should simply be slot->touch state.
>
>> +             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_PRESSURE, s->p);
>> +             s->prev_valid = true;
>> +             s->valid = false;
>
> Invalidating the data of a tracked slots seems wrong. If the device
> sends tracked data properly, no special consideration is needed - it
> will get cleared when appropriate. Other cases could be dealt with
> separately.

already discussed (pb in naming the fields I think)

>
>> +
>> +     }
>> +
>> +     input_mt_report_pointer_emulation(input, true);
>> +     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);
>> +
>> +     if (hid->claimed & HID_CLAIMED_INPUT) {
>> +             switch (usage->hid) {
>> +             case HID_DG_INRANGE:
>> +                     break;
>
> Egalax uses this field as validity.
>
>> +             case HID_DG_TIPSWITCH:
>> +                     td->curvalid = value;
>
> Most drivers seem to use this as touch state.

agree and that is how it is used in the current implementation. We
really should change the name.

>
>> +                     break;
>> +             case HID_DG_CONFIDENCE:
>> +                     break;
>> +             case HID_DG_CONTACTID:
>> +                     td->curdata.contactid = value;
>> +                     break;
>> +             case HID_DG_TIPPRESSURE:
>> +                     td->curdata.p = value;
>> +                     break;
>> +             case HID_GD_X:
>> +                     td->curdata.x = value;
>> +                     break;
>> +             case HID_GD_Y:
>> +                     td->curdata.y = value;
>> +                     break;
>> +             case HID_DG_CONTACTCOUNT:
>> +                     /*
>> +                      * We must not overwrite the previous value (some
>> +                      * devices send one sequence splitted over several
>> +                      * messages)
>> +                      */
>> +                     if (value)
>> +                             td->maxcontact = value - 1;
>
> Is td->maxcontact ever reset? And why not num_expected or something
> instead of maxcontact - odd semantics.

maxcontact is not reset (not needed as it is sent in each report).
Concerning the name, agree.

>
>> +                     break;
>> +             case HID_DG_CONTACTMAX:
>> +                     break;
>
> This one was filtered already.

ok

>
>> +
>> +             default:
>> +                     /* fallback to the generic hidinput handling */
>> +                     return 0;
>> +             }
>> +     }
>> +
>> +     if (usage->hid == td->last_slot_field)
>> +             mt_complete_slot(td);
>> +
>> +     if (field->index == td->last_field_index
>> +             && td->num_received > td->maxcontact) {
>> +             struct input_dev *input = field->hidinput->input;
>
> No need to declare a temp variable for one access.

bad refactoring, will change

>
>> +             mt_emit_event(td, input);
>
> Resetting expected countact count here would be good.

if you want, but not really needed.

>
>> +     }
>> +
>> +     /* we have handled the hidinput part, now remains hiddev */
>> +     if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
>> +             hid->hiddev_hid_event(hid, field, usage, value);
>> +
>> +     return 1;
>> +}
>> +
>> +static void mt_set_input_mode(struct hid_device *hdev)
>> +{
>> +     struct mt_device *td = hid_get_drvdata(hdev);
>> +     struct hid_report *r;
>> +     struct hid_report_enum *re;
>> +
>> +     if (td->inputmode < 0)
>> +             return;
>> +
>> +     re = &(hdev->report_enum[HID_FEATURE_REPORT]);
>> +     r = re->report_id_hash[td->inputmode];
>> +     if (r) {
>> +             r->field[0]->value[0] = 0x02;
>> +             usbhid_submit_report(hdev, r, USB_DIR_OUT);
>> +     }
>> +}
>
> Nice reduction.

thanks ;)

Cheers,
Benjamin

>
>> +
>> +static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
>> +{
>> +     int ret;
>> +     struct mt_device *td;
>> +     struct mt_class *mtclass = mt_classes + id->driver_data;
>> +
>> +     /* This allows the driver to correctly support devices
>> +      * that emit events over several HID messages.
>> +      */
>> +     hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
>> +
>> +     td = kzalloc(sizeof(struct mt_device) +
>> +                             mtclass->maxcontacts * sizeof(struct mt_slot),
>> +                             GFP_KERNEL);
>> +     if (!td) {
>> +             dev_err(&hdev->dev, "cannot allocate multitouch data\n");
>> +             return -ENOMEM;
>> +     }
>> +     td->mtclass = mtclass;
>> +     td->inputmode = -1;
>> +     hid_set_drvdata(hdev, td);
>> +
>> +     ret = hid_parse(hdev);
>> +     if (ret != 0)
>> +             goto fail;
>> +
>> +     ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
>> +     if (ret != 0)
>> +             goto fail;
>> +
>> +     mt_set_input_mode(hdev);
>> +
>> +     return 0;
>> +
>> +fail:
>> +     kfree(td);
>> +     return ret;
>> +}
>> +
>> +#ifdef CONFIG_PM
>> +static int mt_reset_resume(struct hid_device *hdev)
>> +{
>> +     mt_set_input_mode(hdev);
>> +     return 0;
>> +}
>> +#endif
>> +
>> +static void mt_remove(struct hid_device *hdev)
>> +{
>> +     struct mt_device *td = hid_get_drvdata(hdev);
>> +     hid_hw_stop(hdev);
>> +     kfree(td);
>> +     hid_set_drvdata(hdev, NULL);
>> +}
>> +
>> +static const struct hid_device_id mt_devices[] = {
>> +
>> +     /* PixCir-based panels */
>> +     { .driver_data = MT_CLS_DUAL1,
>> +             HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
>> +                     USB_DEVICE_ID_HANVON_MULTITOUCH) },
>> +     { .driver_data = MT_CLS_DUAL1,
>> +             HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
>> +                     USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
>> +
>> +     { }
>> +};
>> +MODULE_DEVICE_TABLE(hid, mt_devices);
>> +
>> +static const struct hid_usage_id mt_grabbed_usages[] = {
>> +     { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
>> +     { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
>> +};
>> +
>> +static struct hid_driver mt_driver = {
>> +     .name = "hid-multitouch",
>> +     .id_table = mt_devices,
>> +     .probe = mt_probe,
>> +     .remove = mt_remove,
>> +     .input_mapping = mt_input_mapping,
>> +     .input_mapped = mt_input_mapped,
>> +     .feature_mapping = mt_feature_mapping,
>> +     .usage_table = mt_grabbed_usages,
>> +     .event = mt_event,
>> +#ifdef CONFIG_PM
>> +     .reset_resume = mt_reset_resume,
>> +#endif
>> +};
>> +
>> +static int __init mt_init(void)
>> +{
>> +     return hid_register_driver(&mt_driver);
>> +}
>> +
>> +static void __exit mt_exit(void)
>> +{
>> +     hid_unregister_driver(&mt_driver);
>> +}
>> +
>> +module_init(mt_init);
>> +module_exit(mt_exit);
>> --
>> 1.7.3.4
>>
>
> Thanks,
> Henrik
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
@ 2011-01-07  9:38       ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-07  9:38 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Thu, Jan 6, 2011 at 6:25 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
> On Wed, Jan 05, 2011 at 06:27:41PM +0100, Benjamin Tissoires wrote:
>> Created a driver for PixCir based dual-touch panels, including the one
>> in the Hanvon tablet.  This is done in a code structure aimed at unifying
>> support for several existing HID multitouch panels.
>>
>> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
>> Signed-off-by: Stéphane Chatty <chatty@enac.fr>
>> ---
>>  drivers/hid/Kconfig          |    6 +
>>  drivers/hid/Makefile         |    1 +
>>  drivers/hid/hid-core.c       |    2 +
>>  drivers/hid/hid-ids.h        |    4 +
>>  drivers/hid/hid-multitouch.c |  434 ++++++++++++++++++++++++++++++++++++++++++
>>  5 files changed, 447 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/hid/hid-multitouch.c
>>
>> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
>> index 401acec..6519981 100644
>> --- a/drivers/hid/Kconfig
>> +++ b/drivers/hid/Kconfig
>> @@ -285,6 +285,12 @@ config HID_MONTEREY
>>       ---help---
>>       Support for Monterey Genius KB29E.
>>
>> +config HID_MULTITOUCH
>> +     tristate "HID Multitouch panels"
>> +     depends on USB_HID
>> +     ---help---
>> +     Generic support for HID multitouch panels.
>> +
>
> Please provide a bit more information under this config option. The
> usual "what should I do", and roughly what devices are supported.

Will try, but don't hesitate to send one if you feel in a good mood for writing.

I can propose:

+        ---help---
+          Generic support for HID multitouch panels.
+          Currently supported panels are:
+          - PixCir touchscreen
+          - Cypress TrueTouch
+          - 'Sensing Win7-TwoFinger' panel by GeneralTouch

>
>>  config HID_NTRIG
>>       tristate "N-Trig touch screen"
>>       depends on USB_HID
>> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
>> index c335605..ec991d4 100644
>> --- a/drivers/hid/Makefile
>> +++ b/drivers/hid/Makefile
>> @@ -46,6 +46,7 @@ obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
>>  obj-$(CONFIG_HID_MICROSOFT)  += hid-microsoft.o
>>  obj-$(CONFIG_HID_MONTEREY)   += hid-monterey.o
>>  obj-$(CONFIG_HID_MOSART)     += hid-mosart.o
>> +obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o
>>  obj-$(CONFIG_HID_NTRIG)              += hid-ntrig.o
>>  obj-$(CONFIG_HID_ORTEK)              += hid-ortek.o
>>  obj-$(CONFIG_HID_PRODIKEYS)  += hid-prodikeys.o
>> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
>> index 88668ae..2b4d9b9 100644
>> --- a/drivers/hid/hid-core.c
>> +++ b/drivers/hid/hid-core.c
>> @@ -1286,6 +1286,7 @@ static const struct hid_device_id hid_blacklist[] = {
>>       { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
>> +     { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
>> @@ -1312,6 +1313,7 @@ static const struct hid_device_id hid_blacklist[] = {
>>       { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
>> +     { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
>>       { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
>> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
>> index 0f150c7..17b444b 100644
>> --- a/drivers/hid/hid-ids.h
>> +++ b/drivers/hid/hid-ids.h
>> @@ -134,6 +134,7 @@
>>  #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2    0x5577
>>
>>  #define USB_VENDOR_ID_CANDO          0x2087
>> +#define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703
>>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH      0x0a01
>>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
>>  #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
>> @@ -306,6 +307,9 @@
>>  #define USB_DEVICE_ID_HANWANG_TABLET_FIRST   0x5000
>>  #define USB_DEVICE_ID_HANWANG_TABLET_LAST    0x8fff
>>
>> +#define USB_VENDOR_ID_HANVON         0x20b3
>> +#define USB_DEVICE_ID_HANVON_MULTITOUCH      0x0a18
>> +
>>  #define USB_VENDOR_ID_HAPP           0x078b
>>  #define USB_DEVICE_ID_UGCI_DRIVING   0x0010
>>  #define USB_DEVICE_ID_UGCI_FLYING    0x0020
>> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
>> new file mode 100644
>> index 0000000..aea0e32
>> --- /dev/null
>> +++ b/drivers/hid/hid-multitouch.c
>> @@ -0,0 +1,434 @@
>> +/*
>> + *  HID driver for multitouch panels
>> + *
>> + *  Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr>
>> + *  Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
>> + *  Copyright (c) 2010-2011 Enac
>> + *
>> + */
>> +
>> +/*
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License as published by the Free
>> + * Software Foundation; either version 2 of the License, or (at your option)
>> + * any later version.
>> + */
>> +
>> +#include <linux/device.h>
>> +#include <linux/hid.h>
>> +#include <linux/module.h>
>> +#include <linux/slab.h>
>> +#include <linux/usb.h>
>> +#include <linux/input/mt.h>
>> +#include "usbhid/usbhid.h"
>> +
>> +
>> +MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
>> +MODULE_DESCRIPTION("HID multitouch panels");
>> +MODULE_LICENSE("GPL");
>> +
>> +#include "hid-ids.h"
>> +
>> +
>> +struct mt_slot {
>> +     __s32 x, y, p;
>> +     __s32 contactid;        /* the device ContactID assigned to this slot */
>> +     __u16 trkid;    /* the tracking ID that was assigned to this slot */
>> +     bool valid;     /* did we just get valid contact data for this slot? */
>> +     bool prev_valid;/* was this slot previously valid/active? */
>> +};
>
> The trkid and prev_valid are no longer needed. The touch state seems to be missing.

Concerning the trkid, agree.
I can assure you that prev_valid is needed by at least the Cypress
device. In a sense, it has the same problem than mt protocol A: it
does not send the release information except when the last finger has
been released. This gymnastic is thus required.

I think that the misunderstanding comes from the name. We have this 2
flags (valid and prev_valid) to tell whether the device sent data
during this report or the previous one. It's not the same meaning that
the touch you're talking about. For Cypress device, those 2 flags are
mandatory.

Maybe introducing data + prev_data + touch (3 flags instead of 2->
touch can go into mt_buffer, and data and prev_data only in mt_slot as
they are not given by the device) is clearer.


>
>> +
>> +struct mt_buffer {
>> +     __s32 x, y, p;
>> +     __s32 contactid;        /* the device ContactID assigned to this slot */
>> +};
>
> The only different to mt_slot are the valid and touch field, which is
> also needed for incoming data. I'd say those should be merged.
>

Well, the point is that the buffer and the slot have 2 different meanings:
one is the incoming data, the other is the processed data. It strikes
us to have only one struct as the slot contains extra information for
it to be processed.

>> +
>> +struct mt_device {
>> +     struct mt_buffer curdata;       /* placeholder of incoming data */
>> +     struct mt_class *mtclass;       /* our mt device class */
>> +     unsigned last_field_index;      /* last field index of the report */
>> +     unsigned last_slot_field;       /* the last field of a slot */
>> +     __u16 lasttrkid;        /* the last tracking ID we assigned */
>
> No longer needed.

agree (I must have read your patch too quickly).

>
>> +     __s8 inputmode;         /* InputMode HID feature, -1 if non-existent */
>> +     __u8 num_received;      /* how many contacts we received */
>> +     __u8 maxcontact;        /* expected last contact index */
>> +     bool curvalid;          /* is the current contact valid? */
>
> This value should probably be a mt_slot struct as well.

I was bothering too. Renaming the field (see above) may solve the
problem: we have curvalid (or curdata with the name I propose) which
is only needed for algorithm reasons, and touch that goes into
mt_buffer as it comes from the device.

>
>> +     struct mt_slot slots[0];        /* first slot */
>> +};
>> +
>> +struct mt_class {
>> +     int (*compute_slot)(struct mt_device *);
>> +     __u8 maxcontacts;
>> +};
>
> I imagine maxcontacts could be variable for devices within the same
> class. Perhaps it should be a member of the device instead? The
> resolution and fuzz could be added here as well.

resolution and fuzz: I let you implement it (when adding egalax or
3m). But isn't it something we can't get from the report descriptors?

concerning the device vs. class, currently, we have only seen classes
(one or more device sharing the same behavior), but we didn't bother
about resolution and fuzz.
It would be a shame to have to duplicate the mt_class (or mt_device),
one by vendorID/deviceID, as many devices may share the same
properties (at least those that have been manufactured by the same
company and that behave the same way: cando, stantum, etc...).
I also like the concept of default class as it will help people easily
adding devices.

>
>> +
>> +/* classes of device behavior */
>> +#define MT_CLS_DEFAULT 0
>> +#define MT_CLS_DUAL1 1
>> +
>> +/*
>> + * these device-dependent functions determine what slot corresponds
>> + * to a valid contact that was just read.
>> + */
>> +
>> +static int slot_is_contactid(struct mt_device *td)
>> +{
>> +     return td->curdata.contactid;
>> +}
>> +
>> +static int find_slot_from_contactid(struct mt_device *td)
>> +{
>> +     int i;
>> +     for (i = 0; i < td->mtclass->maxcontacts; ++i) {
>> +             if (td->slots[i].prev_valid &&
>
> Why prev_valid? Ought to be valid, right?

Because the code resets valid after each sending -> implementation dependent.

>
>> +                     td->slots[i].contactid == td->curdata.contactid)
>> +                     return i;
>> +     }
>> +     for (i = 0; i < td->mtclass->maxcontacts; ++i) {
>> +             if (!td->slots[i].valid && !td->slots[i].prev_valid)
>> +                     return i;
>
> Simplifaction here too without the prev_valid.

Related to current implementation too

>
>> +     }
>> +     return -1; /* should not occurs */
>
> And what should happen if it does?

good question. This would means that the device sent more touches that
it says in the report descriptor. It is ignored then.
Will add a comment.

>
>> +}
>> +
>> +struct mt_class mt_classes[] = {
>> +     { find_slot_from_contactid, 10 },     /* MT_CLS_DEFAULT */
>> +     { slot_is_contactid, 2 },             /* MT_CLS_DUAL1 */
>> +};
>
> It seems likely that this will become a device-specific list, rather than classes.

see above. Maybe we should add this patch with classes, and when
resolution and fuzz are added, we may turn it into devices if
required.

>
>> +
>> +static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
>> +             struct hid_field *field, struct hid_usage *usage)
>> +{
>> +     if (usage->hid == HID_DG_INPUTMODE) {
>> +             struct mt_device *td = hid_get_drvdata(hdev);
>> +             td->inputmode = field->report->id;
>> +     }
>> +}
>> +
>> +static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
>> +             struct hid_field *field, struct hid_usage *usage,
>> +             unsigned long **bit, int *max)
>> +{
>> +     struct mt_device *td = hid_get_drvdata(hdev);
>> +     switch (usage->hid & HID_USAGE_PAGE) {
>> +
>> +     case HID_UP_GENDESK:
>> +             switch (usage->hid) {
>> +             case HID_GD_X:
>> +                     hid_map_usage(hi, usage, bit, max,
>> +                                     EV_ABS, ABS_MT_POSITION_X);
>> +                     input_set_abs_params(hi->input, ABS_MT_POSITION_X,
>> +                                             field->logical_minimum,
>> +                                             field->logical_maximum, 0, 0);
>> +                     /* touchscreen emulation */
>> +                     input_set_abs_params(hi->input, ABS_X,
>> +                                             field->logical_minimum,
>> +                                             field->logical_maximum, 0, 0);
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>> +             case HID_GD_Y:
>> +                     hid_map_usage(hi, usage, bit, max,
>> +                                     EV_ABS, ABS_MT_POSITION_Y);
>> +                     input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
>> +                                             field->logical_minimum,
>> +                                             field->logical_maximum, 0, 0);
>> +                     /* touchscreen emulation */
>> +                     input_set_abs_params(hi->input, ABS_Y,
>> +                                             field->logical_minimum,
>> +                                             field->logical_maximum, 0, 0);
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>> +             }
>> +             return 0;
>
> Nice solution to the end-of-data issue. It would be good if the input
> setup was abstracted into a function like in hid-egalax, to simplify
> further additions.

thanks.
I was not very happy in making this abstraction for just one line of
code. I thought you could do it when adding the additions.

>
>> +
>> +     case HID_UP_DIGITIZER:
>> +             switch (usage->hid) {
>> +             case HID_DG_INRANGE:
>> +             case HID_DG_CONFIDENCE:
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>
> The inrange field has meaning for some drivers, I think these should be split.

if you want.

>
>> +             case HID_DG_TIPSWITCH:
>> +                     hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
>> +                     input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>> +             case HID_DG_CONTACTID:
>> +                     if (!hi->input->mt)
>
> This test can be dropped now.

will do

>
>> +                             input_mt_init_slots(hi->input,
>> +                                             td->mtclass->maxcontacts);
>
> Maxcontacts should probably take the hid description into account as well.

I don't understand your point here

>
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>> +             case HID_DG_TIPPRESSURE:
>> +                     hid_map_usage(hi, usage, bit, max,
>> +                                     EV_ABS, ABS_MT_PRESSURE);
>> +                     td->last_slot_field = usage->hid;
>> +                     return 1;
>
> And ABS_PRESSURE.

I thought that the mouse emulation was restricted to X and Y.

>
>> +             case HID_DG_CONTACTCOUNT:
>> +                     td->last_field_index = field->report->maxfield - 1;
>
> A fall-through here does not seem very useful.

ok

>
>> +             case HID_DG_CONTACTMAX:
>> +                     /* we don't set td->last_slot_field as contactcount and
>> +                      * contact max are global to the report */
>> +                     return -1;
>> +             }
>> +             /* let hid-input decide for the others */
>> +             return 0;
>> +
>> +     case 0xff000000:
>> +             /* we do not want to map these: no input-oriented meaning */
>> +             return -1;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
>> +             struct hid_field *field, struct hid_usage *usage,
>> +             unsigned long **bit, int *max)
>> +{
>> +     if (usage->type == EV_KEY || usage->type == EV_ABS)
>> +             set_bit(usage->type, hi->input->evbit);
>> +
>> +     return -1;
>> +}
>
> There are some hid drivers that need to setup fuzz in order to work
> properly. We should either add it to hid core or use the same bypass as
> in hid-egalax and hid-3m-pct.

Can I let you do this in further updates? (for the new devices and
those I sent, this works out of the box)

>
>> +
>> +/*
>> + * 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)
>> +{
>> +     if (td->curvalid) {
>> +             struct mt_slot *slot;
>> +             int slotnum = td->mtclass->compute_slot(td);
>> +
>> +             if (slotnum >= 0 && slotnum <= td->mtclass->maxcontacts - 1) {
>
> Please use "< maxcontacts".

oops

>
>> +                     slot = td->slots + slotnum;
>> +
>> +                     slot->valid = true;
>> +                     memcpy(slot, &(td->curdata), sizeof(struct mt_buffer));
>
> Valid is not always true for sure, and touch should be in here as
> well. A simple copy of the current data into the right slot will
> suffice - the validity will be copied too.

see curvalid/valid/prev_valid proposal above

>
>> +             }
>> +     }
>> +     td->num_received++;
>> +}
>> +
>> +
>> +/*
>> + * 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)
>> +{
>> +     int i;
>> +
>> +     for (i = 0; i < td->mtclass->maxcontacts; ++i) {
>> +             struct mt_slot *s = &(td->slots[i]);
>> +             if (!s->valid) {
>> +                     /*
>> +                      * this slot does not contain useful data,
>> +                      * notify its closure if necessary
>> +                      */
>> +                     if (s->prev_valid) {
>> +                             input_mt_slot(input, i);
>> +                             input_mt_report_slot_state(input,
>> +                                     MT_TOOL_FINGER, false);
>> +                             s->prev_valid = false;
>> +                     }
>> +                     continue;
>> +             }
>> +             if (!s->prev_valid)
>> +                     s->trkid = td->lasttrkid++;
>
> Most of the above can be removed.

Cypress device does not sends touch information when a touch is
released. This piece of code is required for devices that behave the
same way.

>
>> +
>> +             input_mt_slot(input, i);
>> +             input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
>
> "true" here should simply be slot->touch state.
>
>> +             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_PRESSURE, s->p);
>> +             s->prev_valid = true;
>> +             s->valid = false;
>
> Invalidating the data of a tracked slots seems wrong. If the device
> sends tracked data properly, no special consideration is needed - it
> will get cleared when appropriate. Other cases could be dealt with
> separately.

already discussed (pb in naming the fields I think)

>
>> +
>> +     }
>> +
>> +     input_mt_report_pointer_emulation(input, true);
>> +     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);
>> +
>> +     if (hid->claimed & HID_CLAIMED_INPUT) {
>> +             switch (usage->hid) {
>> +             case HID_DG_INRANGE:
>> +                     break;
>
> Egalax uses this field as validity.
>
>> +             case HID_DG_TIPSWITCH:
>> +                     td->curvalid = value;
>
> Most drivers seem to use this as touch state.

agree and that is how it is used in the current implementation. We
really should change the name.

>
>> +                     break;
>> +             case HID_DG_CONFIDENCE:
>> +                     break;
>> +             case HID_DG_CONTACTID:
>> +                     td->curdata.contactid = value;
>> +                     break;
>> +             case HID_DG_TIPPRESSURE:
>> +                     td->curdata.p = value;
>> +                     break;
>> +             case HID_GD_X:
>> +                     td->curdata.x = value;
>> +                     break;
>> +             case HID_GD_Y:
>> +                     td->curdata.y = value;
>> +                     break;
>> +             case HID_DG_CONTACTCOUNT:
>> +                     /*
>> +                      * We must not overwrite the previous value (some
>> +                      * devices send one sequence splitted over several
>> +                      * messages)
>> +                      */
>> +                     if (value)
>> +                             td->maxcontact = value - 1;
>
> Is td->maxcontact ever reset? And why not num_expected or something
> instead of maxcontact - odd semantics.

maxcontact is not reset (not needed as it is sent in each report).
Concerning the name, agree.

>
>> +                     break;
>> +             case HID_DG_CONTACTMAX:
>> +                     break;
>
> This one was filtered already.

ok

>
>> +
>> +             default:
>> +                     /* fallback to the generic hidinput handling */
>> +                     return 0;
>> +             }
>> +     }
>> +
>> +     if (usage->hid == td->last_slot_field)
>> +             mt_complete_slot(td);
>> +
>> +     if (field->index == td->last_field_index
>> +             && td->num_received > td->maxcontact) {
>> +             struct input_dev *input = field->hidinput->input;
>
> No need to declare a temp variable for one access.

bad refactoring, will change

>
>> +             mt_emit_event(td, input);
>
> Resetting expected countact count here would be good.

if you want, but not really needed.

>
>> +     }
>> +
>> +     /* we have handled the hidinput part, now remains hiddev */
>> +     if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
>> +             hid->hiddev_hid_event(hid, field, usage, value);
>> +
>> +     return 1;
>> +}
>> +
>> +static void mt_set_input_mode(struct hid_device *hdev)
>> +{
>> +     struct mt_device *td = hid_get_drvdata(hdev);
>> +     struct hid_report *r;
>> +     struct hid_report_enum *re;
>> +
>> +     if (td->inputmode < 0)
>> +             return;
>> +
>> +     re = &(hdev->report_enum[HID_FEATURE_REPORT]);
>> +     r = re->report_id_hash[td->inputmode];
>> +     if (r) {
>> +             r->field[0]->value[0] = 0x02;
>> +             usbhid_submit_report(hdev, r, USB_DIR_OUT);
>> +     }
>> +}
>
> Nice reduction.

thanks ;)

Cheers,
Benjamin

>
>> +
>> +static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
>> +{
>> +     int ret;
>> +     struct mt_device *td;
>> +     struct mt_class *mtclass = mt_classes + id->driver_data;
>> +
>> +     /* This allows the driver to correctly support devices
>> +      * that emit events over several HID messages.
>> +      */
>> +     hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
>> +
>> +     td = kzalloc(sizeof(struct mt_device) +
>> +                             mtclass->maxcontacts * sizeof(struct mt_slot),
>> +                             GFP_KERNEL);
>> +     if (!td) {
>> +             dev_err(&hdev->dev, "cannot allocate multitouch data\n");
>> +             return -ENOMEM;
>> +     }
>> +     td->mtclass = mtclass;
>> +     td->inputmode = -1;
>> +     hid_set_drvdata(hdev, td);
>> +
>> +     ret = hid_parse(hdev);
>> +     if (ret != 0)
>> +             goto fail;
>> +
>> +     ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
>> +     if (ret != 0)
>> +             goto fail;
>> +
>> +     mt_set_input_mode(hdev);
>> +
>> +     return 0;
>> +
>> +fail:
>> +     kfree(td);
>> +     return ret;
>> +}
>> +
>> +#ifdef CONFIG_PM
>> +static int mt_reset_resume(struct hid_device *hdev)
>> +{
>> +     mt_set_input_mode(hdev);
>> +     return 0;
>> +}
>> +#endif
>> +
>> +static void mt_remove(struct hid_device *hdev)
>> +{
>> +     struct mt_device *td = hid_get_drvdata(hdev);
>> +     hid_hw_stop(hdev);
>> +     kfree(td);
>> +     hid_set_drvdata(hdev, NULL);
>> +}
>> +
>> +static const struct hid_device_id mt_devices[] = {
>> +
>> +     /* PixCir-based panels */
>> +     { .driver_data = MT_CLS_DUAL1,
>> +             HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
>> +                     USB_DEVICE_ID_HANVON_MULTITOUCH) },
>> +     { .driver_data = MT_CLS_DUAL1,
>> +             HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
>> +                     USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
>> +
>> +     { }
>> +};
>> +MODULE_DEVICE_TABLE(hid, mt_devices);
>> +
>> +static const struct hid_usage_id mt_grabbed_usages[] = {
>> +     { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
>> +     { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
>> +};
>> +
>> +static struct hid_driver mt_driver = {
>> +     .name = "hid-multitouch",
>> +     .id_table = mt_devices,
>> +     .probe = mt_probe,
>> +     .remove = mt_remove,
>> +     .input_mapping = mt_input_mapping,
>> +     .input_mapped = mt_input_mapped,
>> +     .feature_mapping = mt_feature_mapping,
>> +     .usage_table = mt_grabbed_usages,
>> +     .event = mt_event,
>> +#ifdef CONFIG_PM
>> +     .reset_resume = mt_reset_resume,
>> +#endif
>> +};
>> +
>> +static int __init mt_init(void)
>> +{
>> +     return hid_register_driver(&mt_driver);
>> +}
>> +
>> +static void __exit mt_exit(void)
>> +{
>> +     hid_unregister_driver(&mt_driver);
>> +}
>> +
>> +module_init(mt_init);
>> +module_exit(mt_exit);
>> --
>> 1.7.3.4
>>
>
> Thanks,
> Henrik
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
  2011-01-07  1:14         ` Dmitry Torokhov
  (?)
@ 2011-01-07  9:41         ` Jiri Kosina
  2011-01-07  9:48             ` Benjamin Tissoires
  -1 siblings, 1 reply; 56+ messages in thread
From: Jiri Kosina @ 2011-01-07  9:41 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Benjamin Tissoires, Henrik Rydberg, Stephane Chatty, linux-input,
	linux-kernel

On Thu, 6 Jan 2011, Dmitry Torokhov wrote:

> > In case the patchset doesn't impose danger of regressions for already 
> > existing devices, we could merge this new 'unified' driver only for newly 
> > supported devices, and finish the unification in 2.6.39.
> 
> Yep, let's merge the dirver and all new devices in this round and then
> get ready to convert already supported devices in next window.

Fully agreed, as I have written elsewhere already.

Benjamin, when do you expect to have the patches for .38 ready? The merge 
window is already open, so that I could schedule the merges properly.

Thanks,

-- 
Jiri Kosina
SUSE Labs, Novell Inc.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 01/10] hid: add feature_mapping callback
  2011-01-06 16:22   ` Henrik Rydberg
@ 2011-01-07  9:44     ` Benjamin Tissoires
  2011-01-07 10:18       ` Henrik Rydberg
  0 siblings, 1 reply; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-07  9:44 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Thu, Jan 6, 2011 at 5:22 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
> On Wed, Jan 05, 2011 at 06:27:39PM +0100, Benjamin Tissoires wrote:
>> Currently hid doesn't export the features it knows to the specific modules.
>> Some information can be really important in such features: MosArt and
>> Cypress devices are by default not in a multitouch mode.
>> We have to send the value 2 on the right feature.
>>
>> This patch exports to the module the features report so they can find the
>> right feature to set up the correct mode.
>>
>> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
>> ---
>>  drivers/hid/hid-input.c |   10 +++++++++-
>>  include/linux/hid.h     |    4 ++++
>>  2 files changed, 13 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
>> index bb0b365..07d8cb2 100644
>> --- a/drivers/hid/hid-input.c
>> +++ b/drivers/hid/hid-input.c
>> @@ -287,6 +287,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
>>               goto ignore;
>>       }
>>
>> +     if (field->report_type == HID_FEATURE_REPORT) {
>> +             if (device->driver->feature_mapping) {
>> +                     device->driver->feature_mapping(device, hidinput, field,
>> +                                usage);
>> +             }
>> +             goto ignore;
>> +     }
>> +
>>       if (device->driver->input_mapping) {
>>               int ret = device->driver->input_mapping(device, hidinput, field,
>>                               usage, &bit, &max);
>> @@ -836,7 +844,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
>>       struct hid_input *hidinput = NULL;
>>       struct input_dev *input_dev;
>>       int i, j, k;
>> -     int max_report_type = HID_OUTPUT_REPORT;
>> +     int max_report_type = HID_FEATURE_REPORT;
>
> Doing it this way conflicts with the HID_QUIRK_SKIP_OUTPUT_REPORTS quirk.


Do you agree on this way? (will send the patch in the next version)

@@ -834,11 +842,10 @@ int hidinput_connect(struct hid_device *hid,
unsigned int force)
 {
 	struct hid_report *report;
 	struct hid_input *hidinput = NULL;
 	struct input_dev *input_dev;
 	int i, j, k;
-	int max_report_type = HID_OUTPUT_REPORT;

 	INIT_LIST_HEAD(&hid->inputs);

 	if (!force) {
 		for (i = 0; i < hid->maxcollection; i++) {
@@ -851,14 +858,14 @@ int hidinput_connect(struct hid_device *hid,
unsigned int force)

 		if (i == hid->maxcollection)
 			return -1;
 	}

-	if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
-		max_report_type = HID_INPUT_REPORT;
+	for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++)
+		if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
+			continue;

-	for (k = HID_INPUT_REPORT; k <= max_report_type; k++)
 		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {

 			if (!report->maxfield)
 				continue;

Cheers,
Benjamin
>
>>
>>       INIT_LIST_HEAD(&hid->inputs);
>>
>> diff --git a/include/linux/hid.h b/include/linux/hid.h
>> index bb0f56f..75303b0 100644
>> --- a/include/linux/hid.h
>> +++ b/include/linux/hid.h
>> @@ -593,6 +593,7 @@ struct hid_usage_id {
>>   * @report_fixup: called before report descriptor parsing (NULL means nop)
>>   * @input_mapping: invoked on input registering before mapping an usage
>>   * @input_mapped: invoked on input registering after mapping an usage
>> + * @feature_mapping: invoked on feature registering
>>   * @suspend: invoked on suspend (NULL means nop)
>>   * @resume: invoked on resume if device was not reset (NULL means nop)
>>   * @reset_resume: invoked on resume if device was reset (NULL means nop)
>> @@ -636,6 +637,9 @@ struct hid_driver {
>>       int (*input_mapped)(struct hid_device *hdev,
>>                       struct hid_input *hidinput, struct hid_field *field,
>>                       struct hid_usage *usage, unsigned long **bit, int *max);
>> +     void (*feature_mapping)(struct hid_device *hdev,
>> +                     struct hid_input *hidinput, struct hid_field *field,
>> +                     struct hid_usage *usage);
>>  #ifdef CONFIG_PM
>>       int (*suspend)(struct hid_device *hdev, pm_message_t message);
>>       int (*resume)(struct hid_device *hdev);
>
> Thanks,
> Henrik
>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
  2011-01-07  9:41         ` Jiri Kosina
@ 2011-01-07  9:48             ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-07  9:48 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Dmitry Torokhov, Henrik Rydberg, Stephane Chatty, linux-input,
	linux-kernel

On Fri, Jan 7, 2011 at 10:41 AM, Jiri Kosina <jkosina@suse.cz> wrote:
> On Thu, 6 Jan 2011, Dmitry Torokhov wrote:
>
>> > In case the patchset doesn't impose danger of regressions for already
>> > existing devices, we could merge this new 'unified' driver only for newly
>> > supported devices, and finish the unification in 2.6.39.
>>
>> Yep, let's merge the dirver and all new devices in this round and then
>> get ready to convert already supported devices in next window.
>
> Fully agreed, as I have written elsewhere already.
>
> Benjamin, when do you expect to have the patches for .38 ready? The merge
> window is already open, so that I could schedule the merges properly.

I'm doing my best to have the v3 today with only the 3 new devices.
After, we may have to find a consensus for the not ideal
implementation.

Cheers,
Benjamin


>
> Thanks,
>
> --
> Jiri Kosina
> SUSE Labs, Novell Inc.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
@ 2011-01-07  9:48             ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-07  9:48 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Dmitry Torokhov, Henrik Rydberg, Stephane Chatty, linux-input,
	linux-kernel

On Fri, Jan 7, 2011 at 10:41 AM, Jiri Kosina <jkosina@suse.cz> wrote:
> On Thu, 6 Jan 2011, Dmitry Torokhov wrote:
>
>> > In case the patchset doesn't impose danger of regressions for already
>> > existing devices, we could merge this new 'unified' driver only for newly
>> > supported devices, and finish the unification in 2.6.39.
>>
>> Yep, let's merge the dirver and all new devices in this round and then
>> get ready to convert already supported devices in next window.
>
> Fully agreed, as I have written elsewhere already.
>
> Benjamin, when do you expect to have the patches for .38 ready? The merge
> window is already open, so that I could schedule the merges properly.

I'm doing my best to have the v3 today with only the 3 new devices.
After, we may have to find a consensus for the not ideal
implementation.

Cheers,
Benjamin


>
> Thanks,
>
> --
> Jiri Kosina
> SUSE Labs, Novell Inc.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification
  2011-01-07  9:48             ` Benjamin Tissoires
  (?)
@ 2011-01-07 10:03             ` Jiri Kosina
  -1 siblings, 0 replies; 56+ messages in thread
From: Jiri Kosina @ 2011-01-07 10:03 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Dmitry Torokhov, Henrik Rydberg, Stephane Chatty, linux-input,
	linux-kernel

On Fri, 7 Jan 2011, Benjamin Tissoires wrote:

> >> > In case the patchset doesn't impose danger of regressions for already
> >> > existing devices, we could merge this new 'unified' driver only for newly
> >> > supported devices, and finish the unification in 2.6.39.
> >>
> >> Yep, let's merge the dirver and all new devices in this round and then
> >> get ready to convert already supported devices in next window.
> >
> > Fully agreed, as I have written elsewhere already.
> >
> > Benjamin, when do you expect to have the patches for .38 ready? The merge
> > window is already open, so that I could schedule the merges properly.
> 
> I'm doing my best to have the v3 today with only the 3 new devices.
> After, we may have to find a consensus for the not ideal
> implementation.

That would be excellent, and will allow me to prepare the merge over the 
weekend.

Thanks,

-- 
Jiri Kosina
SUSE Labs, Novell Inc.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 01/10] hid: add feature_mapping callback
  2011-01-07  9:44     ` Benjamin Tissoires
@ 2011-01-07 10:18       ` Henrik Rydberg
  2011-01-07 11:12           ` Benjamin Tissoires
  0 siblings, 1 reply; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-07 10:18 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

> >>       struct input_dev *input_dev;
> >>       int i, j, k;
> >> -     int max_report_type = HID_OUTPUT_REPORT;
> >> +     int max_report_type = HID_FEATURE_REPORT;
> >
> > Doing it this way conflicts with the HID_QUIRK_SKIP_OUTPUT_REPORTS quirk.
> 
> 
> Do you agree on this way? (will send the patch in the next version)
> 
> @@ -834,11 +842,10 @@ int hidinput_connect(struct hid_device *hid,
> unsigned int force)
>  {
>  	struct hid_report *report;
>  	struct hid_input *hidinput = NULL;
>  	struct input_dev *input_dev;
>  	int i, j, k;
> -	int max_report_type = HID_OUTPUT_REPORT;
> 
>  	INIT_LIST_HEAD(&hid->inputs);
> 
>  	if (!force) {
>  		for (i = 0; i < hid->maxcollection; i++) {
> @@ -851,14 +858,14 @@ int hidinput_connect(struct hid_device *hid,
> unsigned int force)
> 
>  		if (i == hid->maxcollection)
>  			return -1;
>  	}
> 
> -	if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
> -		max_report_type = HID_INPUT_REPORT;
> +	for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++)
> +		if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
> +			continue;
> 
> -	for (k = HID_INPUT_REPORT; k <= max_report_type; k++)
>  		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
> 
>  			if (!report->maxfield)
>  				continue;

Perfect.

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 01/10] hid: add feature_mapping callback
  2011-01-07 10:18       ` Henrik Rydberg
@ 2011-01-07 11:12           ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-07 11:12 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Fri, Jan 7, 2011 at 11:18 AM, Henrik Rydberg <rydberg@euromail.se> wrote:
>> >>       struct input_dev *input_dev;
>> >>       int i, j, k;
>> >> -     int max_report_type = HID_OUTPUT_REPORT;
>> >> +     int max_report_type = HID_FEATURE_REPORT;
>> >
>> > Doing it this way conflicts with the HID_QUIRK_SKIP_OUTPUT_REPORTS quirk.
>>
>>
>> Do you agree on this way? (will send the patch in the next version)
>>
>> @@ -834,11 +842,10 @@ int hidinput_connect(struct hid_device *hid,
>> unsigned int force)
>>  {
>>       struct hid_report *report;
>>       struct hid_input *hidinput = NULL;
>>       struct input_dev *input_dev;
>>       int i, j, k;
>> -     int max_report_type = HID_OUTPUT_REPORT;
>>
>>       INIT_LIST_HEAD(&hid->inputs);
>>
>>       if (!force) {
>>               for (i = 0; i < hid->maxcollection; i++) {
>> @@ -851,14 +858,14 @@ int hidinput_connect(struct hid_device *hid,
>> unsigned int force)
>>
>>               if (i == hid->maxcollection)
>>                       return -1;
>>       }
>>
>> -     if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
>> -             max_report_type = HID_INPUT_REPORT;
>> +     for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++)
>> +             if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
>> +                     continue;
>>
>> -     for (k = HID_INPUT_REPORT; k <= max_report_type; k++)
>>               list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
>>
>>                       if (!report->maxfield)
>>                               continue;
>
> Perfect.

Well, in fact, I made 2 big mistakes (forgot the brackets after
for(;;), and test if k==HID_OUTPUT_REPORT...), but the idea is still
the same.

Sorry,
Benjamin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 01/10] hid: add feature_mapping callback
@ 2011-01-07 11:12           ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-07 11:12 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Fri, Jan 7, 2011 at 11:18 AM, Henrik Rydberg <rydberg@euromail.se> wrote:
>> >>       struct input_dev *input_dev;
>> >>       int i, j, k;
>> >> -     int max_report_type = HID_OUTPUT_REPORT;
>> >> +     int max_report_type = HID_FEATURE_REPORT;
>> >
>> > Doing it this way conflicts with the HID_QUIRK_SKIP_OUTPUT_REPORTS quirk.
>>
>>
>> Do you agree on this way? (will send the patch in the next version)
>>
>> @@ -834,11 +842,10 @@ int hidinput_connect(struct hid_device *hid,
>> unsigned int force)
>>  {
>>       struct hid_report *report;
>>       struct hid_input *hidinput = NULL;
>>       struct input_dev *input_dev;
>>       int i, j, k;
>> -     int max_report_type = HID_OUTPUT_REPORT;
>>
>>       INIT_LIST_HEAD(&hid->inputs);
>>
>>       if (!force) {
>>               for (i = 0; i < hid->maxcollection; i++) {
>> @@ -851,14 +858,14 @@ int hidinput_connect(struct hid_device *hid,
>> unsigned int force)
>>
>>               if (i == hid->maxcollection)
>>                       return -1;
>>       }
>>
>> -     if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
>> -             max_report_type = HID_INPUT_REPORT;
>> +     for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++)
>> +             if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
>> +                     continue;
>>
>> -     for (k = HID_INPUT_REPORT; k <= max_report_type; k++)
>>               list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
>>
>>                       if (!report->maxfield)
>>                               continue;
>
> Perfect.

Well, in fact, I made 2 big mistakes (forgot the brackets after
for(;;), and test if k==HID_OUTPUT_REPORT...), but the idea is still
the same.

Sorry,
Benjamin
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
  2011-01-07  9:38       ` Benjamin Tissoires
  (?)
@ 2011-01-07 12:23       ` Henrik Rydberg
  2011-01-07 15:12         ` Benjamin Tissoires
  -1 siblings, 1 reply; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-07 12:23 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

> > Please provide a bit more information under this config option. The
> > usual "what should I do", and roughly what devices are supported.
> 
> Will try, but don't hesitate to send one if you feel in a good mood for writing.
> 
> I can propose:
> 
> +        ---help---
> +          Generic support for HID multitouch panels.
> +          Currently supported panels are:
> +          - PixCir touchscreen
> +          - Cypress TrueTouch
> +          - 'Sensing Win7-TwoFinger' panel by GeneralTouch

This is fine, but needs the "to compile as a module" etc, examples are
all around the Kconfig file.

> >> +struct mt_slot {
> >> +     __s32 x, y, p;
> >> +     __s32 contactid;        /* the device ContactID assigned to this slot */
> >> +     __u16 trkid;    /* the tracking ID that was assigned to this slot */
> >> +     bool valid;     /* did we just get valid contact data for this slot? */
> >> +     bool prev_valid;/* was this slot previously valid/active? */
> >> +};
> >
> > The trkid and prev_valid are no longer needed. The touch state seems to be missing.
> 
> Concerning the trkid, agree.
> I can assure you that prev_valid is needed by at least the Cypress
> device. In a sense, it has the same problem than mt protocol A: it
> does not send the release information except when the last finger has
> been released. This gymnastic is thus required.

Perhaps I did not explain properly. What is needed is a way to clear
the touch state of the active slots not yet seen in a touch
frame. Because of the mixup of semantics around "valid" and "touch",
it looks more complicated than it really is. My point is that the
previous frame has nothing to do with it.

> 
> I think that the misunderstanding comes from the name. We have this 2
> flags (valid and prev_valid) to tell whether the device sent data
> during this report or the previous one. It's not the same meaning that
> the touch you're talking about. For Cypress device, those 2 flags are
> mandatory.

The names are indeed confusing. A valid packet means the incoming
packet contains information about a slot, and brings updates to the
touch state and the touch properties. The touch state just needs to be
set, it is the same logic everytime.

> 
> Maybe introducing data + prev_data + touch (3 flags instead of 2->
> touch can go into mt_buffer, and data and prev_data only in mt_slot as
> they are not given by the device) is clearer.

This would be unnecessarily complicated. Either (touch_state,
seen_in_this_frame), or (touch_state,
last_frame_revision_of_this_slot) would be enough.

> 
> >
> >> +
> >> +struct mt_buffer {
> >> +     __s32 x, y, p;
> >> +     __s32 contactid;        /* the device ContactID assigned to this slot */
> >> +};
> >
> > The only different to mt_slot are the valid and touch field, which is
> > also needed for incoming data. I'd say those should be merged.
> >
> 
> Well, the point is that the buffer and the slot have 2 different meanings:
> one is the incoming data, the other is the processed data. It strikes
> us to have only one struct as the slot contains extra information for
> it to be processed.

This is not true. The data that comes via a valid packet is the touch
state and the property updates, the rest is about handling the
validity. But let's say you use (touch, revision, props), for
instance.  The incoming valid packet would update curdata.touch and
curdata.props. When the slot is finished, curdata is copied to the
right place. At the end of the frame, a device with the
slots-not-send-in-this-frame-are-considered-unused quirk would reset
the touch of the slots with slot[i].revision !=
curdata.revision. Finally, curdata.revision would be incremented.

> >
> >> +     __s8 inputmode;         /* InputMode HID feature, -1 if non-existent */
> >> +     __u8 num_received;      /* how many contacts we received */
> >> +     __u8 maxcontact;        /* expected last contact index */
> >> +     bool curvalid;          /* is the current contact valid? */
> >
> > This value should probably be a mt_slot struct as well.
> 
> I was bothering too. Renaming the field (see above) may solve the
> problem: we have curvalid (or curdata with the name I propose) which
> is only needed for algorithm reasons, and touch that goes into
> mt_buffer as it comes from the device.

Looking again, it seems to me that curvalid should really be where it
is now.

> >
> >> +     struct mt_slot slots[0];        /* first slot */
> >> +};
> >> +
> >> +struct mt_class {
> >> +     int (*compute_slot)(struct mt_device *);
> >> +     __u8 maxcontacts;
> >> +};
> >
> > I imagine maxcontacts could be variable for devices within the same
> > class. Perhaps it should be a member of the device instead? The
> > resolution and fuzz could be added here as well.
> 
> resolution and fuzz: I let you implement it (when adding egalax or
> 3m). But isn't it something we can't get from the report descriptors?

Resolution, yes, but defaults might still be needed. And maybe
compute_slot should be a bitmask of quirks instead. So far we would
have MT_QUIRK_SLOT_IS_CONTACTID and MT_QUIRK_NOT_SEEN_MEANS_UP.

> concerning the device vs. class, currently, we have only seen classes
> (one or more device sharing the same behavior), but we didn't bother
> about resolution and fuzz.
> It would be a shame to have to duplicate the mt_class (or mt_device),
> one by vendorID/deviceID, as many devices may share the same
> properties (at least those that have been manufactured by the same
> company and that behave the same way: cando, stantum, etc...).
> I also like the concept of default class as it will help people easily
> adding devices.

The statement comes from observing what seems to happen over time with
device lists, but sure, it won't really hurt to have the classes.

> >
> >> +
> >> +/* classes of device behavior */
> >> +#define MT_CLS_DEFAULT 0
> >> +#define MT_CLS_DUAL1 1
> >> +
> >> +/*
> >> + * these device-dependent functions determine what slot corresponds
> >> + * to a valid contact that was just read.
> >> + */
> >> +
> >> +static int slot_is_contactid(struct mt_device *td)
> >> +{
> >> +     return td->curdata.contactid;
> >> +}
> >> +
> >> +static int find_slot_from_contactid(struct mt_device *td)
> >> +{
> >> +     int i;
> >> +     for (i = 0; i < td->mtclass->maxcontacts; ++i) {
> >> +             if (td->slots[i].prev_valid &&
> >
> > Why prev_valid? Ought to be valid, right?
> 
> Because the code resets valid after each sending -> implementation dependent.

The prev_valid and valid are only different because prev_valid is used
with touch semantics, whereas valid is not and is reset at each frame
emission. Once we stop mixing fruits, it will all become clear and
simple.

> > Nice solution to the end-of-data issue. It would be good if the input
> > setup was abstracted into a function like in hid-egalax, to simplify
> > further additions.
> 
> thanks.
> I was not very happy in making this abstraction for just one line of
> code. I thought you could do it when adding the additions.

Or you could do it right away - it will simplify the existing
patch, and make subsequent patches simpler as well.

> >
> >> +                             input_mt_init_slots(hi->input,
> >> +                                             td->mtclass->maxcontacts);
> >
> > Maxcontacts should probably take the hid description into account as well.
> 
> I don't understand your point here

Take 3M as an example. The controller supports up to 60 contacts, but
different devices may not be needing that many. Having a way to trim
the number of allocated slots to just the right size for the current
devices seems like a good idea.

> >
> > And ABS_PRESSURE.
> 
> I thought that the mouse emulation was restricted to X and Y.

Look at the psmouse, wacom and generic MT emulation code for counter examples.

> > There are some hid drivers that need to setup fuzz in order to work
> > properly. We should either add it to hid core or use the same bypass as
> > in hid-egalax and hid-3m-pct.
> 
> Can I let you do this in further updates? (for the new devices and
> those I sent, this works out of the box)

Why not do it right away? It is quite simple, and mostly copy and
paste from those drivers.

> >> +/*
> >> + * 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)
> >> +{
> >> +     int i;
> >> +
> >> +     for (i = 0; i < td->mtclass->maxcontacts; ++i) {
> >> +             struct mt_slot *s = &(td->slots[i]);
> >> +             if (!s->valid) {
> >> +                     /*
> >> +                      * this slot does not contain useful data,
> >> +                      * notify its closure if necessary
> >> +                      */
> >> +                     if (s->prev_valid) {
> >> +                             input_mt_slot(input, i);
> >> +                             input_mt_report_slot_state(input,
> >> +                                     MT_TOOL_FINGER, false);
> >> +                             s->prev_valid = false;
> >> +                     }

This code will have exactly the same result without the "if
(s->prev_valid)", since prev_valid is a copy of the last touch
state. The input core will filter away any duplicate calls. Thus, it
can all be replaced by

input_mt_slot(input, i);
input_mt_report_slot_state(input, MT_TOOL_FINGER, s->valid);

Further assuming that valid will change to touch, it is all starting
to look conceptually correct. We could then prepend this line

if ((device_quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && s->revision != curdata.revision)
    s->state = false;

and we would have support for the devices you mention.

> >> +                     continue;
> >> +             }
> >> +             if (!s->prev_valid)
> >> +                     s->trkid = td->lasttrkid++;
> >
> > Most of the above can be removed.
> 
> Cypress device does not sends touch information when a touch is
> released. This piece of code is required for devices that behave the
> same way.

See the above example.

> >
> >> +
> >> +             input_mt_slot(input, i);
> >> +             input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
> >
> > "true" here should simply be slot->touch state.
> >
> >> +             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_PRESSURE, s->p);
> >> +             s->prev_valid = true;
> >> +             s->valid = false;
> >
> > Invalidating the data of a tracked slots seems wrong. If the device
> > sends tracked data properly, no special consideration is needed - it
> > will get cleared when appropriate. Other cases could be dealt with
> > separately.
> 
> already discussed (pb in naming the fields I think)

The egalax driver has a different behavior, for instance.

> >> +             case HID_DG_TIPSWITCH:
> >> +                     td->curvalid = value;
> >
> > Most drivers seem to use this as touch state.
> 
> agree and that is how it is used in the current implementation. We
> really should change the name.

I believe the curvalid is fine, but it should be updated differently.
The INRANGE and CONFIDENCE fields seem to do that for some devices,
yet others rely on the contactcount. The TIPSWITCH field should rather
update curdata.touch.

> >> +             case HID_DG_CONTACTCOUNT:
> >> +                     /*
> >> +                      * We must not overwrite the previous value (some
> >> +                      * devices send one sequence splitted over several
> >> +                      * messages)
> >> +                      */
> >> +                     if (value)
> >> +                             td->maxcontact = value - 1;
> >
> > Is td->maxcontact ever reset? And why not num_expected or something
> > instead of maxcontact - odd semantics.
> 
> maxcontact is not reset (not needed as it is sent in each report).
> Concerning the name, agree.

You are right, this will work, too.

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
  2011-01-07 12:23       ` Henrik Rydberg
@ 2011-01-07 15:12         ` Benjamin Tissoires
  2011-01-07 15:57             ` Henrik Rydberg
  0 siblings, 1 reply; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-07 15:12 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

Hi Henrik,

I've made the changes and I pushed them on the git of our lab. I
thought it was easier for you to have a look at the changes instead of
resending the whole patch. But v3 will be for this afternoon.

the repo is at:
http://lii-enac.fr/cgi-bin/gitweb.cgi?p=linux-input/enac-drivers.git;a=summary
the changes are on the branch "hid-multitouch-dtor" from "Copyright
notice" to the head ("hid-input: better way of handling
HID_FEATURE_REPORT").

To summarize:

- I used touch_state and seen_in_this_frame -> I hope the semantic is
now clearer. I was able to test it on stantum and cypress device. I
should do the test for pixcir as soon as I can have some time in the
afternoon, and the test against generaltouch should happend in the
beginning of the week.

- I integrated fuzz (please check)

- I re-factorized set_abs (just copied-pasted your code)

- I made other small changes

- Concerning the quirks, I am not very in favor ATM: a flag for
compute slot will infer a switch of 5 cases in the emit_event, and the
idea was to be able to have a constant time access (1) when using
specific function.
The Quirk MT_QUIRK_NOT_SEEN_MEANS_UP is better (it will speed up a
little the code: 1 test against 1 test and 1 affectation) but I don't
think it worse the effort for further device additions.

- The Egalax problem: I am pretty sure that Stéphane took this driver
into account when writing the original patch. BTW I propose to
postpone the problem for 2.6.39.

Cheers,
Benjamin

On Fri, Jan 7, 2011 at 1:23 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
>> > Please provide a bit more information under this config option. The
>> > usual "what should I do", and roughly what devices are supported.
>>
>> Will try, but don't hesitate to send one if you feel in a good mood for writing.
>>
>> I can propose:
>>
>> +        ---help---
>> +          Generic support for HID multitouch panels.
>> +          Currently supported panels are:
>> +          - PixCir touchscreen
>> +          - Cypress TrueTouch
>> +          - 'Sensing Win7-TwoFinger' panel by GeneralTouch
>
> This is fine, but needs the "to compile as a module" etc, examples are
> all around the Kconfig file.
>
>> >> +struct mt_slot {
>> >> +     __s32 x, y, p;
>> >> +     __s32 contactid;        /* the device ContactID assigned to this slot */
>> >> +     __u16 trkid;    /* the tracking ID that was assigned to this slot */
>> >> +     bool valid;     /* did we just get valid contact data for this slot? */
>> >> +     bool prev_valid;/* was this slot previously valid/active? */
>> >> +};
>> >
>> > The trkid and prev_valid are no longer needed. The touch state seems to be missing.
>>
>> Concerning the trkid, agree.
>> I can assure you that prev_valid is needed by at least the Cypress
>> device. In a sense, it has the same problem than mt protocol A: it
>> does not send the release information except when the last finger has
>> been released. This gymnastic is thus required.
>
> Perhaps I did not explain properly. What is needed is a way to clear
> the touch state of the active slots not yet seen in a touch
> frame. Because of the mixup of semantics around "valid" and "touch",
> it looks more complicated than it really is. My point is that the
> previous frame has nothing to do with it.
>
>>
>> I think that the misunderstanding comes from the name. We have this 2
>> flags (valid and prev_valid) to tell whether the device sent data
>> during this report or the previous one. It's not the same meaning that
>> the touch you're talking about. For Cypress device, those 2 flags are
>> mandatory.
>
> The names are indeed confusing. A valid packet means the incoming
> packet contains information about a slot, and brings updates to the
> touch state and the touch properties. The touch state just needs to be
> set, it is the same logic everytime.
>
>>
>> Maybe introducing data + prev_data + touch (3 flags instead of 2->
>> touch can go into mt_buffer, and data and prev_data only in mt_slot as
>> they are not given by the device) is clearer.
>
> This would be unnecessarily complicated. Either (touch_state,
> seen_in_this_frame), or (touch_state,
> last_frame_revision_of_this_slot) would be enough.
>
>>
>> >
>> >> +
>> >> +struct mt_buffer {
>> >> +     __s32 x, y, p;
>> >> +     __s32 contactid;        /* the device ContactID assigned to this slot */
>> >> +};
>> >
>> > The only different to mt_slot are the valid and touch field, which is
>> > also needed for incoming data. I'd say those should be merged.
>> >
>>
>> Well, the point is that the buffer and the slot have 2 different meanings:
>> one is the incoming data, the other is the processed data. It strikes
>> us to have only one struct as the slot contains extra information for
>> it to be processed.
>
> This is not true. The data that comes via a valid packet is the touch
> state and the property updates, the rest is about handling the
> validity. But let's say you use (touch, revision, props), for
> instance.  The incoming valid packet would update curdata.touch and
> curdata.props. When the slot is finished, curdata is copied to the
> right place. At the end of the frame, a device with the
> slots-not-send-in-this-frame-are-considered-unused quirk would reset
> the touch of the slots with slot[i].revision !=
> curdata.revision. Finally, curdata.revision would be incremented.
>
>> >
>> >> +     __s8 inputmode;         /* InputMode HID feature, -1 if non-existent */
>> >> +     __u8 num_received;      /* how many contacts we received */
>> >> +     __u8 maxcontact;        /* expected last contact index */
>> >> +     bool curvalid;          /* is the current contact valid? */
>> >
>> > This value should probably be a mt_slot struct as well.
>>
>> I was bothering too. Renaming the field (see above) may solve the
>> problem: we have curvalid (or curdata with the name I propose) which
>> is only needed for algorithm reasons, and touch that goes into
>> mt_buffer as it comes from the device.
>
> Looking again, it seems to me that curvalid should really be where it
> is now.
>
>> >
>> >> +     struct mt_slot slots[0];        /* first slot */
>> >> +};
>> >> +
>> >> +struct mt_class {
>> >> +     int (*compute_slot)(struct mt_device *);
>> >> +     __u8 maxcontacts;
>> >> +};
>> >
>> > I imagine maxcontacts could be variable for devices within the same
>> > class. Perhaps it should be a member of the device instead? The
>> > resolution and fuzz could be added here as well.
>>
>> resolution and fuzz: I let you implement it (when adding egalax or
>> 3m). But isn't it something we can't get from the report descriptors?
>
> Resolution, yes, but defaults might still be needed. And maybe
> compute_slot should be a bitmask of quirks instead. So far we would
> have MT_QUIRK_SLOT_IS_CONTACTID and MT_QUIRK_NOT_SEEN_MEANS_UP.
>
>> concerning the device vs. class, currently, we have only seen classes
>> (one or more device sharing the same behavior), but we didn't bother
>> about resolution and fuzz.
>> It would be a shame to have to duplicate the mt_class (or mt_device),
>> one by vendorID/deviceID, as many devices may share the same
>> properties (at least those that have been manufactured by the same
>> company and that behave the same way: cando, stantum, etc...).
>> I also like the concept of default class as it will help people easily
>> adding devices.
>
> The statement comes from observing what seems to happen over time with
> device lists, but sure, it won't really hurt to have the classes.
>
>> >
>> >> +
>> >> +/* classes of device behavior */
>> >> +#define MT_CLS_DEFAULT 0
>> >> +#define MT_CLS_DUAL1 1
>> >> +
>> >> +/*
>> >> + * these device-dependent functions determine what slot corresponds
>> >> + * to a valid contact that was just read.
>> >> + */
>> >> +
>> >> +static int slot_is_contactid(struct mt_device *td)
>> >> +{
>> >> +     return td->curdata.contactid;
>> >> +}
>> >> +
>> >> +static int find_slot_from_contactid(struct mt_device *td)
>> >> +{
>> >> +     int i;
>> >> +     for (i = 0; i < td->mtclass->maxcontacts; ++i) {
>> >> +             if (td->slots[i].prev_valid &&
>> >
>> > Why prev_valid? Ought to be valid, right?
>>
>> Because the code resets valid after each sending -> implementation dependent.
>
> The prev_valid and valid are only different because prev_valid is used
> with touch semantics, whereas valid is not and is reset at each frame
> emission. Once we stop mixing fruits, it will all become clear and
> simple.
>
>> > Nice solution to the end-of-data issue. It would be good if the input
>> > setup was abstracted into a function like in hid-egalax, to simplify
>> > further additions.
>>
>> thanks.
>> I was not very happy in making this abstraction for just one line of
>> code. I thought you could do it when adding the additions.
>
> Or you could do it right away - it will simplify the existing
> patch, and make subsequent patches simpler as well.
>
>> >
>> >> +                             input_mt_init_slots(hi->input,
>> >> +                                             td->mtclass->maxcontacts);
>> >
>> > Maxcontacts should probably take the hid description into account as well.
>>
>> I don't understand your point here
>
> Take 3M as an example. The controller supports up to 60 contacts, but
> different devices may not be needing that many. Having a way to trim
> the number of allocated slots to just the right size for the current
> devices seems like a good idea.
>
>> >
>> > And ABS_PRESSURE.
>>
>> I thought that the mouse emulation was restricted to X and Y.
>
> Look at the psmouse, wacom and generic MT emulation code for counter examples.
>
>> > There are some hid drivers that need to setup fuzz in order to work
>> > properly. We should either add it to hid core or use the same bypass as
>> > in hid-egalax and hid-3m-pct.
>>
>> Can I let you do this in further updates? (for the new devices and
>> those I sent, this works out of the box)
>
> Why not do it right away? It is quite simple, and mostly copy and
> paste from those drivers.
>
>> >> +/*
>> >> + * 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)
>> >> +{
>> >> +     int i;
>> >> +
>> >> +     for (i = 0; i < td->mtclass->maxcontacts; ++i) {
>> >> +             struct mt_slot *s = &(td->slots[i]);
>> >> +             if (!s->valid) {
>> >> +                     /*
>> >> +                      * this slot does not contain useful data,
>> >> +                      * notify its closure if necessary
>> >> +                      */
>> >> +                     if (s->prev_valid) {
>> >> +                             input_mt_slot(input, i);
>> >> +                             input_mt_report_slot_state(input,
>> >> +                                     MT_TOOL_FINGER, false);
>> >> +                             s->prev_valid = false;
>> >> +                     }
>
> This code will have exactly the same result without the "if
> (s->prev_valid)", since prev_valid is a copy of the last touch
> state. The input core will filter away any duplicate calls. Thus, it
> can all be replaced by
>
> input_mt_slot(input, i);
> input_mt_report_slot_state(input, MT_TOOL_FINGER, s->valid);
>
> Further assuming that valid will change to touch, it is all starting
> to look conceptually correct. We could then prepend this line
>
> if ((device_quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && s->revision != curdata.revision)
>    s->state = false;
>
> and we would have support for the devices you mention.
>
>> >> +                     continue;
>> >> +             }
>> >> +             if (!s->prev_valid)
>> >> +                     s->trkid = td->lasttrkid++;
>> >
>> > Most of the above can be removed.
>>
>> Cypress device does not sends touch information when a touch is
>> released. This piece of code is required for devices that behave the
>> same way.
>
> See the above example.
>
>> >
>> >> +
>> >> +             input_mt_slot(input, i);
>> >> +             input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
>> >
>> > "true" here should simply be slot->touch state.
>> >
>> >> +             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_PRESSURE, s->p);
>> >> +             s->prev_valid = true;
>> >> +             s->valid = false;
>> >
>> > Invalidating the data of a tracked slots seems wrong. If the device
>> > sends tracked data properly, no special consideration is needed - it
>> > will get cleared when appropriate. Other cases could be dealt with
>> > separately.
>>
>> already discussed (pb in naming the fields I think)
>
> The egalax driver has a different behavior, for instance.
>
>> >> +             case HID_DG_TIPSWITCH:
>> >> +                     td->curvalid = value;
>> >
>> > Most drivers seem to use this as touch state.
>>
>> agree and that is how it is used in the current implementation. We
>> really should change the name.
>
> I believe the curvalid is fine, but it should be updated differently.
> The INRANGE and CONFIDENCE fields seem to do that for some devices,
> yet others rely on the contactcount. The TIPSWITCH field should rather
> update curdata.touch.
>
>> >> +             case HID_DG_CONTACTCOUNT:
>> >> +                     /*
>> >> +                      * We must not overwrite the previous value (some
>> >> +                      * devices send one sequence splitted over several
>> >> +                      * messages)
>> >> +                      */
>> >> +                     if (value)
>> >> +                             td->maxcontact = value - 1;
>> >
>> > Is td->maxcontact ever reset? And why not num_expected or something
>> > instead of maxcontact - odd semantics.
>>
>> maxcontact is not reset (not needed as it is sent in each report).
>> Concerning the name, agree.
>
> You are right, this will work, too.
>
> Thanks,
> Henrik
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
  2011-01-07 15:12         ` Benjamin Tissoires
@ 2011-01-07 15:57             ` Henrik Rydberg
  0 siblings, 0 replies; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-07 15:57 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Fri, Jan 07, 2011 at 04:12:24PM +0100, Benjamin Tissoires wrote:
> Hi Henrik,
> 
> I've made the changes and I pushed them on the git of our lab. I
> thought it was easier for you to have a look at the changes instead of
> resending the whole patch. But v3 will be for this afternoon.

Well, it is not really easier, since there is no easy way to comment
on the code. Also, transparency is lost. Please let the review process
take its time.

> 
> the repo is at:
> http://lii-enac.fr/cgi-bin/gitweb.cgi?p=linux-input/enac-drivers.git;a=summary
> the changes are on the branch "hid-multitouch-dtor" from "Copyright
> notice" to the head ("hid-input: better way of handling
> HID_FEATURE_REPORT").
> 
> To summarize:
> 
> - I used touch_state and seen_in_this_frame -> I hope the semantic is
> now clearer. I was able to test it on stantum and cypress device. I
> should do the test for pixcir as soon as I can have some time in the
> afternoon, and the test against generaltouch should happend in the
> beginning of the week.

The code looks clearer, but there are still two more or less identical
structures in there. Please remove, it just looks silly.

> - I integrated fuzz (please check)

But the mt_input_mapped function did not change - needs to change too.

> - I re-factorized set_abs (just copied-pasted your code)

Ok.

> - I made other small changes
> 
> - Concerning the quirks, I am not very in favor ATM: a flag for
> compute slot will infer a switch of 5 cases in the emit_event, and the
> idea was to be able to have a constant time access (1) when using
> specific function.
> The Quirk MT_QUIRK_NOT_SEEN_MEANS_UP is better (it will speed up a
> little the code: 1 test against 1 test and 1 affectation) but I don't
> think it worse the effort for further device additions.

Given everything that happens within a hid packet, this really, really
does not matter much. And the quirks can be implemented efficiently
too, if really needed.

> - The Egalax problem: I am pretty sure that Stéphane took this driver
> into account when writing the original patch. BTW I propose to
> postpone the problem for 2.6.39.

This driver is aiming at engulfing a larger set of drivers, and as
such, should be prepared sensibly, IMO. Rushing things will only cause
us grief further down the road.

Henrik

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
@ 2011-01-07 15:57             ` Henrik Rydberg
  0 siblings, 0 replies; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-07 15:57 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Fri, Jan 07, 2011 at 04:12:24PM +0100, Benjamin Tissoires wrote:
> Hi Henrik,
> 
> I've made the changes and I pushed them on the git of our lab. I
> thought it was easier for you to have a look at the changes instead of
> resending the whole patch. But v3 will be for this afternoon.

Well, it is not really easier, since there is no easy way to comment
on the code. Also, transparency is lost. Please let the review process
take its time.

> 
> the repo is at:
> http://lii-enac.fr/cgi-bin/gitweb.cgi?p=linux-input/enac-drivers.git;a=summary
> the changes are on the branch "hid-multitouch-dtor" from "Copyright
> notice" to the head ("hid-input: better way of handling
> HID_FEATURE_REPORT").
> 
> To summarize:
> 
> - I used touch_state and seen_in_this_frame -> I hope the semantic is
> now clearer. I was able to test it on stantum and cypress device. I
> should do the test for pixcir as soon as I can have some time in the
> afternoon, and the test against generaltouch should happend in the
> beginning of the week.

The code looks clearer, but there are still two more or less identical
structures in there. Please remove, it just looks silly.

> - I integrated fuzz (please check)

But the mt_input_mapped function did not change - needs to change too.

> - I re-factorized set_abs (just copied-pasted your code)

Ok.

> - I made other small changes
> 
> - Concerning the quirks, I am not very in favor ATM: a flag for
> compute slot will infer a switch of 5 cases in the emit_event, and the
> idea was to be able to have a constant time access (1) when using
> specific function.
> The Quirk MT_QUIRK_NOT_SEEN_MEANS_UP is better (it will speed up a
> little the code: 1 test against 1 test and 1 affectation) but I don't
> think it worse the effort for further device additions.

Given everything that happens within a hid packet, this really, really
does not matter much. And the quirks can be implemented efficiently
too, if really needed.

> - The Egalax problem: I am pretty sure that Stéphane took this driver
> into account when writing the original patch. BTW I propose to
> postpone the problem for 2.6.39.

This driver is aiming at engulfing a larger set of drivers, and as
such, should be prepared sensibly, IMO. Rushing things will only cause
us grief further down the road.

Henrik
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
  2011-01-07 15:57             ` Henrik Rydberg
@ 2011-01-07 17:07               ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-07 17:07 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Fri, Jan 7, 2011 at 4:57 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
> On Fri, Jan 07, 2011 at 04:12:24PM +0100, Benjamin Tissoires wrote:
>> Hi Henrik,
>>
>> I've made the changes and I pushed them on the git of our lab. I
>> thought it was easier for you to have a look at the changes instead of
>> resending the whole patch. But v3 will be for this afternoon.
>
> Well, it is not really easier, since there is no easy way to comment
> on the code. Also, transparency is lost. Please let the review process
> take its time.
>
>>
>> the repo is at:
>> http://lii-enac.fr/cgi-bin/gitweb.cgi?p=linux-input/enac-drivers.git;a=summary
>> the changes are on the branch "hid-multitouch-dtor" from "Copyright
>> notice" to the head ("hid-input: better way of handling
>> HID_FEATURE_REPORT").
>>
>> To summarize:
>>
>> - I used touch_state and seen_in_this_frame -> I hope the semantic is
>> now clearer. I was able to test it on stantum and cypress device. I
>> should do the test for pixcir as soon as I can have some time in the
>> afternoon, and the test against generaltouch should happend in the
>> beginning of the week.
>
> The code looks clearer, but there are still two more or less identical
> structures in there. Please remove, it just looks silly.

In not a big fan of this idea, but we have to find a compromise -> will do.

>
>> - I integrated fuzz (please check)
>
> But the mt_input_mapped function did not change - needs to change too.

I can not see any differences between mt_input_mapped and those found
in 3m and egalax. Can you point me exactly what I should add please?

>
>> - I re-factorized set_abs (just copied-pasted your code)
>
> Ok.
>
>> - I made other small changes
>>
>> - Concerning the quirks, I am not very in favor ATM: a flag for
>> compute slot will infer a switch of 5 cases in the emit_event, and the
>> idea was to be able to have a constant time access (1) when using
>> specific function.
>> The Quirk MT_QUIRK_NOT_SEEN_MEANS_UP is better (it will speed up a
>> little the code: 1 test against 1 test and 1 affectation) but I don't
>> think it worse the effort for further device additions.
>
> Given everything that happens within a hid packet, this really, really
> does not matter much. And the quirks can be implemented efficiently
> too, if really needed.

Will do.

>
>> - The Egalax problem: I am pretty sure that Stéphane took this driver
>> into account when writing the original patch. BTW I propose to
>> postpone the problem for 2.6.39.
>
> This driver is aiming at engulfing a larger set of drivers, and as
> such, should be prepared sensibly, IMO. Rushing things will only cause
> us grief further down the road.
>

So, have you got any clue (or even better, can you test a solution)
for those devices?

Cheers,
Benjamin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
@ 2011-01-07 17:07               ` Benjamin Tissoires
  0 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-07 17:07 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Fri, Jan 7, 2011 at 4:57 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
> On Fri, Jan 07, 2011 at 04:12:24PM +0100, Benjamin Tissoires wrote:
>> Hi Henrik,
>>
>> I've made the changes and I pushed them on the git of our lab. I
>> thought it was easier for you to have a look at the changes instead of
>> resending the whole patch. But v3 will be for this afternoon.
>
> Well, it is not really easier, since there is no easy way to comment
> on the code. Also, transparency is lost. Please let the review process
> take its time.
>
>>
>> the repo is at:
>> http://lii-enac.fr/cgi-bin/gitweb.cgi?p=linux-input/enac-drivers.git;a=summary
>> the changes are on the branch "hid-multitouch-dtor" from "Copyright
>> notice" to the head ("hid-input: better way of handling
>> HID_FEATURE_REPORT").
>>
>> To summarize:
>>
>> - I used touch_state and seen_in_this_frame -> I hope the semantic is
>> now clearer. I was able to test it on stantum and cypress device. I
>> should do the test for pixcir as soon as I can have some time in the
>> afternoon, and the test against generaltouch should happend in the
>> beginning of the week.
>
> The code looks clearer, but there are still two more or less identical
> structures in there. Please remove, it just looks silly.

In not a big fan of this idea, but we have to find a compromise -> will do.

>
>> - I integrated fuzz (please check)
>
> But the mt_input_mapped function did not change - needs to change too.

I can not see any differences between mt_input_mapped and those found
in 3m and egalax. Can you point me exactly what I should add please?

>
>> - I re-factorized set_abs (just copied-pasted your code)
>
> Ok.
>
>> - I made other small changes
>>
>> - Concerning the quirks, I am not very in favor ATM: a flag for
>> compute slot will infer a switch of 5 cases in the emit_event, and the
>> idea was to be able to have a constant time access (1) when using
>> specific function.
>> The Quirk MT_QUIRK_NOT_SEEN_MEANS_UP is better (it will speed up a
>> little the code: 1 test against 1 test and 1 affectation) but I don't
>> think it worse the effort for further device additions.
>
> Given everything that happens within a hid packet, this really, really
> does not matter much. And the quirks can be implemented efficiently
> too, if really needed.

Will do.

>
>> - The Egalax problem: I am pretty sure that Stéphane took this driver
>> into account when writing the original patch. BTW I propose to
>> postpone the problem for 2.6.39.
>
> This driver is aiming at engulfing a larger set of drivers, and as
> such, should be prepared sensibly, IMO. Rushing things will only cause
> us grief further down the road.
>

So, have you got any clue (or even better, can you test a solution)
for those devices?

Cheers,
Benjamin
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
  2011-01-07 17:07               ` Benjamin Tissoires
@ 2011-01-07 17:27                 ` Henrik Rydberg
  -1 siblings, 0 replies; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-07 17:27 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

> > But the mt_input_mapped function did not change - needs to change too.
> 
> I can not see any differences between mt_input_mapped and those found
> in 3m and egalax. Can you point me exactly what I should add please?

My bad - it seems your tree does contain the right function. Another
reason to have the patches in mail. :-)

> >> - The Egalax problem: I am pretty sure that Stéphane took this driver
> >> into account when writing the original patch. BTW I propose to
> >> postpone the problem for 2.6.39.
> >
> > This driver is aiming at engulfing a larger set of drivers, and as
> > such, should be prepared sensibly, IMO. Rushing things will only cause
> > us grief further down the road.
> >
> 
> So, have you got any clue (or even better, can you test a solution)
> for those devices?

Yes I can, but I will not be available the coming couple of days, so
the timing is a bit off. I agree with you that we do not need to solve
every issue right now, but I know for a fact that the newer DWAV
firmware has no touch frame indication, and does not assume the
not-seen-means-up behavior. Perhaps it is enough to just add the
quirks field to the class, define one or two quirks currently in use,
and leave the rest for later. Sounds reasonable?

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
@ 2011-01-07 17:27                 ` Henrik Rydberg
  0 siblings, 0 replies; 56+ messages in thread
From: Henrik Rydberg @ 2011-01-07 17:27 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

> > But the mt_input_mapped function did not change - needs to change too.
> 
> I can not see any differences between mt_input_mapped and those found
> in 3m and egalax. Can you point me exactly what I should add please?

My bad - it seems your tree does contain the right function. Another
reason to have the patches in mail. :-)

> >> - The Egalax problem: I am pretty sure that Stéphane took this driver
> >> into account when writing the original patch. BTW I propose to
> >> postpone the problem for 2.6.39.
> >
> > This driver is aiming at engulfing a larger set of drivers, and as
> > such, should be prepared sensibly, IMO. Rushing things will only cause
> > us grief further down the road.
> >
> 
> So, have you got any clue (or even better, can you test a solution)
> for those devices?

Yes I can, but I will not be available the coming couple of days, so
the timing is a bit off. I agree with you that we do not need to solve
every issue right now, but I know for a fact that the newer DWAV
firmware has no touch frame indication, and does not assume the
not-seen-means-up behavior. Perhaps it is enough to just add the
quirks field to the class, define one or two quirks currently in use,
and leave the rest for later. Sounds reasonable?

Thanks,
Henrik
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [RFC v2 03/10] hid-multitouch: support for PixCir-based panels
  2011-01-07 17:27                 ` Henrik Rydberg
  (?)
@ 2011-01-07 17:31                 ` Benjamin Tissoires
  -1 siblings, 0 replies; 56+ messages in thread
From: Benjamin Tissoires @ 2011-01-07 17:31 UTC (permalink / raw)
  To: Henrik Rydberg
  Cc: Stephane Chatty, Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Fri, Jan 7, 2011 at 6:27 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
>> > But the mt_input_mapped function did not change - needs to change too.
>>
>> I can not see any differences between mt_input_mapped and those found
>> in 3m and egalax. Can you point me exactly what I should add please?
>
> My bad - it seems your tree does contain the right function. Another
> reason to have the patches in mail. :-)
>
>> >> - The Egalax problem: I am pretty sure that Stéphane took this driver
>> >> into account when writing the original patch. BTW I propose to
>> >> postpone the problem for 2.6.39.
>> >
>> > This driver is aiming at engulfing a larger set of drivers, and as
>> > such, should be prepared sensibly, IMO. Rushing things will only cause
>> > us grief further down the road.
>> >
>>
>> So, have you got any clue (or even better, can you test a solution)
>> for those devices?
>
> Yes I can, but I will not be available the coming couple of days, so
> the timing is a bit off. I agree with you that we do not need to solve
> every issue right now, but I know for a fact that the newer DWAV
> firmware has no touch frame indication, and does not assume the
> not-seen-means-up behavior. Perhaps it is enough to just add the
> quirks field to the class, define one or two quirks currently in use,
> and leave the rest for later. Sounds reasonable?
>

Sounds reasonable

Cheers,
Benjamin

^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2011-01-07 17:31 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-05 17:27 [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification Benjamin Tissoires
2011-01-05 17:27 ` Benjamin Tissoires
2011-01-05 17:27 ` [RFC v2 01/10] hid: add feature_mapping callback Benjamin Tissoires
2011-01-05 17:27   ` Benjamin Tissoires
2011-01-06 16:22   ` Henrik Rydberg
2011-01-07  9:44     ` Benjamin Tissoires
2011-01-07 10:18       ` Henrik Rydberg
2011-01-07 11:12         ` Benjamin Tissoires
2011-01-07 11:12           ` Benjamin Tissoires
2011-01-05 17:27 ` [RFC v2 02/10] hid: set HID_MAX_FIELD at 128 Benjamin Tissoires
2011-01-05 17:27   ` Benjamin Tissoires
2011-01-06 16:28   ` Henrik Rydberg
2011-01-05 17:27 ` [RFC v2 03/10] hid-multitouch: support for PixCir-based panels Benjamin Tissoires
2011-01-05 17:27   ` Benjamin Tissoires
2011-01-06 17:25   ` Henrik Rydberg
2011-01-06 17:25     ` Henrik Rydberg
2011-01-07  9:38     ` Benjamin Tissoires
2011-01-07  9:38       ` Benjamin Tissoires
2011-01-07 12:23       ` Henrik Rydberg
2011-01-07 15:12         ` Benjamin Tissoires
2011-01-07 15:57           ` Henrik Rydberg
2011-01-07 15:57             ` Henrik Rydberg
2011-01-07 17:07             ` Benjamin Tissoires
2011-01-07 17:07               ` Benjamin Tissoires
2011-01-07 17:27               ` Henrik Rydberg
2011-01-07 17:27                 ` Henrik Rydberg
2011-01-07 17:31                 ` Benjamin Tissoires
2011-01-05 17:27 ` [RFC v2 04/10] hid-multitouch: migrated support for Cando panels Benjamin Tissoires
2011-01-05 17:27   ` Benjamin Tissoires
2011-01-05 17:27 ` [RFC v2 05/10] hid-multitouch: Add support for Cando 10.1" panels Benjamin Tissoires
2011-01-05 17:27   ` Benjamin Tissoires
2011-01-05 17:27 ` [RFC v2 06/10] hid-multitouch: added support for Cypress TrueTouch panels Benjamin Tissoires
2011-01-05 17:27   ` Benjamin Tissoires
2011-01-05 17:27 ` [RFC v2 07/10] hid-multitouch: migrated support for MosArt panels Benjamin Tissoires
2011-01-05 17:27   ` Benjamin Tissoires
2011-01-05 17:27 ` [RFC v2 08/10] hid-multitouch: migrated support for Quanta dual-touch panels Benjamin Tissoires
2011-01-05 17:27   ` Benjamin Tissoires
2011-01-05 17:27 ` [RFC v2 09/10] hid-mulitouch: added support for the 'Sensing Win7-TwoFinger' Benjamin Tissoires
2011-01-05 17:27   ` Benjamin Tissoires
2011-01-05 17:27 ` [RFC v2 10/10] hid-multitouch: migrated support for Stantum panels Benjamin Tissoires
2011-01-05 17:27   ` Benjamin Tissoires
2011-01-05 17:49 ` [RFC v2 0/10] hid-multitouch: a first step towards multitouch unification Henrik Rydberg
2011-01-06 15:08   ` Benjamin Tissoires
2011-01-06 15:08     ` Benjamin Tissoires
2011-01-06 15:11     ` Jiri Kosina
2011-01-06 15:11       ` Jiri Kosina
2011-01-06 16:04       ` Henrik Rydberg
2011-01-06 16:08         ` Benjamin Tissoires
2011-01-06 17:28           ` Henrik Rydberg
2011-01-06 23:26           ` Jiri Kosina
2011-01-07  1:14       ` Dmitry Torokhov
2011-01-07  1:14         ` Dmitry Torokhov
2011-01-07  9:41         ` Jiri Kosina
2011-01-07  9:48           ` Benjamin Tissoires
2011-01-07  9:48             ` Benjamin Tissoires
2011-01-07 10:03             ` Jiri Kosina

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.