513 lines
15 KiB
Diff
513 lines
15 KiB
Diff
commit 094693bee2b1fd8628846040f4a07cc4725b6011
|
|
Author: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Date: Mon May 3 05:08:30 2010 -0400
|
|
|
|
HID: ntrig: Remove unused macro, TripleTap and QuadTap
|
|
|
|
Removing the higher number taps. Their usage was incorrect
|
|
and even if correct they should not be used for a touch screen.
|
|
_MT_ events should be used to communicate multiple fingers.
|
|
|
|
Signed-off-by: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
|
|
commit e4ca1ed6c39920c6be60e26c8b1c61b82792906b
|
|
Author: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Date: Mon May 3 05:08:29 2010 -0400
|
|
|
|
HID: ntrig: TipSwitch for single touch mode touch.
|
|
|
|
Include TipSwitch in the touch detection decision for some single touch
|
|
firmwares. Confidence and InRange are high for all finger events
|
|
including those used to indicate the finger is no longer in contact with
|
|
the sensor.
|
|
|
|
Signed-off-by: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
|
|
commit 2a85cd7c45cf219fe27e5f8c031f954fdec637fd
|
|
Author: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Date: Fri Apr 9 17:58:25 2010 -0400
|
|
|
|
HID: ntrig: Emit TOUCH with DOUBLETAP for single touch
|
|
|
|
I squelched TipSwitch in a recent patch which resulted in the loss
|
|
of Touch events for single touch firmwares. This patch just puts Touch back
|
|
in for single touch, and bundles it with DoubleTap (like the multitouch code).
|
|
The two events are used to convey the same message to different drivers.
|
|
|
|
Signed-off-by: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
|
|
commit 811b16c09476e2a72736dd55f3fe62549c4d722c
|
|
Author: Jiri Kosina <jkosina@suse.cz>
|
|
Date: Wed Apr 7 12:10:29 2010 +0200
|
|
|
|
HID: ntrig: explain firmware quirk
|
|
|
|
Commit 6549981bc54777c ("HID: fix N-trig touch panel with recent firmware")
|
|
adds a quirk that is needed for devices with more recent firmware so that
|
|
they become operational.
|
|
|
|
As it's not directly obvious from the code why is it needed, a comment
|
|
is worthwile.
|
|
|
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
|
|
commit aa604050185ad5b17e8bf838d73d76382ee3e3e5
|
|
Author: Stephane Chatty <chatty@lii-enac.fr>
|
|
Date: Tue Apr 6 22:22:58 2010 +0200
|
|
|
|
HID: fix N-trig touch panel with recent firmware
|
|
|
|
Added an init message that avoids device freeze with recent firmware.
|
|
|
|
Signed-off-by: Stephane Chatty <chatty@enac.fr>
|
|
Tested-by: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
|
|
commit 26196d5d0f6884f632e978103f435e2ba001a7ce
|
|
Author: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Date: Wed Mar 10 16:10:28 2010 +0100
|
|
|
|
HID: ntrig: fix touch events
|
|
|
|
This reinstates the lost unpressing of BTN_TOUCH. To prevent undesireably
|
|
touch toggles this also deals with tip switch events.
|
|
|
|
Added a trap to prevent going out of bounds for hidinputs with empty reports.
|
|
|
|
Clear bits of unused buttons which result in misidentification.
|
|
|
|
Signed-off-by: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
|
|
commit 04b1217771e454eea260d5cf8e66fa75cd7863bf
|
|
Author: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Date: Tue Feb 16 10:22:11 2010 -0500
|
|
|
|
HID: hid-ntrig: Single touch mode tap
|
|
|
|
Add DOUBLETAP to events emitted when in single touch only mode.
|
|
|
|
Users with a single touch firmware report not seeing the DOUBLETAP events; this
|
|
is a side effect of dropping old mapping for confidence. The confidence mapping
|
|
may be fine for singletouch mode but causes problems in multitouch mode.
|
|
|
|
Signed-off-by: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
|
|
commit 52bd98e1c2e3b0587f8c45c15f3ff8af69353044
|
|
Author: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Date: Fri Feb 12 21:13:05 2010 -0500
|
|
|
|
HID: hid-ntrig: multitouch cleanup and fix
|
|
|
|
This cleans up the identification of multitouch groups and enables
|
|
the end of group sync.
|
|
|
|
Taps are now explicitly handled to adjust for the changes in the
|
|
event stream in multitouch mode. Added triple and quad tap for the
|
|
benefit of tools that recognize different tap types but do not have
|
|
full multi touch support.
|
|
|
|
This cleans up the behavior particularly for the latest firmware, which
|
|
didn't work particularly well with the older version of the driver.
|
|
|
|
In this form, when multitouch is active, both mt and st events will come out of
|
|
the "N-Trig MultiTouch" device. And when its not st events will come out of
|
|
"N-Trig Touchscreen".
|
|
|
|
Signed-off-by: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
|
|
commit 9ff5ed6b935929019c459e4d853c3afe52a4d8f2
|
|
Author: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Date: Thu Feb 11 22:14:06 2010 -0500
|
|
|
|
HID: n-trig: remove unnecessary tool switching
|
|
|
|
With the pen and touch split apart, we no longer need to inject
|
|
additional tool switching events.
|
|
|
|
Signed-off-by: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
|
|
commit 0336d54acf59a4ccd97fc9d983518c6d60639f5b
|
|
Author: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Date: Thu Feb 11 22:14:05 2010 -0500
|
|
|
|
HID: hid-ntrig add multi input quirk and clean up
|
|
|
|
Added a quirk to enable distinct input devices. The digitizer utilizes
|
|
three inputs to represent pen, multitouch and a normal touch screen.
|
|
|
|
With the Pen partitioned, it behaves well and does not need special
|
|
handling.
|
|
|
|
Also, I set names to the input devices to clarify the functions of the
|
|
various inputs.
|
|
|
|
Signed-off-by: Rafi Rubin <rafi@seas.upenn.edu>
|
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
|
|
drivers/hid/hid-ntrig.c | 229 ++++++++++++++++++++++++++++++++--------------
|
|
1 files changed, 159 insertions(+), 70 deletions(-)
|
|
|
|
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
|
|
index 49ce69d..836a4ba 100644
|
|
--- a/drivers/hid/hid-ntrig.c
|
|
+++ b/drivers/hid/hid-ntrig.c
|
|
@@ -1,8 +1,8 @@
|
|
/*
|
|
* HID driver for N-Trig touchscreens
|
|
*
|
|
- * Copyright (c) 2008 Rafi Rubin
|
|
- * Copyright (c) 2009 Stephane Chatty
|
|
+ * Copyright (c) 2008-2010 Rafi Rubin
|
|
+ * Copyright (c) 2009-2010 Stephane Chatty
|
|
*
|
|
*/
|
|
|
|
@@ -15,21 +15,27 @@
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/hid.h>
|
|
+#include <linux/usb.h>
|
|
+#include "usbhid/usbhid.h"
|
|
#include <linux/module.h>
|
|
|
|
#include "hid-ids.h"
|
|
|
|
#define NTRIG_DUPLICATE_USAGES 0x001
|
|
|
|
-#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;
|
|
- char pen_active;
|
|
- char finger_active;
|
|
- char inverted;
|
|
+ /* Incoming raw values for a single contact */
|
|
+ __u16 x, y, w, h;
|
|
+ __u16 id;
|
|
+
|
|
+ bool tipswitch;
|
|
+ bool confidence;
|
|
+ bool first_contact_touch;
|
|
+
|
|
+ bool reading_mt;
|
|
+
|
|
+ __u8 mt_footer[4];
|
|
+ __u8 mt_foot_count;
|
|
};
|
|
|
|
/*
|
|
@@ -42,8 +48,11 @@ 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)
|
|
{
|
|
- switch (usage->hid & HID_USAGE_PAGE) {
|
|
+ /* No special mappings needed for the pen and single touch */
|
|
+ if (field->physical)
|
|
+ return 0;
|
|
|
|
+ switch (usage->hid & HID_USAGE_PAGE) {
|
|
case HID_UP_GENDESK:
|
|
switch (usage->hid) {
|
|
case HID_GD_X:
|
|
@@ -66,18 +75,12 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|
case HID_UP_DIGITIZER:
|
|
switch (usage->hid) {
|
|
/* we do not want to map these for now */
|
|
- case HID_DG_CONTACTID: /* value is useless */
|
|
+ case HID_DG_CONTACTID: /* Not trustworthy, squelch for now */
|
|
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,
|
|
@@ -104,6 +107,10 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
|
struct hid_field *field, struct hid_usage *usage,
|
|
unsigned long **bit, int *max)
|
|
{
|
|
+ /* No special mappings needed for the pen and single touch */
|
|
+ if (field->physical)
|
|
+ return 0;
|
|
+
|
|
if (usage->type == EV_KEY || usage->type == EV_REL
|
|
|| usage->type == EV_ABS)
|
|
clear_bit(usage->code, *bit);
|
|
@@ -123,31 +130,34 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
|
|
struct input_dev *input = field->hidinput->input;
|
|
struct ntrig_data *nd = hid_get_drvdata(hid);
|
|
|
|
+ /* No special handling needed for the pen */
|
|
+ if (field->application == HID_DG_PEN)
|
|
+ return 0;
|
|
+
|
|
if (hid->claimed & HID_CLAIMED_INPUT) {
|
|
switch (usage->hid) {
|
|
-
|
|
- case HID_DG_INRANGE:
|
|
- if (field->application & 0x3)
|
|
- nd->pen_active = (value != 0);
|
|
- else
|
|
- nd->finger_active = (value != 0);
|
|
- return 0;
|
|
-
|
|
- case HID_DG_INVERT:
|
|
- nd->inverted = value;
|
|
- return 0;
|
|
-
|
|
+ case 0xff000001:
|
|
+ /* Tag indicating the start of a multitouch group */
|
|
+ nd->reading_mt = 1;
|
|
+ nd->first_contact_touch = 0;
|
|
+ break;
|
|
+ case HID_DG_TIPSWITCH:
|
|
+ nd->tipswitch = value;
|
|
+ /* Prevent emission of touch until validated */
|
|
+ return 1;
|
|
+ case HID_DG_CONFIDENCE:
|
|
+ nd->confidence = value;
|
|
+ break;
|
|
case HID_GD_X:
|
|
nd->x = value;
|
|
- nd->reading_a_point = 1;
|
|
+ /* Clear the contact footer */
|
|
+ nd->mt_foot_count = 0;
|
|
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;
|
|
@@ -159,33 +169,17 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
|
|
* report received in a finger event. We want
|
|
* to emit a normal (X, Y) position
|
|
*/
|
|
- if (!nd->found_contact_id) {
|
|
- if (nd->pen_active && nd->finger_active) {
|
|
- input_report_key(input, BTN_TOOL_DOUBLETAP, 0);
|
|
- input_report_key(input, BTN_TOOL_DOUBLETAP, 1);
|
|
- }
|
|
- 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) {
|
|
- if (nd->pen_active && nd->finger_active) {
|
|
- input_report_key(input,
|
|
- nd->inverted ? BTN_TOOL_RUBBER : BTN_TOOL_PEN
|
|
- , 0);
|
|
- input_report_key(input,
|
|
- nd->inverted ? BTN_TOOL_RUBBER : BTN_TOOL_PEN
|
|
- , 1);
|
|
- }
|
|
+ if (!nd->reading_mt) {
|
|
+ /*
|
|
+ * TipSwitch indicates the presence of a
|
|
+ * finger in single touch mode.
|
|
+ */
|
|
+ input_report_key(input, BTN_TOUCH,
|
|
+ nd->tipswitch);
|
|
+ input_report_key(input, BTN_TOOL_DOUBLETAP,
|
|
+ nd->tipswitch);
|
|
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:
|
|
@@ -195,10 +189,40 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
|
|
* this usage tells if the contact point is real
|
|
* or a placeholder
|
|
*/
|
|
- if (!nd->reading_a_point || value != 1)
|
|
+
|
|
+ /* Shouldn't get more than 4 footer packets, so skip */
|
|
+ if (nd->mt_foot_count >= 4)
|
|
break;
|
|
+
|
|
+ nd->mt_footer[nd->mt_foot_count++] = value;
|
|
+
|
|
+ /* if the footer isn't complete break */
|
|
+ if (nd->mt_foot_count != 4)
|
|
+ break;
|
|
+
|
|
+ /* Pen activity signal, trigger end of touch. */
|
|
+ if (nd->mt_footer[2]) {
|
|
+ nd->confidence = 0;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* If the contact was invalid */
|
|
+ if (!(nd->confidence && nd->mt_footer[0])
|
|
+ || nd->w <= 250
|
|
+ || nd->h <= 190) {
|
|
+ nd->confidence = 0;
|
|
+ break;
|
|
+ }
|
|
+
|
|
/* emit a normal (X, Y) for the first point only */
|
|
if (nd->id == 0) {
|
|
+ /*
|
|
+ * TipSwitch is superfluous in multitouch
|
|
+ * mode. The footer events tell us
|
|
+ * if there is a finger on the screen or
|
|
+ * not.
|
|
+ */
|
|
+ nd->first_contact_touch = nd->confidence;
|
|
input_event(input, EV_ABS, ABS_X, nd->x);
|
|
input_event(input, EV_ABS, ABS_Y, nd->y);
|
|
}
|
|
@@ -220,8 +244,21 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
|
|
ABS_MT_TOUCH_MINOR, nd->w);
|
|
}
|
|
input_mt_sync(field->hidinput->input);
|
|
- nd->reading_a_point = 0;
|
|
- nd->found_contact_id = 0;
|
|
+ break;
|
|
+
|
|
+ case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
|
|
+ if (!nd->reading_mt)
|
|
+ break;
|
|
+
|
|
+ nd->reading_mt = 0;
|
|
+
|
|
+ if (nd->first_contact_touch) {
|
|
+ input_report_key(input, BTN_TOOL_DOUBLETAP, 1);
|
|
+ input_report_key(input, BTN_TOUCH, 1);
|
|
+ } else {
|
|
+ input_report_key(input, BTN_TOOL_DOUBLETAP, 0);
|
|
+ input_report_key(input, BTN_TOUCH, 0);
|
|
+ }
|
|
break;
|
|
|
|
default:
|
|
@@ -231,8 +268,8 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
|
|
}
|
|
|
|
/* 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);
|
|
+ if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event)
|
|
+ hid->hiddev_hid_event(hid, field, usage, value);
|
|
|
|
return 1;
|
|
}
|
|
@@ -241,23 +278,75 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|
{
|
|
int ret;
|
|
struct ntrig_data *nd;
|
|
+ struct hid_input *hidinput;
|
|
+ struct input_dev *input;
|
|
+ struct hid_report *report;
|
|
+
|
|
+ if (id->driver_data)
|
|
+ hdev->quirks |= HID_QUIRK_MULTI_INPUT;
|
|
|
|
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;
|
|
+
|
|
+ nd->reading_mt = 0;
|
|
hid_set_drvdata(hdev, nd);
|
|
|
|
ret = hid_parse(hdev);
|
|
- if (!ret)
|
|
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
|
+ if (ret) {
|
|
+ dev_err(&hdev->dev, "parse failed\n");
|
|
+ goto err_free;
|
|
+ }
|
|
+
|
|
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
|
+ if (ret) {
|
|
+ dev_err(&hdev->dev, "hw start failed\n");
|
|
+ goto err_free;
|
|
+ }
|
|
+
|
|
+
|
|
+ list_for_each_entry(hidinput, &hdev->inputs, list) {
|
|
+ if (hidinput->report->maxfield < 1)
|
|
+ continue;
|
|
+
|
|
+ input = hidinput->input;
|
|
+ switch (hidinput->report->field[0]->application) {
|
|
+ case HID_DG_PEN:
|
|
+ input->name = "N-Trig Pen";
|
|
+ break;
|
|
+ case HID_DG_TOUCHSCREEN:
|
|
+ /* These keys are redundant for fingers, clear them
|
|
+ * to prevent incorrect identification */
|
|
+ __clear_bit(BTN_TOOL_PEN, input->keybit);
|
|
+ __clear_bit(BTN_TOOL_FINGER, input->keybit);
|
|
+ __clear_bit(BTN_0, input->keybit);
|
|
+ __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
|
|
+ /*
|
|
+ * The physical touchscreen (single touch)
|
|
+ * input has a value for physical, whereas
|
|
+ * the multitouch only has logical input
|
|
+ * fields.
|
|
+ */
|
|
+ input->name =
|
|
+ (hidinput->report->field[0]
|
|
+ ->physical) ?
|
|
+ "N-Trig Touchscreen" :
|
|
+ "N-Trig MultiTouch";
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
|
|
- if (ret)
|
|
- kfree (nd);
|
|
+ /* This is needed for devices with more recent firmware versions */
|
|
+ report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a];
|
|
+ if (report)
|
|
+ usbhid_submit_report(hdev, report, USB_DIR_OUT);
|
|
|
|
+
|
|
+ return 0;
|
|
+err_free:
|
|
+ kfree(nd);
|
|
return ret;
|
|
}
|
|
|
|
@@ -276,7 +365,7 @@ 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}
|
|
+ { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1 }
|
|
};
|
|
|
|
static struct hid_driver ntrig_driver = {
|