unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
int cc_index; /* contact count field index in the report */
int cc_value_index; /* contact count value index in the field */
+ int scantime_index; /* scantime field index in the report */
+ int scantime_val_index; /* scantime value index in the field */
+ int prev_scantime; /* scantime reported in the previous packet */
unsigned last_slot_field; /* the last field of a slot */
unsigned mt_report_id; /* the report ID of the multitouch device */
unsigned long initial_quirks; /* initial quirks state */
EV_MSC, MSC_TIMESTAMP);
input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
mt_store_field(usage, td, hi);
+ /* Ignore if indexes are out of bounds. */
+ if (field->index >= field->report->maxfield ||
+ usage->usage_index >= field->report_count)
+ return 1;
+ td->scantime_index = field->index;
+ td->scantime_val_index = usage->usage_index;
return 1;
case HID_DG_CONTACTCOUNT:
/* Ignore if indexes are out of bounds. */
static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
{
struct mt_device *td = hid_get_drvdata(hid);
+ __s32 cls = td->mtclass.name;
struct hid_field *field;
unsigned count;
- int r, n;
+ int r, n, scantime = 0;
/* sticky fingers release in progress, abort */
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
* Includes multi-packet support where subsequent
* packets are sent with zero contactcount.
*/
+ if (td->scantime_index >= 0) {
+ field = report->field[td->scantime_index];
+ scantime = field->value[td->scantime_val_index];
+ }
if (td->cc_index >= 0) {
struct hid_field *field = report->field[td->cc_index];
int value = field->value[td->cc_value_index];
- if (value)
+
+ /*
+ * For Win8 PTPs the first packet (td->num_received == 0) may
+ * have a contactcount of 0 if there only is a button event.
+ * We double check that this is not a continuation packet
+ * of a possible multi-packet frame be checking that the
+ * timestamp has changed.
+ */
+ if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
+ td->num_received == 0 && td->prev_scantime != scantime)
+ td->num_expected = value;
+ /* A non 0 contact count always indicates a first packet */
+ else if (value)
td->num_expected = value;
}
+ td->prev_scantime = scantime;
for (r = 0; r < report->maxfield; r++) {
field = report->field[r];
td->maxcontact_report_id = -1;
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
td->cc_index = -1;
+ td->scantime_index = -1;
td->mt_report_id = -1;
hid_set_drvdata(hdev, td);