HID: multitouch: ditch mt_report_id
Now that the driver can handle more than one multitouch collection in a single HID device, ditch the last bit that contains us to use only one mt collection. Acked-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
Родитель
3ceb382644
Коммит
8dfe14b3b4
|
@ -147,6 +147,13 @@ struct mt_fields {
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mt_report_data {
|
||||||
|
struct list_head list;
|
||||||
|
struct hid_report *report;
|
||||||
|
struct mt_application *application;
|
||||||
|
bool is_mt_collection;
|
||||||
|
};
|
||||||
|
|
||||||
struct mt_device {
|
struct mt_device {
|
||||||
struct mt_class mtclass; /* our mt device class */
|
struct mt_class mtclass; /* our mt device class */
|
||||||
struct timer_list release_timer; /* to release sticky fingers */
|
struct timer_list release_timer; /* to release sticky fingers */
|
||||||
|
@ -154,13 +161,13 @@ struct mt_device {
|
||||||
struct mt_fields *fields; /* temporary placeholder for storing the
|
struct mt_fields *fields; /* temporary placeholder for storing the
|
||||||
multitouch fields */
|
multitouch fields */
|
||||||
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
|
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
|
||||||
unsigned mt_report_id; /* the report ID of the multitouch device */
|
|
||||||
__u8 inputmode_value; /* InputMode HID feature value */
|
__u8 inputmode_value; /* InputMode HID feature value */
|
||||||
__u8 maxcontacts;
|
__u8 maxcontacts;
|
||||||
bool is_buttonpad; /* is this device a button pad? */
|
bool is_buttonpad; /* is this device a button pad? */
|
||||||
bool serial_maybe; /* need to check for serial protocol */
|
bool serial_maybe; /* need to check for serial protocol */
|
||||||
|
|
||||||
struct list_head applications;
|
struct list_head applications;
|
||||||
|
struct list_head reports;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void mt_post_parse_default_settings(struct mt_device *td,
|
static void mt_post_parse_default_settings(struct mt_device *td,
|
||||||
|
@ -526,6 +533,60 @@ static struct mt_application *mt_find_application(struct mt_device *td,
|
||||||
return mt_application;
|
return mt_application;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct mt_report_data *mt_allocate_report_data(struct mt_device *td,
|
||||||
|
struct hid_report *report)
|
||||||
|
{
|
||||||
|
struct mt_report_data *rdata;
|
||||||
|
struct hid_field *field;
|
||||||
|
int r, n;
|
||||||
|
|
||||||
|
rdata = devm_kzalloc(&td->hdev->dev, sizeof(*rdata), GFP_KERNEL);
|
||||||
|
if (!rdata)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
rdata->report = report;
|
||||||
|
rdata->application = mt_find_application(td, report->application);
|
||||||
|
|
||||||
|
if (!rdata->application) {
|
||||||
|
devm_kfree(&td->hdev->dev, rdata);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (r = 0; r < report->maxfield; r++) {
|
||||||
|
field = report->field[r];
|
||||||
|
|
||||||
|
if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (n = 0; n < field->report_count; n++) {
|
||||||
|
if (field->usage[n].hid == HID_DG_CONTACTID)
|
||||||
|
rdata->is_mt_collection = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_tail(&rdata->list, &td->reports);
|
||||||
|
|
||||||
|
return rdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mt_report_data *mt_find_report_data(struct mt_device *td,
|
||||||
|
struct hid_report *report)
|
||||||
|
{
|
||||||
|
struct mt_report_data *tmp, *rdata = NULL;
|
||||||
|
|
||||||
|
list_for_each_entry(tmp, &td->reports, list) {
|
||||||
|
if (report == tmp->report) {
|
||||||
|
rdata = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rdata)
|
||||||
|
rdata = mt_allocate_report_data(td, report);
|
||||||
|
|
||||||
|
return rdata;
|
||||||
|
}
|
||||||
|
|
||||||
static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
|
static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
|
||||||
struct hid_input *hi)
|
struct hid_input *hi)
|
||||||
{
|
{
|
||||||
|
@ -614,7 +675,6 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||||
case HID_DG_CONTACTID:
|
case HID_DG_CONTACTID:
|
||||||
mt_store_field(usage, td, hi);
|
mt_store_field(usage, td, hi);
|
||||||
app->touches_by_report++;
|
app->touches_by_report++;
|
||||||
td->mt_report_id = field->report->id;
|
|
||||||
return 1;
|
return 1;
|
||||||
case HID_DG_WIDTH:
|
case HID_DG_WIDTH:
|
||||||
hid_map_usage(hi, usage, bit, max,
|
hid_map_usage(hi, usage, bit, max,
|
||||||
|
@ -979,10 +1039,12 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
static void mt_touch_report(struct hid_device *hid,
|
||||||
|
struct mt_report_data *rdata)
|
||||||
{
|
{
|
||||||
struct mt_device *td = hid_get_drvdata(hid);
|
struct mt_device *td = hid_get_drvdata(hid);
|
||||||
struct mt_application *app;
|
struct hid_report *report = rdata->report;
|
||||||
|
struct mt_application *app = rdata->application;
|
||||||
struct hid_field *field;
|
struct hid_field *field;
|
||||||
bool first_packet;
|
bool first_packet;
|
||||||
unsigned count;
|
unsigned count;
|
||||||
|
@ -994,11 +1056,6 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
||||||
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
|
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
app = mt_find_application(td, report->application);
|
|
||||||
|
|
||||||
if (!app)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Includes multi-packet support where subsequent
|
* Includes multi-packet support where subsequent
|
||||||
* packets are sent with zero contactcount.
|
* packets are sent with zero contactcount.
|
||||||
|
@ -1119,8 +1176,15 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||||
{
|
{
|
||||||
struct mt_device *td = hid_get_drvdata(hdev);
|
struct mt_device *td = hid_get_drvdata(hdev);
|
||||||
struct mt_application *application;
|
struct mt_application *application;
|
||||||
|
struct mt_report_data *rdata;
|
||||||
|
|
||||||
application = mt_find_application(td, field->application);
|
rdata = mt_find_report_data(td, field->report);
|
||||||
|
if (!rdata) {
|
||||||
|
hid_err(hdev, "failed to allocate data for report\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
application = rdata->application;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If mtclass.export_all_inputs is not set, only map fields from
|
* If mtclass.export_all_inputs is not set, only map fields from
|
||||||
|
@ -1163,22 +1227,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (rdata->is_mt_collection &&
|
||||||
* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
|
(field->application == HID_DG_TOUCHSCREEN ||
|
||||||
* for the stylus.
|
field->application == HID_DG_TOUCHPAD))
|
||||||
* The check for mt_report_id ensures we don't process
|
|
||||||
* HID_DG_CONTACTCOUNT from the pen report as it is outside the physical
|
|
||||||
* collection, but within the report ID.
|
|
||||||
*/
|
|
||||||
if (field->physical == HID_DG_STYLUS)
|
|
||||||
return 0;
|
|
||||||
else if ((field->physical == 0) &&
|
|
||||||
(field->report->id != td->mt_report_id) &&
|
|
||||||
(td->mt_report_id != -1))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (field->application == HID_DG_TOUCHSCREEN ||
|
|
||||||
field->application == HID_DG_TOUCHPAD)
|
|
||||||
return mt_touch_input_mapping(hdev, hi, field, usage, bit, max,
|
return mt_touch_input_mapping(hdev, hi, field, usage, bit, max,
|
||||||
application);
|
application);
|
||||||
|
|
||||||
|
@ -1211,8 +1262,10 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
|
||||||
struct hid_usage *usage, __s32 value)
|
struct hid_usage *usage, __s32 value)
|
||||||
{
|
{
|
||||||
struct mt_device *td = hid_get_drvdata(hid);
|
struct mt_device *td = hid_get_drvdata(hid);
|
||||||
|
struct mt_report_data *rdata;
|
||||||
|
|
||||||
if (field->report->id == td->mt_report_id)
|
rdata = mt_find_report_data(td, field->report);
|
||||||
|
if (rdata && rdata->is_mt_collection)
|
||||||
return mt_touch_event(hid, field, usage, value);
|
return mt_touch_event(hid, field, usage, value);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1222,12 +1275,14 @@ static void mt_report(struct hid_device *hid, struct hid_report *report)
|
||||||
{
|
{
|
||||||
struct mt_device *td = hid_get_drvdata(hid);
|
struct mt_device *td = hid_get_drvdata(hid);
|
||||||
struct hid_field *field = report->field[0];
|
struct hid_field *field = report->field[0];
|
||||||
|
struct mt_report_data *rdata;
|
||||||
|
|
||||||
if (!(hid->claimed & HID_CLAIMED_INPUT))
|
if (!(hid->claimed & HID_CLAIMED_INPUT))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (report->id == td->mt_report_id)
|
rdata = mt_find_report_data(td, report);
|
||||||
return mt_touch_report(hid, report);
|
if (rdata && rdata->is_mt_collection)
|
||||||
|
return mt_touch_report(hid, rdata);
|
||||||
|
|
||||||
if (field && field->hidinput && field->hidinput->input)
|
if (field && field->hidinput && field->hidinput->input)
|
||||||
input_sync(field->hidinput->input);
|
input_sync(field->hidinput->input);
|
||||||
|
@ -1368,15 +1423,22 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
|
||||||
char *name;
|
char *name;
|
||||||
const char *suffix = NULL;
|
const char *suffix = NULL;
|
||||||
unsigned int application = 0;
|
unsigned int application = 0;
|
||||||
|
struct mt_report_data *rdata;
|
||||||
struct mt_application *mt_application = NULL;
|
struct mt_application *mt_application = NULL;
|
||||||
struct hid_report *report;
|
struct hid_report *report;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
list_for_each_entry(report, &hi->reports, hidinput_list) {
|
list_for_each_entry(report, &hi->reports, hidinput_list) {
|
||||||
application = report->application;
|
application = report->application;
|
||||||
mt_application = mt_find_application(td, application);
|
rdata = mt_find_report_data(td, report);
|
||||||
|
if (!rdata) {
|
||||||
|
hid_err(hdev, "failed to allocate data for report\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
if (report->id == td->mt_report_id) {
|
mt_application = rdata->application;
|
||||||
|
|
||||||
|
if (rdata->is_mt_collection) {
|
||||||
ret = mt_touch_input_configured(hdev, hi,
|
ret = mt_touch_input_configured(hdev, hi,
|
||||||
mt_application);
|
mt_application);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -1529,10 +1591,10 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
td->hdev = hdev;
|
td->hdev = hdev;
|
||||||
td->mtclass = *mtclass;
|
td->mtclass = *mtclass;
|
||||||
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
|
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
|
||||||
td->mt_report_id = -1;
|
|
||||||
hid_set_drvdata(hdev, td);
|
hid_set_drvdata(hdev, td);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&td->applications);
|
INIT_LIST_HEAD(&td->applications);
|
||||||
|
INIT_LIST_HEAD(&td->reports);
|
||||||
|
|
||||||
td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
|
td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче