Commit 72c16d9a authored by Jiri Kosina's avatar Jiri Kosina

Merge branch 'for-3.10/mt-hybrid-finger-pen' into for-linus

Conflicts:
	drivers/hid/hid-multitouch.c
parents 4f5a8104 fb4d8d98
...@@ -1198,6 +1198,67 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) ...@@ -1198,6 +1198,67 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
return hidinput; return hidinput;
} }
static bool hidinput_has_been_populated(struct hid_input *hidinput)
{
int i;
unsigned long r = 0;
for (i = 0; i < BITS_TO_LONGS(EV_CNT); i++)
r |= hidinput->input->evbit[i];
for (i = 0; i < BITS_TO_LONGS(KEY_CNT); i++)
r |= hidinput->input->keybit[i];
for (i = 0; i < BITS_TO_LONGS(REL_CNT); i++)
r |= hidinput->input->relbit[i];
for (i = 0; i < BITS_TO_LONGS(ABS_CNT); i++)
r |= hidinput->input->absbit[i];
for (i = 0; i < BITS_TO_LONGS(MSC_CNT); i++)
r |= hidinput->input->mscbit[i];
for (i = 0; i < BITS_TO_LONGS(LED_CNT); i++)
r |= hidinput->input->ledbit[i];
for (i = 0; i < BITS_TO_LONGS(SND_CNT); i++)
r |= hidinput->input->sndbit[i];
for (i = 0; i < BITS_TO_LONGS(FF_CNT); i++)
r |= hidinput->input->ffbit[i];
for (i = 0; i < BITS_TO_LONGS(SW_CNT); i++)
r |= hidinput->input->swbit[i];
return !!r;
}
static void hidinput_cleanup_hidinput(struct hid_device *hid,
struct hid_input *hidinput)
{
struct hid_report *report;
int i, k;
list_del(&hidinput->list);
input_free_device(hidinput->input);
for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
if (k == HID_OUTPUT_REPORT &&
hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
continue;
list_for_each_entry(report, &hid->report_enum[k].report_list,
list) {
for (i = 0; i < report->maxfield; i++)
if (report->field[i]->hidinput == hidinput)
report->field[i]->hidinput = NULL;
}
}
kfree(hidinput);
}
/* /*
* Register the input device; print a message. * Register the input device; print a message.
* Configure the input layer interface * Configure the input layer interface
...@@ -1249,6 +1310,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) ...@@ -1249,6 +1310,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
hidinput_configure_usage(hidinput, report->field[i], hidinput_configure_usage(hidinput, report->field[i],
report->field[i]->usage + j); report->field[i]->usage + j);
if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
!hidinput_has_been_populated(hidinput))
continue;
if (hid->quirks & HID_QUIRK_MULTI_INPUT) { if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
/* This will leave hidinput NULL, so that it /* This will leave hidinput NULL, so that it
* allocates another one if we have more inputs on * allocates another one if we have more inputs on
...@@ -1265,6 +1330,18 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) ...@@ -1265,6 +1330,18 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
} }
} }
if (hidinput && (hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
!hidinput_has_been_populated(hidinput)) {
/* no need to register an input device not populated */
hidinput_cleanup_hidinput(hid, hidinput);
hidinput = NULL;
}
if (list_empty(&hid->inputs)) {
hid_err(hid, "No inputs registered, leaving\n");
goto out_unwind;
}
if (hidinput) { if (hidinput) {
if (drv->input_configured) if (drv->input_configured)
drv->input_configured(hid, hidinput); drv->input_configured(hid, hidinput);
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/string.h>
MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
...@@ -97,9 +98,9 @@ struct mt_device { ...@@ -97,9 +98,9 @@ struct mt_device {
multitouch fields */ multitouch fields */
int cc_index; /* contact count field index in the report */ int cc_index; /* contact count field index in the report */
int cc_value_index; /* contact count value index in the field */ int cc_value_index; /* contact count value index in the field */
unsigned last_field_index; /* last field index of the report */
unsigned last_slot_field; /* the last field of a slot */ unsigned last_slot_field; /* the last field of a slot */
unsigned mt_report_id; /* the report ID of the multitouch device */ unsigned mt_report_id; /* the report ID of the multitouch device */
unsigned pen_report_id; /* the report ID of the pen device */
__s8 inputmode; /* InputMode HID feature, -1 if non-existent */ __s8 inputmode; /* InputMode HID feature, -1 if non-existent */
__s8 inputmode_index; /* InputMode HID feature index in the report */ __s8 inputmode_index; /* InputMode HID feature index in the report */
__s8 maxcontact_report_id; /* Maximum Contact Number HID feature, __s8 maxcontact_report_id; /* Maximum Contact Number HID feature,
...@@ -115,6 +116,9 @@ struct mt_device { ...@@ -115,6 +116,9 @@ struct mt_device {
unsigned mt_flags; /* flags to pass to input-mt */ unsigned mt_flags; /* flags to pass to input-mt */
}; };
static void mt_post_parse_default_settings(struct mt_device *td);
static void mt_post_parse(struct mt_device *td);
/* classes of device behavior */ /* classes of device behavior */
#define MT_CLS_DEFAULT 0x0001 #define MT_CLS_DEFAULT 0x0001
...@@ -257,6 +261,14 @@ static struct mt_class mt_classes[] = { ...@@ -257,6 +261,14 @@ static struct mt_class mt_classes[] = {
{ } { }
}; };
static void mt_free_input_name(struct hid_input *hi)
{
struct hid_device *hdev = hi->report->device;
if (hi->input->name != hdev->name)
kfree(hi->input->name);
}
static ssize_t mt_show_quirks(struct device *dev, static ssize_t mt_show_quirks(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
...@@ -365,7 +377,53 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td, ...@@ -365,7 +377,53 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
f->usages[f->length++] = usage->hid; f->usages[f->length++] = usage->hid;
} }
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
struct mt_device *td = hid_get_drvdata(hdev);
td->pen_report_id = field->report->id;
return 0;
}
static int mt_pen_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
return 0;
}
static int mt_pen_event(struct hid_device *hid, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
/* let hid-input handle it */
return 0;
}
static void mt_pen_report(struct hid_device *hid, struct hid_report *report)
{
struct hid_field *field = report->field[0];
input_sync(field->hidinput->input);
}
static void mt_pen_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
char *name = kzalloc(strlen(hi->input->name) + 5, GFP_KERNEL);
if (name) {
sprintf(name, "%s Pen", hi->input->name);
mt_free_input_name(hi);
hi->input->name = name;
}
/* force BTN_STYLUS to allow tablet matching in udev */
__set_bit(BTN_STYLUS, hi->input->keybit);
}
static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage, struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max) unsigned long **bit, int *max)
{ {
...@@ -374,13 +432,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -374,13 +432,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
int code; int code;
struct hid_usage *prev_usage = NULL; struct hid_usage *prev_usage = NULL;
/* Only map fields from TouchScreen or TouchPad collections.
* We need to ignore fields that belong to other collections
* such as Mouse that might have the same GenericDesktop usages. */
if (field->application == HID_DG_TOUCHSCREEN) if (field->application == HID_DG_TOUCHSCREEN)
td->mt_flags |= INPUT_MT_DIRECT; td->mt_flags |= INPUT_MT_DIRECT;
else if (field->application != HID_DG_TOUCHPAD)
return 0;
/* /*
* Model touchscreens providing buttons as touchpads. * Model touchscreens providing buttons as touchpads.
...@@ -389,12 +442,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -389,12 +442,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
(usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
td->mt_flags |= INPUT_MT_POINTER; td->mt_flags |= INPUT_MT_POINTER;
/* eGalax devices provide a Digitizer.Stylus input which overrides
* the correct Digitizers.Finger X/Y ranges.
* Let's just ignore this input. */
if (field->physical == HID_DG_STYLUS)
return -1;
if (usage->usage_index) if (usage->usage_index)
prev_usage = &field->usage[usage->usage_index - 1]; prev_usage = &field->usage[usage->usage_index - 1];
...@@ -416,7 +463,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -416,7 +463,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
} }
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1; return 1;
case HID_GD_Y: case HID_GD_Y:
if (prev_usage && (prev_usage->hid == usage->hid)) { if (prev_usage && (prev_usage->hid == usage->hid)) {
...@@ -432,7 +478,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -432,7 +478,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
} }
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1; return 1;
} }
return 0; return 0;
...@@ -447,21 +492,17 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -447,21 +492,17 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
ABS_MT_DISTANCE, 0, 1, 0, 0); ABS_MT_DISTANCE, 0, 1, 0, 0);
} }
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1; return 1;
case HID_DG_CONFIDENCE: case HID_DG_CONFIDENCE:
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1; return 1;
case HID_DG_TIPSWITCH: case HID_DG_TIPSWITCH:
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
input_set_capability(hi->input, EV_KEY, BTN_TOUCH); input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1; return 1;
case HID_DG_CONTACTID: case HID_DG_CONTACTID:
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index;
td->touches_by_report++; td->touches_by_report++;
td->mt_report_id = field->report->id; td->mt_report_id = field->report->id;
return 1; return 1;
...@@ -472,7 +513,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -472,7 +513,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
cls->sn_width); cls->sn_width);
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1; return 1;
case HID_DG_HEIGHT: case HID_DG_HEIGHT:
hid_map_usage(hi, usage, bit, max, hid_map_usage(hi, usage, bit, max,
...@@ -484,7 +524,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -484,7 +524,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
ABS_MT_ORIENTATION, 0, 1, 0, 0); ABS_MT_ORIENTATION, 0, 1, 0, 0);
} }
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1; return 1;
case HID_DG_TIPPRESSURE: case HID_DG_TIPPRESSURE:
hid_map_usage(hi, usage, bit, max, hid_map_usage(hi, usage, bit, max,
...@@ -492,17 +531,14 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -492,17 +531,14 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
set_abs(hi->input, ABS_MT_PRESSURE, field, set_abs(hi->input, ABS_MT_PRESSURE, field,
cls->sn_pressure); cls->sn_pressure);
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1; return 1;
case HID_DG_CONTACTCOUNT: case HID_DG_CONTACTCOUNT:
td->cc_index = field->index; td->cc_index = field->index;
td->cc_value_index = usage->usage_index; td->cc_value_index = usage->usage_index;
td->last_field_index = field->index;
return 1; return 1;
case HID_DG_CONTACTMAX: case HID_DG_CONTACTMAX:
/* we don't set td->last_slot_field as contactcount and /* we don't set td->last_slot_field as contactcount and
* contact max are global to the report */ * contact max are global to the report */
td->last_field_index = field->index;
return -1; return -1;
case HID_DG_TOUCH: case HID_DG_TOUCH:
/* Legacy devices use TIPSWITCH and not TOUCH. /* Legacy devices use TIPSWITCH and not TOUCH.
...@@ -526,7 +562,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -526,7 +562,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 0; return 0;
} }
static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage, struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max) unsigned long **bit, int *max)
{ {
...@@ -617,7 +653,7 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input) ...@@ -617,7 +653,7 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
td->num_received = 0; td->num_received = 0;
} }
static int mt_event(struct hid_device *hid, struct hid_field *field, static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
struct hid_usage *usage, __s32 value) struct hid_usage *usage, __s32 value)
{ {
/* we will handle the hidinput part later, now remains hiddev */ /* we will handle the hidinput part later, now remains hiddev */
...@@ -691,29 +727,19 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, ...@@ -691,29 +727,19 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
if (usage->usage_index + 1 == field->report_count) { if (usage->usage_index + 1 == field->report_count) {
/* we only take into account the last report. */ /* we only take into account the last report. */
if (usage->hid == td->last_slot_field) if (usage->hid == td->last_slot_field)
mt_complete_slot(td, input); mt_complete_slot(td, field->hidinput->input);
if (field->index == td->last_field_index
&& td->num_received >= td->num_expected)
mt_sync_frame(td, field->hidinput->input);
} }
} }
} }
static void mt_report(struct hid_device *hid, struct hid_report *report) static void mt_touch_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; struct hid_field *field;
unsigned count; unsigned count;
int r, n; int r, n;
if (report->id != td->mt_report_id)
return;
if (!(hid->claimed & HID_CLAIMED_INPUT))
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.
...@@ -736,6 +762,91 @@ static void mt_report(struct hid_device *hid, struct hid_report *report) ...@@ -736,6 +762,91 @@ static void mt_report(struct hid_device *hid, struct hid_report *report)
mt_process_mt_event(hid, field, &field->usage[n], mt_process_mt_event(hid, field, &field->usage[n],
field->value[n]); field->value[n]);
} }
if (td->num_received >= td->num_expected)
mt_sync_frame(td, report->field[0]->hidinput->input);
}
static void mt_touch_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass;
struct input_dev *input = hi->input;
if (!td->maxcontacts)
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
mt_post_parse(td);
if (td->serial_maybe)
mt_post_parse_default_settings(td);
if (cls->is_indirect)
td->mt_flags |= INPUT_MT_POINTER;
if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
td->mt_flags |= INPUT_MT_DROP_UNUSED;
input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
td->mt_flags = 0;
}
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
/* Only map fields from TouchScreen or TouchPad collections.
* We need to ignore fields that belong to other collections
* such as Mouse that might have the same GenericDesktop usages. */
if (field->application != HID_DG_TOUCHSCREEN &&
field->application != HID_DG_PEN &&
field->application != HID_DG_TOUCHPAD)
return -1;
if (field->physical == HID_DG_STYLUS)
return mt_pen_input_mapping(hdev, hi, field, usage, bit, max);
return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
}
static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
if (field->physical == HID_DG_STYLUS)
return mt_pen_input_mapped(hdev, hi, field, usage, bit, max);
return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
}
static int mt_event(struct hid_device *hid, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
struct mt_device *td = hid_get_drvdata(hid);
if (field->report->id == td->mt_report_id)
return mt_touch_event(hid, field, usage, value);
if (field->report->id == td->pen_report_id)
return mt_pen_event(hid, field, usage, value);
/* ignore other reports */
return 1;
}
static void mt_report(struct hid_device *hid, struct hid_report *report)
{
struct mt_device *td = hid_get_drvdata(hid);
if (!(hid->claimed & HID_CLAIMED_INPUT))
return;
if (report->id == td->mt_report_id)
mt_touch_report(hid, report);
if (report->id == td->pen_report_id)
mt_pen_report(hid, report);
} }
static void mt_set_input_mode(struct hid_device *hdev) static void mt_set_input_mode(struct hid_device *hdev)
...@@ -812,32 +923,18 @@ static void mt_post_parse(struct mt_device *td) ...@@ -812,32 +923,18 @@ static void mt_post_parse(struct mt_device *td)
} }
static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) static void mt_input_configured(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_class *cls = &td->mtclass; char *name = kstrdup(hdev->name, GFP_KERNEL);
struct input_dev *input = hi->input;
/* Only initialize slots for MT input devices */ if (name)
if (!test_bit(ABS_MT_POSITION_X, input->absbit)) hi->input->name = name;
return;
if (!td->maxcontacts) if (hi->report->id == td->mt_report_id)
td->maxcontacts = MT_DEFAULT_MAXCONTACT; mt_touch_input_configured(hdev, hi);
mt_post_parse(td); if (hi->report->id == td->pen_report_id)
if (td->serial_maybe) mt_pen_input_configured(hdev, hi);
mt_post_parse_default_settings(td);
if (cls->is_indirect)
td->mt_flags |= INPUT_MT_POINTER;
if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
td->mt_flags |= INPUT_MT_DROP_UNUSED;
input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
td->mt_flags = 0;
} }
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
...@@ -845,6 +942,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -845,6 +942,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
int ret, i; int ret, i;
struct mt_device *td; struct mt_device *td;
struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */ struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
struct hid_input *hi;
for (i = 0; mt_classes[i].name ; i++) { for (i = 0; mt_classes[i].name ; i++) {
if (id->driver_data == mt_classes[i].name) { if (id->driver_data == mt_classes[i].name) {
...@@ -858,6 +956,14 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -858,6 +956,14 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
*/ */
hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
/*
* This allows the driver to handle different input sensors
* that emits events through different reports on the same HID
* device.
*/
hdev->quirks |= HID_QUIRK_MULTI_INPUT;
hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
if (!td) { if (!td) {
dev_err(&hdev->dev, "cannot allocate multitouch data\n"); dev_err(&hdev->dev, "cannot allocate multitouch data\n");
...@@ -867,6 +973,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -867,6 +973,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
td->inputmode = -1; td->inputmode = -1;
td->maxcontact_report_id = -1; td->maxcontact_report_id = -1;
td->cc_index = -1; td->cc_index = -1;
td->mt_report_id = -1;
td->pen_report_id = -1;
hid_set_drvdata(hdev, td); hid_set_drvdata(hdev, td);
td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL); td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL);
...@@ -885,7 +993,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -885,7 +993,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) if (ret)
goto fail; goto hid_fail;
ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
...@@ -897,6 +1005,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -897,6 +1005,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
return 0; return 0;
hid_fail:
list_for_each_entry(hi, &hdev->inputs, list)
mt_free_input_name(hi);
fail: fail:
kfree(td->fields); kfree(td->fields);
kfree(td); kfree(td);
...@@ -926,8 +1037,14 @@ static int mt_resume(struct hid_device *hdev) ...@@ -926,8 +1037,14 @@ static int mt_resume(struct hid_device *hdev)
static void mt_remove(struct hid_device *hdev) static void mt_remove(struct hid_device *hdev)
{ {
struct mt_device *td = hid_get_drvdata(hdev); struct mt_device *td = hid_get_drvdata(hdev);
struct hid_input *hi;
sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
hid_hw_stop(hdev); hid_hw_stop(hdev);
list_for_each_entry(hi, &hdev->inputs, list)
mt_free_input_name(hi);
kfree(td); kfree(td);
hid_set_drvdata(hdev, NULL); hid_set_drvdata(hdev, NULL);
} }
......
...@@ -282,6 +282,7 @@ struct hid_item { ...@@ -282,6 +282,7 @@ struct hid_item {
#define HID_QUIRK_BADPAD 0x00000020 #define HID_QUIRK_BADPAD 0x00000020
#define HID_QUIRK_MULTI_INPUT 0x00000040 #define HID_QUIRK_MULTI_INPUT 0x00000040
#define HID_QUIRK_HIDINPUT_FORCE 0x00000080 #define HID_QUIRK_HIDINPUT_FORCE 0x00000080
#define HID_QUIRK_NO_EMPTY_INPUT 0x00000100
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
#define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000
#define HID_QUIRK_NO_INIT_REPORTS 0x20000000 #define HID_QUIRK_NO_INIT_REPORTS 0x20000000
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment