* [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen
@ 2009-05-18 22:11 Stéphane Chatty
2009-05-19 14:50 ` Jiri Kosina
0 siblings, 1 reply; 7+ messages in thread
From: Stéphane Chatty @ 2009-05-18 22:11 UTC (permalink / raw)
To: linux-input, jkosina, Henrik Rydberg
Added support for multitouch interaction on the N-Trig touchscreen,
using the new ABS_MT_* input constants. Single touch support works
as previously. This code was tested against two versions of the N-
Trig firmware: one that supports dual pen/finger single touch, and
one that supports finger multitouch but no pen at all. Copyright
notices that looked wrong were removed, as it seems that there is
only code written in 2009 by Rafin Rubin and Stephane Chatty in this
file.
Signed-off-by: Stephane Chatty <chatty@enac.fr>
diff -rupN a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
--- a/drivers/hid/hid-ntrig.c 2009-05-09 02:14:14.000000000 +0200
+++ b/drivers/hid/hid-ntrig.c 2009-05-18 23:30:17.000000000 +0200
@@ -1,13 +1,8 @@
/*
- * HID driver for some ntrig "special" devices
+ * HID driver for N-Trig touchscreens
*
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for
Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
- * Copyright (c) 2007 Paul Walmsley
- * Copyright (c) 2008 Jiri Slaby
* Copyright (c) 2008 Rafi Rubin
+ * Copyright (c) 2009 Stephane Chatty
*
*/
@@ -29,15 +24,70 @@
#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
+/*
+ this driver is aimed at two firmware versions in circulation:
+ - dual pen/finger single touch
+ - finger multitouch, pen not working
+*/
+
static int ntrig_input_mapping(struct hid_device *hdev, struct
hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
- if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
- (usage->hid & 0xff) == 0x47) {
- nt_map_key_clear(BTN_TOOL_DOUBLETAP);
- return 1;
+ 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_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);
+ 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) {
+ /* we do not want to map these for now */
+ case HID_DG_INVERT: /* value is always 0 */
+ case HID_DG_ERASER: /* value is always 0 */
+ case HID_DG_CONTACTID: /* value is useless */
+ /* case HID_DG_BARRELSWITCH: doubtful */
+ return -1;
+
+ /* original mapping by Rafi Rubin */
+ case HID_DG_CONFIDENCE:
+ nt_map_key_clear(BTN_TOOL_DOUBLETAP);
+ return 1;
+
+ /* width/height mapped on TouchMajor/TouchMinor/Orientation */
+ 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,
+ 0, 1, 0, 0);
+ return 1;
+ }
+ return 0;
+
+ case 0xff000000:
+ /* we do not want to map these */
+ return -1;
}
+
return 0;
}
@@ -51,6 +101,102 @@ static int ntrig_input_mapped(struct hid
return 0;
}
+
+/*
+ * this function is called upon all reports
+ * so that we can filter contact point information,
+ * decide whether we are in multi or single touch mode
+ * and call input_mt_sync after each point if necessary
+ */
+static int ntrig_event (struct hid_device *hid, struct hid_field
*field,
+ struct hid_usage *usage, __s32 value)
+{
+ static __s32 x, y, id, w, h;
+ static char reading_a_point = 0, found_contact_id = 0;
+ struct input_dev *input = field->hidinput->input;
+
+ if (hid->claimed & HID_CLAIMED_INPUT) {
+ switch (usage->hid) {
+ case HID_GD_X:
+ x = value;
+ reading_a_point = 1;
+ break;
+ case HID_GD_Y:
+ y = value;
+ break;
+ case HID_DG_CONTACTID:
+ id = value;
+ /* we receive this only when in multitouch mode */
+ found_contact_id = 1;
+ break;
+ case HID_DG_WIDTH:
+ w = value;
+ break;
+ case HID_DG_HEIGHT:
+ h = value;
+ /* when in single touch mode, this is the last
+ report received in a finger event. We want
+ to emit a normal (X, Y) position */
+ if (! found_contact_id) {
+ input_event(input, EV_ABS, ABS_X, x);
+ input_event(input, EV_ABS, ABS_Y, y);
+ }
+ break;
+ case HID_DG_TIPPRESSURE:
+ /* when in single touch mode, this is the last
+ report received in a pen event. We want
+ to emit a normal (X, Y) position */
+ if (! found_contact_id) {
+ input_event(input, EV_ABS, ABS_X, x);
+ input_event(input, EV_ABS, ABS_Y, y);
+ input_event(input, EV_ABS, ABS_PRESSURE, value);
+ }
+ break;
+ case 0xff000002:
+ /* we receive this when the device is in multitouch
+ mode. The first of the three values tagged with
+ this usage tells if the contact point is real
+ or a placeholder */
+ if (!reading_a_point || value != 1)
+ break;
+ /* emit a normal (X, Y) for the first point only */
+ if (id == 0) {
+ input_event(input, EV_ABS, ABS_X, x);
+ input_event(input, EV_ABS, ABS_Y, y);
+ }
+ input_event(input, EV_ABS, ABS_MT_POSITION_X, x);
+ input_event(input, EV_ABS, ABS_MT_POSITION_Y, y);
+ if (w > h) {
+ input_event(input, EV_ABS,
+ ABS_MT_ORIENTATION, 1);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MAJOR, w);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MINOR, h);
+ } else {
+ input_event(input, EV_ABS,
+ ABS_MT_ORIENTATION, 0);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MAJOR, h);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MINOR, w);
+ }
+ input_mt_sync(field->hidinput->input);
+ reading_a_point = 0;
+ found_contact_id = 0;
+ break;
+
+ default:
+ hidinput_hid_event(hid, field, usage, value);
+ }
+ }
+ if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+ hid->hiddev_hid_event(hid, field, usage, value);
+
+ return 1;
+}
+
+
static const struct hid_device_id ntrig_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG,
USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
.driver_data = NTRIG_DUPLICATE_USAGES },
@@ -58,11 +204,18 @@ static const struct hid_device_id ntrig_
};
MODULE_DEVICE_TABLE(hid, ntrig_devices);
+static const struct hid_usage_id ntrig_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 ntrig_driver = {
.name = "ntrig",
.id_table = ntrig_devices,
.input_mapping = ntrig_input_mapping,
.input_mapped = ntrig_input_mapped,
+ .usage_table = ntrig_grabbed_usages,
+ .event = ntrig_event,
};
static int ntrig_init(void)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen
2009-05-18 22:11 [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen Stéphane Chatty
@ 2009-05-19 14:50 ` Jiri Kosina
2009-05-19 15:38 ` Stéphane Chatty
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Jiri Kosina @ 2009-05-19 14:50 UTC (permalink / raw)
To: Stéphane Chatty; +Cc: linux-input, Henrik Rydberg, Rafi Rubin
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1400 bytes --]
On Tue, 19 May 2009, Stéphane Chatty wrote:
> +/*
> + this driver is aimed at two firmware versions in circulation:
> + - dual pen/finger single touch
> + - finger multitouch, pen not working
> +*/
Please use kernel-style comments (i.e. stars on each line).
> + case 0xff000000:
> + /* we do not want to map these */
Why?
> +/*
> + * this function is called upon all reports
> + * so that we can filter contact point information,
> + * decide whether we are in multi or single touch mode
> + * and call input_mt_sync after each point if necessary
> + */
> +static int ntrig_event (struct hid_device *hid, struct hid_field *field,
> + struct hid_usage *usage, __s32 value)
> +{
> + static __s32 x, y, id, w, h;
> + static char reading_a_point = 0, found_contact_id = 0;
> + struct input_dev *input = field->hidinput->input;
Why are these variables static? This will break horribly if multiple
devices are connected to the system, right?
> + default:
> + hidinput_hid_event(hid, field, usage, value);
Just return 1; here?
> + }
> + }
> + if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
> + hid->hiddev_hid_event(hid, field, usage, value);
> +
> + return 1;
And return 0; here and let the HID core do all the rest (passing to
hidinput and hiddev, etc) if necessary?
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen
2009-05-19 14:50 ` Jiri Kosina
@ 2009-05-19 15:38 ` Stéphane Chatty
2009-05-20 11:00 ` Jiri Kosina
2009-05-19 16:50 ` [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen [v2] Stéphane Chatty
2009-05-20 12:30 ` [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen [v3] Stéphane Chatty
2 siblings, 1 reply; 7+ messages in thread
From: Stéphane Chatty @ 2009-05-19 15:38 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input, Henrik Rydberg, Rafi Rubin
Le 19 mai 09 à 16:50, Jiri Kosina a écrit :
>> + static __s32 x, y, id, w, h;
>> + static char reading_a_point = 0, found_contact_id = 0;
>> + struct input_dev *input = field->hidinput->input;
>
> Why are these variables static? This will break horribly if multiple
> devices are connected to the system, right?
You're right. But so far these devices are sold only as embedded in a
notebook, and I doubt we will see standalone devices in the near
future. Do you think it is worth planning ahead for this eventuality?
>
> Please use kernel-style comments (i.e. stars on each line).
Will do.
>
>> + case 0xff000000:
>> + /* we do not want to map these */
>
> Why?
Will add a couple of words.
>> + default:
>> + hidinput_hid_event(hid, field, usage, value);
>
> Just return 1; here?
>
>> + }
>> + }
>> + if (hid->claimed & HID_CLAIMED_HIDDEV && hid-
>> >hiddev_hid_event)
>> + hid->hiddev_hid_event(hid, field, usage, value);
>> +
>> + return 1;
>
> And return 0; here and let the HID core do all the rest (passing to
> hidinput and hiddev, etc) if necessary?
See my question in my other reply.
Cheers,
St.
--
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] 7+ messages in thread
* Re: [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen [v2]
2009-05-19 14:50 ` Jiri Kosina
2009-05-19 15:38 ` Stéphane Chatty
@ 2009-05-19 16:50 ` Stéphane Chatty
2009-05-19 18:34 ` Rafi Rubin
2009-05-20 12:30 ` [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen [v3] Stéphane Chatty
2 siblings, 1 reply; 7+ messages in thread
From: Stéphane Chatty @ 2009-05-19 16:50 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input, Henrik Rydberg, Rafi Rubin
Added support for multitouch interaction on the N-Trig touchscreen,
using the new ABS_MT_* input constants. Single touch support works
as previously. This code was tested against two versions of the N-
Trig firmware: one that supports dual pen/finger single touch, and
one that supports finger multitouch but no pen at all. Copyright
notices that looked wrong were removed, as it seems that there is
only code written in 2009 by Rafin Rubin and Stephane Chatty in this
file.
Signed-off-by: Stephane Chatty <chatty@enac.fr>
diff -rupN a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
--- a/drivers/hid/hid-ntrig.c 2009-05-09 02:14:14.000000000 +0200
+++ b/drivers/hid/hid-ntrig.c 2009-05-19 18:36:43.000000000 +0200
@@ -1,13 +1,8 @@
/*
- * HID driver for some ntrig "special" devices
+ * HID driver for N-Trig touchscreens
*
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for
Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
- * Copyright (c) 2007 Paul Walmsley
- * Copyright (c) 2008 Jiri Slaby
* Copyright (c) 2008 Rafi Rubin
+ * Copyright (c) 2009 Stephane Chatty
*
*/
@@ -29,15 +24,74 @@
#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
+/*
+ * this driver is aimed at two firmware versions in circulation:
+ * - dual pen/finger single touch
+ * - finger multitouch, pen not working
+ */
+
static int ntrig_input_mapping(struct hid_device *hdev, struct
hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
- if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
- (usage->hid & 0xff) == 0x47) {
- nt_map_key_clear(BTN_TOOL_DOUBLETAP);
- return 1;
+ 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_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);
+ 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) {
+ /* we do not want to map these for now */
+ case HID_DG_INVERT: /* value is always 0 */
+ case HID_DG_ERASER: /* value is always 0 */
+ case HID_DG_CONTACTID: /* value is useless */
+ case HID_DG_BARRELSWITCH: /* doubtful */
+ case HID_DG_INPUTMODE:
+ case HID_DG_DEVICEINDEX:
+ case HID_DG_CONTACTCOUNT:
+ case HID_DG_CONTACTMAX:
+ return -1;
+
+ /* original mapping by Rafi Rubin */
+ case HID_DG_CONFIDENCE:
+ nt_map_key_clear(BTN_TOOL_DOUBLETAP);
+ return 1;
+
+ /* width/height mapped on TouchMajor/TouchMinor/Orientation */
+ 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,
+ 0, 1, 0, 0);
+ return 1;
+ }
+ return 0;
+
+ case 0xff000000:
+ /* we do not want to map these: no input-oriented meaning */
+ return -1;
}
+
return 0;
}
@@ -51,6 +105,111 @@ static int ntrig_input_mapped(struct hid
return 0;
}
+
+/*
+ * this function is called upon all reports
+ * so that we can filter contact point information,
+ * decide whether we are in multi or single touch mode
+ * and call input_mt_sync after each point if necessary
+ */
+static int ntrig_event (struct hid_device *hid, struct hid_field
*field,
+ struct hid_usage *usage, __s32 value)
+{
+ static __s32 x, y, id, w, h;
+ static char reading_a_point = 0, found_contact_id = 0;
+ struct input_dev *input = field->hidinput->input;
+
+ if (hid->claimed & HID_CLAIMED_INPUT) {
+ switch (usage->hid) {
+ case HID_GD_X:
+ x = value;
+ reading_a_point = 1;
+ break;
+ case HID_GD_Y:
+ y = value;
+ break;
+ case HID_DG_CONTACTID:
+ id = value;
+ /* we receive this only when in multitouch mode */
+ found_contact_id = 1;
+ break;
+ case HID_DG_WIDTH:
+ w = value;
+ break;
+ case HID_DG_HEIGHT:
+ h = value;
+ /*
+ * when in single touch mode, this is the last
+ * report received in a finger event. We want
+ * to emit a normal (X, Y) position
+ */
+ if (! found_contact_id) {
+ input_event(input, EV_ABS, ABS_X, x);
+ input_event(input, EV_ABS, ABS_Y, y);
+ }
+ break;
+ case HID_DG_TIPPRESSURE:
+ /*
+ * when in single touch mode, this is the last
+ * report received in a pen event. We want
+ * to emit a normal (X, Y) position
+ */
+ if (! found_contact_id) {
+ input_event(input, EV_ABS, ABS_X, x);
+ input_event(input, EV_ABS, ABS_Y, y);
+ input_event(input, EV_ABS, ABS_PRESSURE, value);
+ }
+ break;
+ case 0xff000002:
+ /*
+ * we receive this when the device is in multitouch
+ * mode. The first of the three values tagged with
+ * this usage tells if the contact point is real
+ * or a placeholder
+ */
+ if (!reading_a_point || value != 1)
+ break;
+ /* emit a normal (X, Y) for the first point only */
+ if (id == 0) {
+ input_event(input, EV_ABS, ABS_X, x);
+ input_event(input, EV_ABS, ABS_Y, y);
+ }
+ input_event(input, EV_ABS, ABS_MT_POSITION_X, x);
+ input_event(input, EV_ABS, ABS_MT_POSITION_Y, y);
+ if (w > h) {
+ input_event(input, EV_ABS,
+ ABS_MT_ORIENTATION, 1);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MAJOR, w);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MINOR, h);
+ } else {
+ input_event(input, EV_ABS,
+ ABS_MT_ORIENTATION, 0);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MAJOR, h);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MINOR, w);
+ }
+ input_mt_sync(field->hidinput->input);
+ reading_a_point = 0;
+ found_contact_id = 0;
+ 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 const struct hid_device_id ntrig_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG,
USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
.driver_data = NTRIG_DUPLICATE_USAGES },
@@ -58,11 +217,18 @@ static const struct hid_device_id ntrig_
};
MODULE_DEVICE_TABLE(hid, ntrig_devices);
+static const struct hid_usage_id ntrig_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 ntrig_driver = {
.name = "ntrig",
.id_table = ntrig_devices,
.input_mapping = ntrig_input_mapping,
.input_mapped = ntrig_input_mapped,
+ .usage_table = ntrig_grabbed_usages,
+ .event = ntrig_event,
};
static int ntrig_init(void)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen [v2]
2009-05-19 16:50 ` [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen [v2] Stéphane Chatty
@ 2009-05-19 18:34 ` Rafi Rubin
0 siblings, 0 replies; 7+ messages in thread
From: Rafi Rubin @ 2009-05-19 18:34 UTC (permalink / raw)
To: Stéphane Chatty; +Cc: Jiri Kosina, linux-input, Henrik Rydberg
I used hid-lg.c as a reference/example for what was needed and style.
Taking the side of caution, I simply copied the copyright lines from
that file. I have no objection to pruning it as long as there are no
objections. Jiri, you're on that list, what's your feeling on this?
Rafi
Stéphane Chatty wrote:
> Added support for multitouch interaction on the N-Trig touchscreen,
> using the new ABS_MT_* input constants. Single touch support works as
> previously. This code was tested against two versions of the N-Trig
> firmware: one that supports dual pen/finger single touch, and one that
> supports finger multitouch but no pen at all. Copyright notices that
> looked wrong were removed, as it seems that there is only code written
> in 2009 by Rafin Rubin and Stephane Chatty in this file.
--
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] 7+ messages in thread
* Re: [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen
2009-05-19 15:38 ` Stéphane Chatty
@ 2009-05-20 11:00 ` Jiri Kosina
0 siblings, 0 replies; 7+ messages in thread
From: Jiri Kosina @ 2009-05-20 11:00 UTC (permalink / raw)
To: Stéphane Chatty; +Cc: linux-input, Henrik Rydberg, Rafi Rubin
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1101 bytes --]
[ BTW, in all your mails you have @suze.cz as my recepient domain, but
it's in fact @suse.cz, you must be getting bounces for that one :) ]
On Tue, 19 May 2009, Stéphane Chatty wrote:
> > >+ static __s32 x, y, id, w, h;
> > >+ static char reading_a_point = 0, found_contact_id = 0;
> > >+ struct input_dev *input = field->hidinput->input;
> >Why are these variables static? This will break horribly if multiple
> >devices are connected to the system, right?
> You're right. But so far these devices are sold only as embedded in a
> notebook, and I doubt we will see standalone devices in the near future.
> Do you think it is worth planning ahead for this eventuality?
But we should at least be consistent. So at least the driver should
explicitly check whether it is driving more than one device, and if so,
report that this is unsupported configuration.
But I would really prefer doing this cleanly from the start (let's say
allocating per-device structure during probe and storing all these data in
it, let's say).
Would that be possible please?
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen [v3]
2009-05-19 14:50 ` Jiri Kosina
2009-05-19 15:38 ` Stéphane Chatty
2009-05-19 16:50 ` [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen [v2] Stéphane Chatty
@ 2009-05-20 12:30 ` Stéphane Chatty
2 siblings, 0 replies; 7+ messages in thread
From: Stéphane Chatty @ 2009-05-20 12:30 UTC (permalink / raw)
To: linux-input
Cc: Henrik Rydberg, Rafi Rubin, Jiri Kosina, Mohamed Ikbel Boulabiar,
Sebastien Hamdani
Added support for multitouch interaction on the N-Trig touchscreen,
using the new ABS_MT_* input constants. Single touch support works as
previously. This code was tested against two versions of the N- Trig
firmware: one that supports dual pen/finger single touch, and one
that supports finger multitouch but no pen at all. Copyright notices
that looked wrong were removed, as it seems that there is only code
written in 2009 by Rafin Rubin and Stephane Chatty in this file.
Signed-off-by: Stephane Chatty <chatty@enac.fr>
diff -rupN a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
--- a/drivers/hid/hid-ntrig.c 2009-05-09 02:14:14.000000000 +0200
+++ b/drivers/hid/hid-ntrig.c 2009-05-19 22:46:41.000000000 +0200
@@ -1,13 +1,8 @@
/*
- * HID driver for some ntrig "special" devices
+ * HID driver for N-Trig touchscreens
*
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for
Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
- * Copyright (c) 2007 Paul Walmsley
- * Copyright (c) 2008 Jiri Slaby
* Copyright (c) 2008 Rafi Rubin
+ * Copyright (c) 2009 Stephane Chatty
*
*/
@@ -29,15 +24,79 @@
#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
+struct ntrig_data {
+ __s32 x, y, id, w, h;
+ char reading_a_point, found_contact_id;
+};
+
+/*
+ * this driver is aimed at two firmware versions in circulation:
+ * - dual pen/finger single touch
+ * - finger multitouch, pen not working
+ */
+
static int ntrig_input_mapping(struct hid_device *hdev, struct
hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
- if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
- (usage->hid & 0xff) == 0x47) {
- nt_map_key_clear(BTN_TOOL_DOUBLETAP);
- return 1;
+ 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_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);
+ 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) {
+ /* we do not want to map these for now */
+ case HID_DG_INVERT: /* value is always 0 */
+ case HID_DG_ERASER: /* value is always 0 */
+ case HID_DG_CONTACTID: /* value is useless */
+ case HID_DG_BARRELSWITCH: /* doubtful */
+ case HID_DG_INPUTMODE:
+ case HID_DG_DEVICEINDEX:
+ case HID_DG_CONTACTCOUNT:
+ case HID_DG_CONTACTMAX:
+ return -1;
+
+ /* original mapping by Rafi Rubin */
+ case HID_DG_CONFIDENCE:
+ nt_map_key_clear(BTN_TOOL_DOUBLETAP);
+ return 1;
+
+ /* width/height mapped on TouchMajor/TouchMinor/Orientation */
+ 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,
+ 0, 1, 0, 0);
+ return 1;
+ }
+ return 0;
+
+ case 0xff000000:
+ /* we do not want to map these: no input-oriented meaning */
+ return -1;
}
+
return 0;
}
@@ -51,6 +110,138 @@ static int ntrig_input_mapped(struct hid
return 0;
}
+
+/*
+ * this function is called upon all reports
+ * so that we can filter contact point information,
+ * decide whether we are in multi or single touch mode
+ * and call input_mt_sync after each point if necessary
+ */
+static int ntrig_event (struct hid_device *hid, struct hid_field
*field,
+ struct hid_usage *usage, __s32 value)
+{
+ struct input_dev *input = field->hidinput->input;
+ struct ntrig_data *nd = hid_get_drvdata(hid);
+
+ if (hid->claimed & HID_CLAIMED_INPUT) {
+ switch (usage->hid) {
+ case HID_GD_X:
+ nd->x = value;
+ nd->reading_a_point = 1;
+ break;
+ case HID_GD_Y:
+ nd->y = value;
+ break;
+ case HID_DG_CONTACTID:
+ nd->id = value;
+ /* we receive this only when in multitouch mode */
+ nd->found_contact_id = 1;
+ break;
+ case HID_DG_WIDTH:
+ nd->w = value;
+ break;
+ case HID_DG_HEIGHT:
+ nd->h = value;
+ /*
+ * when in single touch mode, this is the last
+ * report received in a finger event. We want
+ * to emit a normal (X, Y) position
+ */
+ if (! nd->found_contact_id) {
+ input_event(input, EV_ABS, ABS_X, nd->x);
+ input_event(input, EV_ABS, ABS_Y, nd->y);
+ }
+ break;
+ case HID_DG_TIPPRESSURE:
+ /*
+ * when in single touch mode, this is the last
+ * report received in a pen event. We want
+ * to emit a normal (X, Y) position
+ */
+ if (! nd->found_contact_id) {
+ input_event(input, EV_ABS, ABS_X, nd->x);
+ input_event(input, EV_ABS, ABS_Y, nd->y);
+ input_event(input, EV_ABS, ABS_PRESSURE, value);
+ }
+ break;
+ case 0xff000002:
+ /*
+ * we receive this when the device is in multitouch
+ * mode. The first of the three values tagged with
+ * this usage tells if the contact point is real
+ * or a placeholder
+ */
+ if (!nd->reading_a_point || value != 1)
+ break;
+ /* emit a normal (X, Y) for the first point only */
+ if (nd->id == 0) {
+ input_event(input, EV_ABS, ABS_X, nd->x);
+ input_event(input, EV_ABS, ABS_Y, nd->y);
+ }
+ input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x);
+ input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y);
+ if (nd->w > nd->h) {
+ input_event(input, EV_ABS,
+ ABS_MT_ORIENTATION, 1);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MAJOR, nd->w);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MINOR, nd->h);
+ } else {
+ input_event(input, EV_ABS,
+ ABS_MT_ORIENTATION, 0);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MAJOR, nd->h);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MINOR, nd->w);
+ }
+ input_mt_sync(field->hidinput->input);
+ nd->reading_a_point = 0;
+ nd->found_contact_id = 0;
+ 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 ntrig_probe(struct hid_device *hdev, const struct
hid_device_id *id)
+{
+ int ret;
+ struct ntrig_data *nd;
+
+ nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL);
+ if (!nd) {
+ dev_err(&hdev->dev, "cannot allocate N-Trig data\n");
+ return -ENOMEM;
+ }
+ nd->reading_a_point = 0;
+ nd->found_contact_id = 0;
+ hid_set_drvdata(hdev, nd);
+
+ ret = hid_parse(hdev);
+ if (!ret)
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+
+ if (ret)
+ kfree (nd);
+ return ret;
+}
+
+static void ntrig_remove(struct hid_device *hdev)
+{
+ hid_hw_stop(hdev);
+ kfree(hid_get_drvdata(hdev));
+}
+
static const struct hid_device_id ntrig_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG,
USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
.driver_data = NTRIG_DUPLICATE_USAGES },
@@ -58,11 +249,20 @@ static const struct hid_device_id ntrig_
};
MODULE_DEVICE_TABLE(hid, ntrig_devices);
+static const struct hid_usage_id ntrig_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 ntrig_driver = {
.name = "ntrig",
.id_table = ntrig_devices,
+ .probe = ntrig_probe,
+ .remove = ntrig_remove,
.input_mapping = ntrig_input_mapping,
.input_mapped = ntrig_input_mapped,
+ .usage_table = ntrig_grabbed_usages,
+ .event = ntrig_event,
};
static int ntrig_init(void)
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-05-20 12:30 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-18 22:11 [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen Stéphane Chatty
2009-05-19 14:50 ` Jiri Kosina
2009-05-19 15:38 ` Stéphane Chatty
2009-05-20 11:00 ` Jiri Kosina
2009-05-19 16:50 ` [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen [v2] Stéphane Chatty
2009-05-19 18:34 ` Rafi Rubin
2009-05-20 12:30 ` [PATCH 3/3] hid: Multitouch support for the N-Trig touchscreen [v3] Stéphane Chatty
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).