diff options
Diffstat (limited to 'bcm5974.c')
| -rw-r--r-- | bcm5974.c | 76 |
1 files changed, 57 insertions, 19 deletions
| @@ -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 | { |
| @@ -229,8 +234,8 @@ static inline int int2bound(const struct bcm5974_param *p, int x) | |||
| 229 | { | 234 | { |
| 230 | int s = int2scale(p, x); | 235 | int s = int2scale(p, x); |
| 231 | 236 | ||
| 232 | // return clamp_val(s, 0, p->dim - 1); | 237 | // return clamp_val(s, 0, p->dim - 1); |
| 233 | return s < 0 ? 0 : s >= p->dim ? p->dim - 1 : s; | 238 | return s < 0 ? 0 : s >= p->dim ? p->dim - 1 : s; |
| 234 | } | 239 | } |
| 235 | 240 | ||
| 236 | /* setup which logical events to report */ | 241 | /* setup which logical events to report */ |
| @@ -275,33 +280,66 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
| 275 | const struct tp_finger *f = dev->tp_data->finger; | 280 | const struct tp_finger *f = dev->tp_data->finger; |
| 276 | struct input_dev *input = dev->input; | 281 | struct input_dev *input = dev->input; |
| 277 | const int fingers = (size - 26) / 28; | 282 | const int fingers = (size - 26) / 28; |
| 278 | int p = 0, w, x, y, n = 0; | 283 | int raw_p, raw_w, raw_x, raw_y; |
| 284 | int ptest = 0, origin = 0, nmin = 0, nmax = 0; | ||
| 285 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; | ||
| 279 | 286 | ||
| 280 | if (size < 26 || (size - 26) % 28 != 0) | 287 | if (size < 26 || (size - 26) % 28 != 0) |
| 281 | return -EIO; | 288 | return -EIO; |
| 282 | 289 | ||
| 290 | /* always track the first finger; when detached, start over */ | ||
| 283 | if (fingers) { | 291 | if (fingers) { |
| 284 | p = raw2int(f->force_major); | 292 | raw_p = raw2int(f->force_major); |
| 285 | w = raw2int(f->size_major); | 293 | raw_w = raw2int(f->size_major); |
| 286 | x = raw2int(f->abs_x); | 294 | raw_x = raw2int(f->abs_x); |
| 287 | y = raw2int(f->abs_y); | 295 | raw_y = raw2int(f->abs_y); |
| 288 | n = p > 0 ? fingers : 0; | ||
| 289 | 296 | ||
| 290 | dprintk(9, | 297 | dprintk(9, |
| 291 | "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", | 298 | "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n", |
| 292 | p, w, x, y, n); | 299 | raw_p, raw_w, raw_x, raw_y); |
| 300 | |||
| 301 | ptest = int2bound(&c->p, raw_p); | ||
| 302 | origin = raw2int(f->origin); | ||
| 303 | } | ||
| 293 | 304 | ||
| 294 | input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w)); | 305 | /* while tracking finger still valid, count all fingers */ |
| 295 | input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin)); | 306 | if (ptest > PRESSURE_LOW && origin) { |
| 296 | input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y)); | 307 | abs_p = ptest; |
| 308 | abs_w = int2bound(&c->w, raw_w); | ||
| 309 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); | ||
| 310 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); | ||
| 311 | for (; f != dev->tp_data->finger + fingers; f++) { | ||
| 312 | ptest = int2bound(&c->p, raw2int(f->force_major)); | ||
| 313 | if (ptest > PRESSURE_LOW) | ||
| 314 | nmax++; | ||
| 315 | if (ptest > PRESSURE_HIGH) | ||
| 316 | nmin++; | ||
| 317 | } | ||
| 297 | } | 318 | } |
| 298 | 319 | ||
| 299 | input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p)); | 320 | if (dev->fingers < nmin) |
| 321 | dev->fingers = nmin; | ||
| 322 | if (dev->fingers > nmax) | ||
| 323 | dev->fingers = nmax; | ||
| 324 | |||
| 325 | input_report_key(input, BTN_TOUCH, dev->fingers > 0); | ||
| 326 | input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); | ||
| 327 | input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); | ||
| 328 | input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2); | ||
| 300 | 329 | ||
| 301 | input_report_key(input, BTN_TOUCH, p > 0); | 330 | input_report_abs(input, ABS_PRESSURE, abs_p); |
| 302 | input_report_key(input, BTN_TOOL_FINGER, n == 1); | 331 | input_report_abs(input, ABS_TOOL_WIDTH, abs_w); |
| 303 | input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2); | 332 | |
| 304 | input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2); | 333 | if (abs_p) { |
| 334 | input_report_abs(input, ABS_X, abs_x); | ||
| 335 | input_report_abs(input, ABS_Y, abs_y); | ||
| 336 | |||
| 337 | dprintk(8, | ||
| 338 | "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " | ||
| 339 | "nmin: %d nmax: %d n: %d\n", | ||
| 340 | abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers); | ||
| 341 | |||
| 342 | } | ||
| 305 | 343 | ||
| 306 | input_sync(input); | 344 | input_sync(input); |
| 307 | 345 | ||
