diff options
-rw-r--r-- | drivers/hid/hid-3m-pct.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c index 2a0d56b7a02..105743068cc 100644 --- a/drivers/hid/hid-3m-pct.c +++ b/drivers/hid/hid-3m-pct.c @@ -24,6 +24,9 @@ MODULE_LICENSE("GPL"); #include "hid-ids.h" +#define MAX_SLOTS 60 +#define MAX_TRKID 59 + struct mmm_finger { __s32 x, y, w, h; __u8 rank; @@ -31,8 +34,9 @@ struct mmm_finger { }; struct mmm_data { - struct mmm_finger f[10]; + struct mmm_finger f[MAX_SLOTS]; __u8 curid, num; + __u8 nexp, nreal; bool touch, valid; }; @@ -93,7 +97,7 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, 1, 1, 0, 0); return 1; case HID_DG_CONTACTID: - field->logical_maximum = 59; + field->logical_maximum = MAX_TRKID; hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TRACKING_ID); return 1; @@ -133,7 +137,7 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) * we need to iterate on all fingers to decide if we have a press * or a release event in our touchscreen emulation. */ - for (i = 0; i < 10; ++i) { + for (i = 0; i < MAX_SLOTS; ++i) { struct mmm_finger *f = &md->f[i]; if (!f->valid) { /* this finger is just placeholder data, ignore */ @@ -190,6 +194,7 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) } else if (released) { input_event(input, EV_KEY, BTN_TOUCH, 0); } + input_sync(input); } /* @@ -223,10 +228,12 @@ static int mmm_event(struct hid_device *hid, struct hid_field *field, md->f[md->curid].h = value; break; case HID_DG_CONTACTID: + value = clamp_val(value, 0, MAX_SLOTS - 1); if (md->valid) { md->curid = value; md->f[value].touch = md->touch; md->f[value].valid = 1; + md->nreal++; } break; case HID_GD_X: @@ -238,7 +245,12 @@ static int mmm_event(struct hid_device *hid, struct hid_field *field, md->f[md->curid].y = value; break; case HID_DG_CONTACTCOUNT: - mmm_filter_event(md, input); + if (value) + md->nexp = value; + if (md->nreal >= md->nexp) { + mmm_filter_event(md, input); + md->nreal = 0; + } break; } } @@ -255,6 +267,8 @@ static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id) int ret; struct mmm_data *md; + hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; + md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL); if (!md) { dev_err(&hdev->dev, "cannot allocate 3M data\n"); |