summaryrefslogtreecommitdiff
path: root/usr/src/dkms_source_tree
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/dkms_source_tree')
-rw-r--r--usr/src/dkms_source_tree/hid-ntrig.c339
1 files changed, 229 insertions, 110 deletions
diff --git a/usr/src/dkms_source_tree/hid-ntrig.c b/usr/src/dkms_source_tree/hid-ntrig.c
index 70a2ccd..635b44d 100644
--- a/usr/src/dkms_source_tree/hid-ntrig.c
+++ b/usr/src/dkms_source_tree/hid-ntrig.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (c) 2008-2010 Rafi Rubin 4 * Copyright (c) 2008-2010 Rafi Rubin
5 * Copyright (c) 2009-2010 Stephane Chatty 5 * Copyright (c) 2009-2010 Stephane Chatty
6 * Copyright (c) 2010 Canonical, Ltd.
6 * 7 *
7 */ 8 */
8 9
@@ -24,25 +25,87 @@
24void usbhid_submit_report 25void usbhid_submit_report
25(struct hid_device *hid, struct hid_report *report, unsigned char dir); 26(struct hid_device *hid, struct hid_report *report, unsigned char dir);
26 27
28#define hid_to_usb_dev(hid_dev) \
29 container_of(hid_dev->dev.parent->parent, struct usb_device, dev)
30
27#define NTRIG_DUPLICATE_USAGES 0x001 31#define NTRIG_DUPLICATE_USAGES 0x001
28 32
29struct mt_data { 33#define MAX_SLOTS 20
34#define MAX_EVENTS 120
35
36#define SN_MOVE_X 128
37#define SN_MOVE_Y 92
38#define SN_MAJOR 48
39
40#define HOLD_MIN 3
41#define HOLD_MED 7
42#define HOLD_MAX 10
43
44#define DIV_MIN 8
45#define DIV_MED 40
46#define DIV_MAX 100
47
48struct ntrig_contact {
30 int x, y, w, h; 49 int x, y, w, h;
31 int tipswitch;
32 int confidence;
33 int in_range;
34 int foot[4];
35 unsigned int nfoot;
36}; 50};
37 51
38struct ntrig_data { 52struct ntrig_data {
39 unsigned int id; 53 struct ntrig_contact row[MAX_SLOTS], col[MAX_SLOTS];
40 struct mt_data data[16]; 54 int dmin, dmed, dmax;
41 int contactcount; 55 int nrow, ncol;
56 int index, nindex;
57 int nhold;
42}; 58};
43 59
44#define SN_MOVE 100 60
45#define SN_SIZE 50 61/*
62 * This function converts the 4 byte raw firmware code into
63 * a string containing 5 comma separated numbers.
64 */
65static int ntrig_version_string(unsigned char *raw, char *buf)
66{
67 __u8 a = (raw[1] & 0x0e) >> 1;
68 __u8 b = (raw[0] & 0x3c) >> 2;
69 __u8 c = ((raw[0] & 0x03) << 3) | ((raw[3] & 0xe0) >> 5);
70 __u8 d = ((raw[3] & 0x07) << 3) | ((raw[2] & 0xe0) >> 5);
71 __u8 e = raw[2] & 0x07;
72
73 /*
74 * As yet unmapped bits:
75 * 0b11000000 0b11110001 0b00011000 0b00011000
76 */
77
78 return sprintf(buf, "%u.%u.%u.%u.%u", a, b, c, d, e);
79}
80
81static void ntrig_report_version(struct hid_device *hdev)
82{
83 int ret;
84 char buf[20];
85 struct usb_device *usb_dev = hid_to_usb_dev(hdev);
86 unsigned char *data = kmalloc(8, GFP_KERNEL);
87
88 if (!data)
89 goto err_free;
90
91 ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
92 USB_REQ_CLEAR_FEATURE,
93 USB_TYPE_CLASS | USB_RECIP_INTERFACE |
94 USB_DIR_IN,
95 0x30c, 1, data, 8,
96 USB_CTRL_SET_TIMEOUT);
97
98 if (ret == 8) {
99 ret = ntrig_version_string(&data[2], buf);
100
101 dev_info(&hdev->dev,
102 "Firmware version: %s (%02x%02x %02x%02x)\n",
103 buf, data[2], data[3], data[4], data[5]);
104 }
105
106err_free:
107 kfree(data);
108}
46 109
47/* 110/*
48 * this driver is aimed at two firmware versions in circulation: 111 * this driver is aimed at two firmware versions in circulation:
@@ -54,7 +117,11 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
54 struct hid_field *field, struct hid_usage *usage, 117 struct hid_field *field, struct hid_usage *usage,
55 unsigned long **bit, int *max) 118 unsigned long **bit, int *max)
56{ 119{
57 int delta = field->logical_maximum - field->logical_minimum; 120 struct ntrig_data *nd = hid_get_drvdata(hdev);
121 struct input_dev *input = hi->input;
122 int f1 = field->logical_minimum;
123 int f2 = field->logical_maximum;
124 int df = f2 - f1;
58 125
59 /* No special mappings needed for the pen and single touch */ 126 /* No special mappings needed for the pen and single touch */
60 if (field->physical) 127 if (field->physical)
@@ -64,28 +131,21 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
64 case HID_UP_GENDESK: 131 case HID_UP_GENDESK:
65 switch (usage->hid) { 132 switch (usage->hid) {
66 case HID_GD_X: 133 case HID_GD_X:
67 hid_map_usage(hi, usage, bit, max, 134 hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_X);
68 EV_ABS, ABS_MT_POSITION_X); 135 input_set_abs_params(input, ABS_X,
69 input_set_abs_params(hi->input, ABS_MT_POSITION_X, 136 f1, f2, df / SN_MOVE_X, 0);
70 field->logical_minimum, 137 input_set_abs_params(input, ABS_MT_POSITION_X,
71 field->logical_maximum, 138 f1, f2, df / SN_MOVE_X, 0);
72 delta / SN_MOVE, 0); 139 nd->dmin = df / DIV_MIN;
73 input_set_abs_params(hi->input, ABS_X, 140 nd->dmed = df / DIV_MED;
74 field->logical_minimum, 141 nd->dmax = df / DIV_MAX;
75 field->logical_maximum,
76 delta / SN_MOVE, 0);
77 return 1; 142 return 1;
78 case HID_GD_Y: 143 case HID_GD_Y:
79 hid_map_usage(hi, usage, bit, max, 144 hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_Y);
80 EV_ABS, ABS_MT_POSITION_Y); 145 input_set_abs_params(input, ABS_Y,
81 input_set_abs_params(hi->input, ABS_MT_POSITION_Y, 146 f1, f2, df / SN_MOVE_Y, 0);
82 field->logical_minimum, 147 input_set_abs_params(input, ABS_MT_POSITION_Y,
83 field->logical_maximum, 148 f1, f2, df / SN_MOVE_Y, 0);
84 delta / SN_MOVE, 0);
85 input_set_abs_params(hi->input, ABS_Y,
86 field->logical_minimum,
87 field->logical_maximum,
88 delta / SN_MOVE, 0);
89 return 1; 149 return 1;
90 } 150 }
91 return 0; 151 return 0;
@@ -97,26 +157,31 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
97 case HID_DG_INPUTMODE: 157 case HID_DG_INPUTMODE:
98 case HID_DG_DEVICEINDEX: 158 case HID_DG_DEVICEINDEX:
99 case HID_DG_CONTACTMAX: 159 case HID_DG_CONTACTMAX:
160 case HID_DG_CONTACTCOUNT:
161 case HID_DG_INRANGE:
162 case HID_DG_CONFIDENCE:
100 return -1; 163 return -1;
101 164
165 case HID_DG_TIPSWITCH:
166 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
167 input_set_capability(input, EV_KEY, BTN_TOUCH);
168 return 1;
169
102 /* width/height mapped on TouchMajor/TouchMinor/Orientation */ 170 /* width/height mapped on TouchMajor/TouchMinor/Orientation */
103 case HID_DG_WIDTH: 171 case HID_DG_WIDTH:
104 hid_map_usage(hi, usage, bit, max, 172 hid_map_usage(hi, usage, bit, max,
105 EV_ABS, ABS_MT_TOUCH_MAJOR); 173 EV_ABS, ABS_MT_TOUCH_MAJOR);
106 input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR, 174 input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,
107 field->logical_minimum, 175 f1, f2, df / SN_MAJOR, 0);
108 field->logical_maximum,
109 delta / SN_SIZE, 0);
110 return 1; 176 return 1;
111 case HID_DG_HEIGHT: 177 case HID_DG_HEIGHT:
112 hid_map_usage(hi, usage, bit, max, 178 hid_map_usage(hi, usage, bit, max,
113 EV_ABS, ABS_MT_TOUCH_MINOR); 179 EV_ABS, ABS_MT_TOUCH_MINOR);
114 input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR, 180 input_set_abs_params(input, ABS_MT_TOUCH_MINOR,
115 field->logical_minimum, 181 f1, f2, df / SN_MAJOR, 0);
116 field->logical_maximum, 182 input_set_abs_params(input, ABS_MT_ORIENTATION,
117 delta / SN_SIZE, 0); 183 0, 1, 0, 0);
118 input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 184 input_set_events_per_packet(input, MAX_EVENTS);
119 0, 1, 0, 0);
120 return 1; 185 return 1;
121 } 186 }
122 return 0; 187 return 0;
@@ -137,34 +202,123 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
137 if (field->physical) 202 if (field->physical)
138 return 0; 203 return 0;
139 204
140 if (usage->type == EV_KEY || usage->type == EV_REL 205 /* tell hid-input to skip setup of these event types */
141 || usage->type == EV_ABS) 206 if (usage->type == EV_KEY || usage->type == EV_ABS)
142 clear_bit(usage->code, *bit); 207 set_bit(usage->type, hi->input->evbit);
208 return -1;
209}
143 210
144 return 0; 211static bool copy_best_column(struct ntrig_data *nd, unsigned *used, int i)
212{
213 int j, jbest = -1, d, dbest;
214 for (j = 0; j < nd->ncol; ++j) {
215 if (*used & (1 << j))
216 continue;
217 d = abs(nd->row[i].x - nd->col[j].x) +
218 abs(nd->row[i].y - nd->col[j].y);
219 if (jbest < 0 || d < dbest) {
220 jbest = j;
221 dbest = d;
222 }
223 }
224 if (jbest < 0)
225 return false;
226 *used |= (1 << jbest);
227 if (nd->nrow > 2)
228 nd->col[jbest].y = (nd->row[i].y + nd->col[jbest].y) >> 1;
229 nd->row[i] = nd->col[jbest];
230 return true;
231}
232
233static bool copy_next_column(struct ntrig_data *nd, unsigned *used, int i)
234{
235 int j;
236 for (j = 0; j < nd->ncol; ++j) {
237 if (*used & (1 << j))
238 continue;
239 *used |= (1 << j);
240 nd->row[i] = nd->col[j];
241 return true;
242 }
243 return false;
244}
245
246static int ghost_distance(const struct ntrig_data *nd, int j)
247{
248 int i, d, dbest = INT_MAX;
249 for (i = 0; i < nd->nrow; ++i) {
250 d = abs(nd->row[i].x - nd->col[j].x);
251 dbest = min(dbest, d);
252 d = abs(nd->row[i].y - nd->col[j].y);
253 dbest = min(dbest, d);
254 }
255 return dbest;
256}
257
258static void discard_ghosts(struct ntrig_data *nd, unsigned *used)
259{
260 int j, d;
261 for (j = 0; j < nd->ncol; ++j) {
262 if (*used & (1 << j))
263 continue;
264 d = ghost_distance(nd, j);
265 if ((nd->nhold < HOLD_MIN && d < nd->dmin) ||
266 (nd->nhold < HOLD_MED && d < nd->dmed) ||
267 (nd->nhold < HOLD_MAX && d < nd->dmax))
268 *used |= (1 << j);
269 }
145} 270}
146 271
147static void report_frame(struct input_dev *input, struct ntrig_data *nd) 272static void report_frame(struct input_dev *input, struct ntrig_data *nd)
148{ 273{
149 int i, count = nd->contactcount; 274 struct ntrig_contact *oldest = 0;
150 for (i = 0; i < count; i++) { 275 unsigned used = 0;
151 struct mt_data *p = &nd->data[i]; 276 int i;
152 if (i == 0) { 277
153 input_report_key(input, BTN_TOUCH, 1); 278 if (nd->nrow < nd->ncol) {
154 input_report_abs(input, ABS_X, p->x); 279 for (i = 0; i < nd->nrow; ++i)
155 input_report_abs(input, ABS_Y, p->y); 280 copy_best_column(nd, &used, i);
156 } 281 if (nd->ncol > 2)
157 input_report_abs(input, ABS_MT_POSITION_X, p->x); 282 discard_ghosts(nd, &used);
158 input_report_abs(input, ABS_MT_POSITION_Y, p->y); 283 while (copy_next_column(nd, &used, i))
159 input_report_abs(input, ABS_MT_TOUCH_MINOR, p->h); 284 i++;
160 input_report_abs(input, ABS_MT_TOUCH_MAJOR, p->w); 285 nd->nrow = i;
161 input_report_abs(input, ABS_MT_ORIENTATION, p->w > p->h); 286 nd->nhold++;
287 } else if (nd->nrow > nd->ncol) {
288 for (i = 0; i < nd->ncol; ++i)
289 nd->row[i] = nd->col[i];
290 nd->nrow = nd->ncol;
291 nd->nhold = 0;
292 } else {
293 unsigned used = 0;
294 for (i = 0; i < nd->nrow; ++i)
295 copy_best_column(nd, &used, i);
296 nd->nhold = 0;
297 }
298
299 for (i = 0; i < nd->nrow; ++i) {
300 struct ntrig_contact *f = &nd->row[i];
301 int wide = (f->w > f->h);
302 int major = max(f->w, f->h);
303 int minor = min(f->w, f->h);
304 if (!oldest)
305 oldest = f;
306 input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
307 input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
308 input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
309 input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
310 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
162 input_mt_sync(input); 311 input_mt_sync(input);
163 } 312 }
164 if (!count) { 313
165 input_report_key(input, BTN_TOUCH, 0); 314 /* touchscreen emulation */
315 if (oldest) {
316 input_event(input, EV_KEY, BTN_TOUCH, 1);
317 input_event(input, EV_ABS, ABS_X, oldest->x);
318 input_event(input, EV_ABS, ABS_Y, oldest->y);
319 } else {
320 input_event(input, EV_KEY, BTN_TOUCH, 0);
166 } 321 }
167 input_sync(input);
168} 322}
169 323
170/* 324/*
@@ -178,7 +332,6 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
178{ 332{
179 struct input_dev *input = field->hidinput->input; 333 struct input_dev *input = field->hidinput->input;
180 struct ntrig_data *nd = hid_get_drvdata(hid); 334 struct ntrig_data *nd = hid_get_drvdata(hid);
181 struct mt_data *p = &nd->data[nd->id];
182 335
183 /* No special handling needed for the pen */ 336 /* No special handling needed for the pen */
184 if (field->application == HID_DG_PEN) 337 if (field->application == HID_DG_PEN)
@@ -186,49 +339,26 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
186 339
187 if (hid->claimed & HID_CLAIMED_INPUT) { 340 if (hid->claimed & HID_CLAIMED_INPUT) {
188 switch (usage->hid) { 341 switch (usage->hid) {
189 case HID_DG_INRANGE:
190 p->in_range = value;
191 break;
192 /* new mt packet */
193 case 0xff000001:
194 p = &nd->data[nd->id = 0];
195 memset(p, 0, sizeof(*p));
196 break;
197 case HID_DG_TIPSWITCH: 342 case HID_DG_TIPSWITCH:
198 p->tipswitch = value; 343 nd->index = nd->nindex++;
199 break;
200 case HID_DG_CONFIDENCE:
201 p->confidence = value;
202 break;
203 case HID_DG_CONTACTID:
204 p = &nd->data[nd->id = value];
205 memset(p, 0, sizeof(*p));
206 break; 344 break;
207 case HID_GD_X: 345 case HID_GD_X:
208 p->x = value; 346 nd->col[nd->index].x = value;
209 break; 347 break;
210 case HID_GD_Y: 348 case HID_GD_Y:
211 p->y = value; 349 nd->col[nd->index].y = value;
212 break; 350 break;
213 case HID_DG_WIDTH: 351 case HID_DG_WIDTH:
214 p->w = value; 352 nd->col[nd->index].w = value;
215 break; 353 break;
216 case HID_DG_HEIGHT: 354 case HID_DG_HEIGHT:
217 p->h = value; 355 nd->col[nd->index].h = value;
218 break; 356 break;
219 case 0xff000002: 357 case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
220 if (p->nfoot < 4) 358 nd->nindex = 0;
221 p->foot[p->nfoot++] = value; 359 nd->ncol = value;
222 else
223 printk(KERN_INFO "NTRIG: lots %d\n", value);
224 break;
225 case HID_DG_CONTACTCOUNT:
226 nd->contactcount = value;
227 report_frame(input, nd); 360 report_frame(input, nd);
228 break; 361 break;
229
230 default:
231 return 0;
232 } 362 }
233 } 363 }
234 364
@@ -249,7 +379,6 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
249 379
250 if (id->driver_data & NTRIG_DUPLICATE_USAGES) 380 if (id->driver_data & NTRIG_DUPLICATE_USAGES)
251 hdev->quirks |= HID_QUIRK_MULTI_INPUT; 381 hdev->quirks |= HID_QUIRK_MULTI_INPUT;
252 //hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
253 382
254 nd = kzalloc(sizeof(struct ntrig_data), GFP_KERNEL); 383 nd = kzalloc(sizeof(struct ntrig_data), GFP_KERNEL);
255 if (!nd) { 384 if (!nd) {
@@ -274,7 +403,6 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
274 403
275 list_for_each_entry(hidinput, &hdev->inputs, list) { 404 list_for_each_entry(hidinput, &hdev->inputs, list) {
276 if (hidinput->report->maxfield < 1) 405 if (hidinput->report->maxfield < 1)
277
278 continue; 406 continue;
279 407
280 input = hidinput->input; 408 input = hidinput->input;
@@ -283,18 +411,6 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
283 input->name = "N-Trig Pen"; 411 input->name = "N-Trig Pen";
284 break; 412 break;
285 case HID_DG_TOUCHSCREEN: 413 case HID_DG_TOUCHSCREEN:
286 /* These keys are redundant for fingers, clear them
287 * to prevent incorrect identification */
288 __clear_bit(BTN_TOOL_PEN, input->keybit);
289 __clear_bit(BTN_TOOL_FINGER, input->keybit);
290 __clear_bit(BTN_0, input->keybit);
291 __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
292 /*
293 * The physical touchscreen (single touch)
294 * input has a value for physical, whereas
295 * the multitouch only has logical input
296 * fields.
297 */
298 input->name = 414 input->name =
299 (hidinput->report->field[0] 415 (hidinput->report->field[0]
300 ->physical) ? 416 ->physical) ?
@@ -309,6 +425,9 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
309 if (report) 425 if (report)
310 usbhid_submit_report(hdev, report, USB_DIR_OUT); 426 usbhid_submit_report(hdev, report, USB_DIR_OUT);
311 427
428 ntrig_report_version(hdev);
429
430
312 return 0; 431 return 0;
313err_free: 432err_free:
314 kfree(nd); 433 kfree(nd);