diff options
author | Benjamin Tissoires <benjamin.tissoires@gmail.com> | 2011-11-23 04:54:28 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-11-23 08:50:38 -0500 |
commit | eec29e3dab483a5d9a742a6fa68db1ec1f0f7504 (patch) | |
tree | af1ab94fccc4c8212fa6b15e5e2fe54fa732fe62 /drivers/hid | |
parent | 1fd8f047490dd0ec4e4db710fcbc1bd4798d944c (diff) |
HID: multitouch: create sysfs attribute to control quirks from user-space
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-multitouch.c | 77 |
1 files changed, 59 insertions, 18 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index a59d939dd165..a51e62efbac1 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
@@ -60,9 +60,19 @@ struct mt_slot { | |||
60 | bool seen_in_this_frame;/* has this slot been updated */ | 60 | bool seen_in_this_frame;/* has this slot been updated */ |
61 | }; | 61 | }; |
62 | 62 | ||
63 | struct mt_class { | ||
64 | __s32 name; /* MT_CLS */ | ||
65 | __s32 quirks; | ||
66 | __s32 sn_move; /* Signal/noise ratio for move events */ | ||
67 | __s32 sn_width; /* Signal/noise ratio for width events */ | ||
68 | __s32 sn_height; /* Signal/noise ratio for height events */ | ||
69 | __s32 sn_pressure; /* Signal/noise ratio for pressure events */ | ||
70 | __u8 maxcontacts; | ||
71 | }; | ||
72 | |||
63 | struct mt_device { | 73 | struct mt_device { |
64 | struct mt_slot curdata; /* placeholder of incoming data */ | 74 | struct mt_slot curdata; /* placeholder of incoming data */ |
65 | struct mt_class *mtclass; /* our mt device class */ | 75 | struct mt_class mtclass; /* our mt device class */ |
66 | unsigned last_field_index; /* last field index of the report */ | 76 | unsigned last_field_index; /* last field index of the report */ |
67 | unsigned last_slot_field; /* the last field of a slot */ | 77 | unsigned last_slot_field; /* the last field of a slot */ |
68 | int last_mt_collection; /* last known mt-related collection */ | 78 | int last_mt_collection; /* last known mt-related collection */ |
@@ -74,16 +84,6 @@ struct mt_device { | |||
74 | struct mt_slot *slots; | 84 | struct mt_slot *slots; |
75 | }; | 85 | }; |
76 | 86 | ||
77 | struct mt_class { | ||
78 | __s32 name; /* MT_CLS */ | ||
79 | __s32 quirks; | ||
80 | __s32 sn_move; /* Signal/noise ratio for move events */ | ||
81 | __s32 sn_width; /* Signal/noise ratio for width events */ | ||
82 | __s32 sn_height; /* Signal/noise ratio for height events */ | ||
83 | __s32 sn_pressure; /* Signal/noise ratio for pressure events */ | ||
84 | __u8 maxcontacts; | ||
85 | }; | ||
86 | |||
87 | /* classes of device behavior */ | 87 | /* classes of device behavior */ |
88 | #define MT_CLS_DEFAULT 0x0001 | 88 | #define MT_CLS_DEFAULT 0x0001 |
89 | 89 | ||
@@ -181,6 +181,44 @@ struct mt_class mt_classes[] = { | |||
181 | { } | 181 | { } |
182 | }; | 182 | }; |
183 | 183 | ||
184 | static ssize_t mt_show_quirks(struct device *dev, | ||
185 | struct device_attribute *attr, | ||
186 | char *buf) | ||
187 | { | ||
188 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | ||
189 | struct mt_device *td = hid_get_drvdata(hdev); | ||
190 | |||
191 | return sprintf(buf, "%u\n", td->mtclass.quirks); | ||
192 | } | ||
193 | |||
194 | static ssize_t mt_set_quirks(struct device *dev, | ||
195 | struct device_attribute *attr, | ||
196 | const char *buf, size_t count) | ||
197 | { | ||
198 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | ||
199 | struct mt_device *td = hid_get_drvdata(hdev); | ||
200 | |||
201 | unsigned long val; | ||
202 | |||
203 | if (kstrtoul(buf, 0, &val)) | ||
204 | return -EINVAL; | ||
205 | |||
206 | td->mtclass.quirks = val; | ||
207 | |||
208 | return count; | ||
209 | } | ||
210 | |||
211 | static DEVICE_ATTR(quirks, S_IWUSR | S_IRUGO, mt_show_quirks, mt_set_quirks); | ||
212 | |||
213 | static struct attribute *sysfs_attrs[] = { | ||
214 | &dev_attr_quirks.attr, | ||
215 | NULL | ||
216 | }; | ||
217 | |||
218 | static struct attribute_group mt_attribute_group = { | ||
219 | .attrs = sysfs_attrs | ||
220 | }; | ||
221 | |||
184 | static void mt_feature_mapping(struct hid_device *hdev, | 222 | static void mt_feature_mapping(struct hid_device *hdev, |
185 | struct hid_field *field, struct hid_usage *usage) | 223 | struct hid_field *field, struct hid_usage *usage) |
186 | { | 224 | { |
@@ -192,9 +230,9 @@ static void mt_feature_mapping(struct hid_device *hdev, | |||
192 | break; | 230 | break; |
193 | case HID_DG_CONTACTMAX: | 231 | case HID_DG_CONTACTMAX: |
194 | td->maxcontacts = field->value[0]; | 232 | td->maxcontacts = field->value[0]; |
195 | if (td->mtclass->maxcontacts) | 233 | if (td->mtclass.maxcontacts) |
196 | /* check if the maxcontacts is given by the class */ | 234 | /* check if the maxcontacts is given by the class */ |
197 | td->maxcontacts = td->mtclass->maxcontacts; | 235 | td->maxcontacts = td->mtclass.maxcontacts; |
198 | 236 | ||
199 | break; | 237 | break; |
200 | } | 238 | } |
@@ -214,7 +252,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
214 | unsigned long **bit, int *max) | 252 | unsigned long **bit, int *max) |
215 | { | 253 | { |
216 | struct mt_device *td = hid_get_drvdata(hdev); | 254 | struct mt_device *td = hid_get_drvdata(hdev); |
217 | struct mt_class *cls = td->mtclass; | 255 | struct mt_class *cls = &td->mtclass; |
218 | __s32 quirks = cls->quirks; | 256 | __s32 quirks = cls->quirks; |
219 | 257 | ||
220 | /* Only map fields from TouchScreen or TouchPad collections. | 258 | /* Only map fields from TouchScreen or TouchPad collections. |
@@ -363,7 +401,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
363 | 401 | ||
364 | static int mt_compute_slot(struct mt_device *td) | 402 | static int mt_compute_slot(struct mt_device *td) |
365 | { | 403 | { |
366 | __s32 quirks = td->mtclass->quirks; | 404 | __s32 quirks = td->mtclass.quirks; |
367 | 405 | ||
368 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTID) | 406 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTID) |
369 | return td->curdata.contactid; | 407 | return td->curdata.contactid; |
@@ -407,7 +445,7 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input) | |||
407 | 445 | ||
408 | for (i = 0; i < td->maxcontacts; ++i) { | 446 | for (i = 0; i < td->maxcontacts; ++i) { |
409 | struct mt_slot *s = &(td->slots[i]); | 447 | struct mt_slot *s = &(td->slots[i]); |
410 | if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && | 448 | if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && |
411 | !s->seen_in_this_frame) { | 449 | !s->seen_in_this_frame) { |
412 | s->touch_state = false; | 450 | s->touch_state = false; |
413 | } | 451 | } |
@@ -444,7 +482,7 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, | |||
444 | struct hid_usage *usage, __s32 value) | 482 | struct hid_usage *usage, __s32 value) |
445 | { | 483 | { |
446 | struct mt_device *td = hid_get_drvdata(hid); | 484 | struct mt_device *td = hid_get_drvdata(hid); |
447 | __s32 quirks = td->mtclass->quirks; | 485 | __s32 quirks = td->mtclass.quirks; |
448 | 486 | ||
449 | if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { | 487 | if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { |
450 | switch (usage->hid) { | 488 | switch (usage->hid) { |
@@ -552,7 +590,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
552 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); | 590 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); |
553 | return -ENOMEM; | 591 | return -ENOMEM; |
554 | } | 592 | } |
555 | td->mtclass = mtclass; | 593 | td->mtclass = *mtclass; |
556 | td->inputmode = -1; | 594 | td->inputmode = -1; |
557 | td->last_mt_collection = -1; | 595 | td->last_mt_collection = -1; |
558 | hid_set_drvdata(hdev, td); | 596 | hid_set_drvdata(hdev, td); |
@@ -574,6 +612,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
574 | goto fail; | 612 | goto fail; |
575 | } | 613 | } |
576 | 614 | ||
615 | ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); | ||
616 | |||
577 | mt_set_input_mode(hdev); | 617 | mt_set_input_mode(hdev); |
578 | 618 | ||
579 | return 0; | 619 | return 0; |
@@ -594,6 +634,7 @@ static int mt_reset_resume(struct hid_device *hdev) | |||
594 | static void mt_remove(struct hid_device *hdev) | 634 | static void mt_remove(struct hid_device *hdev) |
595 | { | 635 | { |
596 | struct mt_device *td = hid_get_drvdata(hdev); | 636 | struct mt_device *td = hid_get_drvdata(hdev); |
637 | sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); | ||
597 | hid_hw_stop(hdev); | 638 | hid_hw_stop(hdev); |
598 | kfree(td->slots); | 639 | kfree(td->slots); |
599 | kfree(td); | 640 | kfree(td); |