From 68709066cdbaa0906bca0693f1b721863d0ec954 Mon Sep 17 00:00:00 2001 From: Rafi Rubin Date: Fri, 12 Feb 2010 21:13:05 -0500 Subject: [PATCH] --- yaml --- r: 180853 b: refs/heads/master c: dbf2b17de505d390b5ecf5b5944fc0c88f6d66fe h: refs/heads/master i: 180851: 902af1e244782608432341cc61a9d962585d807e v: v3 --- [refs] | 2 +- trunk/drivers/hid/hid-ntrig.c | 116 +++++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 23 deletions(-) diff --git a/[refs] b/[refs] index b9767cabebf0..cff90ae7fb5b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b0549cf1a35a92edf053d94066e60fb0ed02bb71 +refs/heads/master: dbf2b17de505d390b5ecf5b5944fc0c88f6d66fe diff --git a/trunk/drivers/hid/hid-ntrig.c b/trunk/drivers/hid/hid-ntrig.c index 1bda3a4bd71f..f6f882da6267 100644 --- a/trunk/drivers/hid/hid-ntrig.c +++ b/trunk/drivers/hid/hid-ntrig.c @@ -25,8 +25,16 @@ EV_KEY, (c)) struct ntrig_data { - __s32 x, y, id, w, h; - bool reading_a_point, found_contact_id; + /* Incoming raw values for a single contact */ + __u16 x, y, w, h; + __u16 id; + __u8 confidence; + + bool reading_mt; + __u8 first_contact_confidence; + + __u8 mt_footer[4]; + __u8 mt_foot_count; }; /* @@ -39,8 +47,8 @@ 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) { - /* No special mappings needed for the pen */ - if (field->application == HID_DG_PEN) + /* No special mappings needed for the pen and single touch */ + if (field->physical) return 0; switch (usage->hid & HID_USAGE_PAGE) { @@ -66,18 +74,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,8 +106,8 @@ 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 */ - if (field->application == HID_DG_PEN) + /* No special mappings needed for the pen and single touch */ + if (field->physical) return 0; if (usage->type == EV_KEY || usage->type == EV_REL @@ -133,17 +135,24 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, if (hid->claimed & HID_CLAIMED_INPUT) { switch (usage->hid) { + case 0xff000001: + /* Tag indicating the start of a multitouch group */ + nd->reading_mt = 1; + nd->first_contact_confidence = 0; + break; + 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; @@ -155,7 +164,7 @@ 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->reading_mt) { input_event(input, EV_ABS, ABS_X, nd->x); input_event(input, EV_ABS, ABS_Y, nd->y); } @@ -167,10 +176,34 @@ 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) { + nd->first_contact_confidence = nd->confidence; input_event(input, EV_ABS, ABS_X, nd->x); input_event(input, EV_ABS, ABS_Y, nd->y); } @@ -192,8 +225,39 @@ 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_confidence) { + switch (value) { + case 0: /* for single touch devices */ + case 1: + input_report_key(input, + BTN_TOOL_DOUBLETAP, 1); + break; + case 2: + input_report_key(input, + BTN_TOOL_TRIPLETAP, 1); + break; + case 3: + default: + input_report_key(input, + BTN_TOOL_QUADTAP, 1); + } + input_report_key(input, BTN_TOUCH, 1); + } else { + input_report_key(input, + BTN_TOOL_DOUBLETAP, 0); + input_report_key(input, + BTN_TOOL_TRIPLETAP, 0); + input_report_key(input, + BTN_TOOL_QUADTAP, 0); + } break; default: @@ -224,8 +288,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) 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); @@ -248,6 +312,14 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) input->name = "N-Trig Pen"; break; case HID_DG_TOUCHSCREEN: + __clear_bit(BTN_TOOL_PEN, input->keybit); + /* + * A little something special to enable + * two and three finger taps. + */ + __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); + __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); + __set_bit(BTN_TOOL_QUADTAP, input->keybit); /* * The physical touchscreen (single touch) * input has a value for physical, whereas