Input: zinitix - do not report shadow fingers

I observed the following problem with the BT404 touch pad
running the Phosh UI:

When e.g. typing on the virtual keyboard pressing "g" would
produce "ggg".

After some analysis it turns out the firmware reports that three
fingers hit that coordinate at the same time, finger 0, 2 and
4 (of the five available 0,1,2,3,4).

DOWN
Zinitix-TS 3-0020: finger 0 down (246, 395)
Zinitix-TS 3-0020: finger 1 up (0, 0)
Zinitix-TS 3-0020: finger 2 down (246, 395)
Zinitix-TS 3-0020: finger 3 up (0, 0)
Zinitix-TS 3-0020: finger 4 down (246, 395)
UP
Zinitix-TS 3-0020: finger 0 up (246, 395)
Zinitix-TS 3-0020: finger 2 up (246, 395)
Zinitix-TS 3-0020: finger 4 up (246, 395)

This is one touch and release: i.e. this is all reported on
touch (down) and release.

There is a field in the struct touch_event called finger_cnt
which is actually a bitmask of the fingers active in the
event.

Rename this field finger_mask as this matches the use contents
better, then use for_each_set_bit() to iterate over just the
fingers that are actally active.

Factor out a finger reporting function zinitix_report_fingers()
to handle all fingers.

Also be more careful in reporting finger down/up: we were
reporting every event with input_mt_report_slot_state(..., true);
but this should only be reported on finger down or move,
not on finger up, so also add code to check p->sub_status
to see what is happening and report correctly.

After this my Zinitix BT404 touchscreen report fingers
flawlessly.

The vendor drive I have notably does not use the "finger_cnt"
and contains obviously incorrect code like this:

if (touch_dev->touch_info.finger_cnt > MAX_SUPPORTED_FINGER_NUM)
touch_dev->touch_info.finger_cnt = MAX_SUPPORTED_FINGER_NUM;

As MAX_SUPPORTED_FINGER_NUM is an ordinal and the field is
a bitmask this seems quite confused.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20220228233017.2270599-1-linus.walleij@linaro.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by Linus Walleij and committed by Dmitry Torokhov e941dc13 327b89f0

Changed files
+35 -9
drivers
input
touchscreen
+35 -9
drivers/input/touchscreen/zinitix.c
··· 135 135 136 136 struct touch_event { 137 137 __le16 status; 138 - u8 finger_cnt; 138 + u8 finger_mask; 139 139 u8 time_stamp; 140 140 struct point_coord point_coord[MAX_SUPPORTED_FINGER_NUM]; 141 141 }; ··· 322 322 static void zinitix_report_finger(struct bt541_ts_data *bt541, int slot, 323 323 const struct point_coord *p) 324 324 { 325 + u16 x, y; 326 + 327 + if (unlikely(!(p->sub_status & 328 + (SUB_BIT_UP | SUB_BIT_DOWN | SUB_BIT_MOVE)))) { 329 + dev_dbg(&bt541->client->dev, "unknown finger event %#02x\n", 330 + p->sub_status); 331 + return; 332 + } 333 + 334 + x = le16_to_cpu(p->x); 335 + y = le16_to_cpu(p->y); 336 + 325 337 input_mt_slot(bt541->input_dev, slot); 326 - input_mt_report_slot_state(bt541->input_dev, MT_TOOL_FINGER, true); 327 - touchscreen_report_pos(bt541->input_dev, &bt541->prop, 328 - le16_to_cpu(p->x), le16_to_cpu(p->y), true); 329 - input_report_abs(bt541->input_dev, ABS_MT_TOUCH_MAJOR, p->width); 338 + if (input_mt_report_slot_state(bt541->input_dev, MT_TOOL_FINGER, 339 + !(p->sub_status & SUB_BIT_UP))) { 340 + touchscreen_report_pos(bt541->input_dev, 341 + &bt541->prop, x, y, true); 342 + input_report_abs(bt541->input_dev, 343 + ABS_MT_TOUCH_MAJOR, p->width); 344 + dev_dbg(&bt541->client->dev, "finger %d %s (%u, %u)\n", 345 + slot, p->sub_status & SUB_BIT_DOWN ? "down" : "move", 346 + x, y); 347 + } else { 348 + dev_dbg(&bt541->client->dev, "finger %d up (%u, %u)\n", 349 + slot, x, y); 350 + } 330 351 } 331 352 332 353 static irqreturn_t zinitix_ts_irq_handler(int irq, void *bt541_handler) ··· 355 334 struct bt541_ts_data *bt541 = bt541_handler; 356 335 struct i2c_client *client = bt541->client; 357 336 struct touch_event touch_event; 337 + unsigned long finger_mask; 358 338 int error; 359 339 int i; 360 340 ··· 368 346 goto out; 369 347 } 370 348 371 - for (i = 0; i < MAX_SUPPORTED_FINGER_NUM; i++) 372 - if (touch_event.point_coord[i].sub_status & SUB_BIT_EXIST) 373 - zinitix_report_finger(bt541, i, 374 - &touch_event.point_coord[i]); 349 + finger_mask = touch_event.finger_mask; 350 + for_each_set_bit(i, &finger_mask, MAX_SUPPORTED_FINGER_NUM) { 351 + const struct point_coord *p = &touch_event.point_coord[i]; 352 + 353 + /* Only process contacts that are actually reported */ 354 + if (p->sub_status & SUB_BIT_EXIST) 355 + zinitix_report_finger(bt541, i, p); 356 + } 375 357 376 358 input_mt_sync_frame(bt541->input_dev); 377 359 input_sync(bt541->input_dev);