aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-ntrig.c116
1 files changed, 94 insertions, 22 deletions
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index 1bda3a4bd71f..f6f882da6267 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -25,8 +25,16 @@
25 EV_KEY, (c)) 25 EV_KEY, (c))
26 26
27struct ntrig_data { 27struct ntrig_data {
28 __s32 x, y, id, w, h; 28 /* Incoming raw values for a single contact */
29 bool reading_a_point, found_contact_id; 29 __u16 x, y, w, h;
30 __u16 id;
31 __u8 confidence;
32
33 bool reading_mt;
34 __u8 first_contact_confidence;
35
36 __u8 mt_footer[4];
37 __u8 mt_foot_count;
30}; 38};
31 39
32/* 40/*
@@ -39,8 +47,8 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
39 struct hid_field *field, struct hid_usage *usage, 47 struct hid_field *field, struct hid_usage *usage,
40 unsigned long **bit, int *max) 48 unsigned long **bit, int *max)
41{ 49{
42 /* No special mappings needed for the pen */ 50 /* No special mappings needed for the pen and single touch */
43 if (field->application == HID_DG_PEN) 51 if (field->physical)
44 return 0; 52 return 0;
45 53
46 switch (usage->hid & HID_USAGE_PAGE) { 54 switch (usage->hid & HID_USAGE_PAGE) {
@@ -66,18 +74,12 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
66 case HID_UP_DIGITIZER: 74 case HID_UP_DIGITIZER:
67 switch (usage->hid) { 75 switch (usage->hid) {
68 /* we do not want to map these for now */ 76 /* we do not want to map these for now */
69 case HID_DG_CONTACTID: /* value is useless */ 77 case HID_DG_CONTACTID: /* Not trustworthy, squelch for now */
70 case HID_DG_INPUTMODE: 78 case HID_DG_INPUTMODE:
71 case HID_DG_DEVICEINDEX: 79 case HID_DG_DEVICEINDEX:
72 case HID_DG_CONTACTCOUNT:
73 case HID_DG_CONTACTMAX: 80 case HID_DG_CONTACTMAX:
74 return -1; 81 return -1;
75 82
76 /* original mapping by Rafi Rubin */
77 case HID_DG_CONFIDENCE:
78 nt_map_key_clear(BTN_TOOL_DOUBLETAP);
79 return 1;
80
81 /* width/height mapped on TouchMajor/TouchMinor/Orientation */ 83 /* width/height mapped on TouchMajor/TouchMinor/Orientation */
82 case HID_DG_WIDTH: 84 case HID_DG_WIDTH:
83 hid_map_usage(hi, usage, bit, max, 85 hid_map_usage(hi, usage, bit, max,
@@ -104,8 +106,8 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
104 struct hid_field *field, struct hid_usage *usage, 106 struct hid_field *field, struct hid_usage *usage,
105 unsigned long **bit, int *max) 107 unsigned long **bit, int *max)
106{ 108{
107 /* No special mappings needed for the pen */ 109 /* No special mappings needed for the pen and single touch */
108 if (field->application == HID_DG_PEN) 110 if (field->physical)
109 return 0; 111 return 0;
110 112
111 if (usage->type == EV_KEY || usage->type == EV_REL 113 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,
133 135
134 if (hid->claimed & HID_CLAIMED_INPUT) { 136 if (hid->claimed & HID_CLAIMED_INPUT) {
135 switch (usage->hid) { 137 switch (usage->hid) {
138 case 0xff000001:
139 /* Tag indicating the start of a multitouch group */
140 nd->reading_mt = 1;
141 nd->first_contact_confidence = 0;
142 break;
143 case HID_DG_CONFIDENCE:
144 nd->confidence = value;
145 break;
136 case HID_GD_X: 146 case HID_GD_X:
137 nd->x = value; 147 nd->x = value;
138 nd->reading_a_point = 1; 148 /* Clear the contact footer */
149 nd->mt_foot_count = 0;
139 break; 150 break;
140 case HID_GD_Y: 151 case HID_GD_Y:
141 nd->y = value; 152 nd->y = value;
142 break; 153 break;
143 case HID_DG_CONTACTID: 154 case HID_DG_CONTACTID:
144 nd->id = value; 155 nd->id = value;
145 /* we receive this only when in multitouch mode */
146 nd->found_contact_id = 1;
147 break; 156 break;
148 case HID_DG_WIDTH: 157 case HID_DG_WIDTH:
149 nd->w = value; 158 nd->w = value;
@@ -155,7 +164,7 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
155 * report received in a finger event. We want 164 * report received in a finger event. We want
156 * to emit a normal (X, Y) position 165 * to emit a normal (X, Y) position
157 */ 166 */
158 if (!nd->found_contact_id) { 167 if (!nd->reading_mt) {
159 input_event(input, EV_ABS, ABS_X, nd->x); 168 input_event(input, EV_ABS, ABS_X, nd->x);
160 input_event(input, EV_ABS, ABS_Y, nd->y); 169 input_event(input, EV_ABS, ABS_Y, nd->y);
161 } 170 }
@@ -167,10 +176,34 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
167 * this usage tells if the contact point is real 176 * this usage tells if the contact point is real
168 * or a placeholder 177 * or a placeholder
169 */ 178 */
170 if (!nd->reading_a_point || value != 1) 179
180 /* Shouldn't get more than 4 footer packets, so skip */
181 if (nd->mt_foot_count >= 4)
182 break;
183
184 nd->mt_footer[nd->mt_foot_count++] = value;
185
186 /* if the footer isn't complete break */
187 if (nd->mt_foot_count != 4)
188 break;
189
190 /* Pen activity signal, trigger end of touch. */
191 if (nd->mt_footer[2]) {
192 nd->confidence = 0;
193 break;
194 }
195
196 /* If the contact was invalid */
197 if (!(nd->confidence && nd->mt_footer[0])
198 || nd->w <= 250
199 || nd->h <= 190) {
200 nd->confidence = 0;
171 break; 201 break;
202 }
203
172 /* emit a normal (X, Y) for the first point only */ 204 /* emit a normal (X, Y) for the first point only */
173 if (nd->id == 0) { 205 if (nd->id == 0) {
206 nd->first_contact_confidence = nd->confidence;
174 input_event(input, EV_ABS, ABS_X, nd->x); 207 input_event(input, EV_ABS, ABS_X, nd->x);
175 input_event(input, EV_ABS, ABS_Y, nd->y); 208 input_event(input, EV_ABS, ABS_Y, nd->y);
176 } 209 }
@@ -192,8 +225,39 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
192 ABS_MT_TOUCH_MINOR, nd->w); 225 ABS_MT_TOUCH_MINOR, nd->w);
193 } 226 }
194 input_mt_sync(field->hidinput->input); 227 input_mt_sync(field->hidinput->input);
195 nd->reading_a_point = 0; 228 break;
196 nd->found_contact_id = 0; 229
230 case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
231 if (!nd->reading_mt)
232 break;
233
234 nd->reading_mt = 0;
235
236 if (nd->first_contact_confidence) {
237 switch (value) {
238 case 0: /* for single touch devices */
239 case 1:
240 input_report_key(input,
241 BTN_TOOL_DOUBLETAP, 1);
242 break;
243 case 2:
244 input_report_key(input,
245 BTN_TOOL_TRIPLETAP, 1);
246 break;
247 case 3:
248 default:
249 input_report_key(input,
250 BTN_TOOL_QUADTAP, 1);
251 }
252 input_report_key(input, BTN_TOUCH, 1);
253 } else {
254 input_report_key(input,
255 BTN_TOOL_DOUBLETAP, 0);
256 input_report_key(input,
257 BTN_TOOL_TRIPLETAP, 0);
258 input_report_key(input,
259 BTN_TOOL_QUADTAP, 0);
260 }
197 break; 261 break;
198 262
199 default: 263 default:
@@ -224,8 +288,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
224 dev_err(&hdev->dev, "cannot allocate N-Trig data\n"); 288 dev_err(&hdev->dev, "cannot allocate N-Trig data\n");
225 return -ENOMEM; 289 return -ENOMEM;
226 } 290 }
227 nd->reading_a_point = 0; 291
228 nd->found_contact_id = 0; 292 nd->reading_mt = 0;
229 hid_set_drvdata(hdev, nd); 293 hid_set_drvdata(hdev, nd);
230 294
231 ret = hid_parse(hdev); 295 ret = hid_parse(hdev);
@@ -248,6 +312,14 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
248 input->name = "N-Trig Pen"; 312 input->name = "N-Trig Pen";
249 break; 313 break;
250 case HID_DG_TOUCHSCREEN: 314 case HID_DG_TOUCHSCREEN:
315 __clear_bit(BTN_TOOL_PEN, input->keybit);
316 /*
317 * A little something special to enable
318 * two and three finger taps.
319 */
320 __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
321 __set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
322 __set_bit(BTN_TOOL_QUADTAP, input->keybit);
251 /* 323 /*
252 * The physical touchscreen (single touch) 324 * The physical touchscreen (single touch)
253 * input has a value for physical, whereas 325 * input has a value for physical, whereas