diff options
-rw-r--r-- | drivers/input/mouse/bcm5974.c | 70 |
1 files changed, 54 insertions, 16 deletions
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index ae78bb833f62..8568211c5564 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -105,7 +105,7 @@ struct tp_header { | |||
105 | 105 | ||
106 | /* trackpad finger structure */ | 106 | /* trackpad finger structure */ |
107 | struct tp_finger { | 107 | struct tp_finger { |
108 | __le16 origin; /* left/right origin? */ | 108 | __le16 origin; /* zero when switching track finger */ |
109 | __le16 abs_x; /* absolute x coodinate */ | 109 | __le16 abs_x; /* absolute x coodinate */ |
110 | __le16 abs_y; /* absolute y coodinate */ | 110 | __le16 abs_y; /* absolute y coodinate */ |
111 | __le16 rel_x; /* relative x coodinate */ | 111 | __le16 rel_x; /* relative x coodinate */ |
@@ -159,6 +159,7 @@ struct bcm5974 { | |||
159 | struct bt_data *bt_data; /* button transferred data */ | 159 | struct bt_data *bt_data; /* button transferred data */ |
160 | struct urb *tp_urb; /* trackpad usb request block */ | 160 | struct urb *tp_urb; /* trackpad usb request block */ |
161 | struct tp_data *tp_data; /* trackpad transferred data */ | 161 | struct tp_data *tp_data; /* trackpad transferred data */ |
162 | int fingers; /* number of fingers on trackpad */ | ||
162 | }; | 163 | }; |
163 | 164 | ||
164 | /* logical dimensions */ | 165 | /* logical dimensions */ |
@@ -172,6 +173,10 @@ struct bcm5974 { | |||
172 | #define SN_WIDTH 100 /* width signal-to-noise ratio */ | 173 | #define SN_WIDTH 100 /* width signal-to-noise ratio */ |
173 | #define SN_COORD 250 /* coordinate signal-to-noise ratio */ | 174 | #define SN_COORD 250 /* coordinate signal-to-noise ratio */ |
174 | 175 | ||
176 | /* pressure thresholds */ | ||
177 | #define PRESSURE_LOW (2 * DIM_PRESSURE / SN_PRESSURE) | ||
178 | #define PRESSURE_HIGH (3 * PRESSURE_LOW) | ||
179 | |||
175 | /* device constants */ | 180 | /* device constants */ |
176 | static const struct bcm5974_config bcm5974_config_table[] = { | 181 | static const struct bcm5974_config bcm5974_config_table[] = { |
177 | { | 182 | { |
@@ -273,32 +278,65 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
273 | const struct tp_finger *f = dev->tp_data->finger; | 278 | const struct tp_finger *f = dev->tp_data->finger; |
274 | struct input_dev *input = dev->input; | 279 | struct input_dev *input = dev->input; |
275 | const int fingers = (size - 26) / 28; | 280 | const int fingers = (size - 26) / 28; |
276 | int p = 0, w, x, y, n = 0; | 281 | int raw_p, raw_w, raw_x, raw_y; |
282 | int ptest = 0, origin = 0, nmin = 0, nmax = 0; | ||
283 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; | ||
277 | 284 | ||
278 | if (size < 26 || (size - 26) % 28 != 0) | 285 | if (size < 26 || (size - 26) % 28 != 0) |
279 | return -EIO; | 286 | return -EIO; |
280 | 287 | ||
288 | /* always track the first finger; when detached, start over */ | ||
281 | if (fingers) { | 289 | if (fingers) { |
282 | p = raw2int(f->force_major); | 290 | raw_p = raw2int(f->force_major); |
283 | w = raw2int(f->size_major); | 291 | raw_w = raw2int(f->size_major); |
284 | x = raw2int(f->abs_x); | 292 | raw_x = raw2int(f->abs_x); |
285 | y = raw2int(f->abs_y); | 293 | raw_y = raw2int(f->abs_y); |
286 | n = p > 0 ? fingers : 0; | ||
287 | 294 | ||
288 | dprintk(9, | 295 | dprintk(9, |
289 | "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", | 296 | "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n", |
290 | p, w, x, y, n); | 297 | raw_p, raw_w, raw_x, raw_y); |
298 | |||
299 | ptest = int2bound(&c->p, raw_p); | ||
300 | origin = raw2int(f->origin); | ||
301 | } | ||
291 | 302 | ||
292 | input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w)); | 303 | /* while tracking finger still valid, count all fingers */ |
293 | input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin)); | 304 | if (ptest > PRESSURE_LOW && origin) { |
294 | input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y)); | 305 | abs_p = ptest; |
306 | abs_w = int2bound(&c->w, raw_w); | ||
307 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); | ||
308 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); | ||
309 | for (; f != dev->tp_data->finger + fingers; f++) { | ||
310 | ptest = int2bound(&c->p, raw2int(f->force_major)); | ||
311 | if (ptest > PRESSURE_LOW) | ||
312 | nmax++; | ||
313 | if (ptest > PRESSURE_HIGH) | ||
314 | nmin++; | ||
315 | } | ||
295 | } | 316 | } |
296 | 317 | ||
297 | input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p)); | 318 | if (dev->fingers < nmin) |
319 | dev->fingers = nmin; | ||
320 | if (dev->fingers > nmax) | ||
321 | dev->fingers = nmax; | ||
322 | |||
323 | input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); | ||
324 | input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); | ||
325 | input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2); | ||
298 | 326 | ||
299 | input_report_key(input, BTN_TOOL_FINGER, n == 1); | 327 | input_report_abs(input, ABS_PRESSURE, abs_p); |
300 | input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2); | 328 | input_report_abs(input, ABS_TOOL_WIDTH, abs_w); |
301 | input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2); | 329 | |
330 | if (abs_p) { | ||
331 | input_report_abs(input, ABS_X, abs_x); | ||
332 | input_report_abs(input, ABS_Y, abs_y); | ||
333 | |||
334 | dprintk(8, | ||
335 | "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " | ||
336 | "nmin: %d nmax: %d n: %d\n", | ||
337 | abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers); | ||
338 | |||
339 | } | ||
302 | 340 | ||
303 | input_sync(input); | 341 | input_sync(input); |
304 | 342 | ||