aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/mouse/bcm5974.c70
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 */
107struct tp_finger { 107struct 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 */
176static const struct bcm5974_config bcm5974_config_table[] = { 181static 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