aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@gmail.com>2011-11-23 04:54:28 -0500
committerJiri Kosina <jkosina@suse.cz>2011-11-23 08:50:38 -0500
commiteec29e3dab483a5d9a742a6fa68db1ec1f0f7504 (patch)
treeaf1ab94fccc4c8212fa6b15e5e2fe54fa732fe62
parent1fd8f047490dd0ec4e4db710fcbc1bd4798d944c (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>
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-multitouch9
-rw-r--r--drivers/hid/hid-multitouch.c77
2 files changed, 68 insertions, 18 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-multitouch b/Documentation/ABI/testing/sysfs-driver-hid-multitouch
new file mode 100644
index 00000000000..f79839d1af3
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-multitouch
@@ -0,0 +1,9 @@
1What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/quirks
2Date: November 2011
3Contact: Benjamin Tissoires <benjamin.tissoires@gmail.com>
4Description: The integer value of this attribute corresponds to the
5 quirks actually in place to handle the device's protocol.
6 When read, this attribute returns the current settings (see
7 MT_QUIRKS_* in hid-multitouch.c).
8 When written this attribute change on the fly the quirks, then
9 the protocol to handle the device.
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index a59d939dd16..a51e62efbac 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
63struct 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
63struct mt_device { 73struct 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
77struct 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
184static 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
194static 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
211static DEVICE_ATTR(quirks, S_IWUSR | S_IRUGO, mt_show_quirks, mt_set_quirks);
212
213static struct attribute *sysfs_attrs[] = {
214 &dev_attr_quirks.attr,
215 NULL
216};
217
218static struct attribute_group mt_attribute_group = {
219 .attrs = sysfs_attrs
220};
221
184static void mt_feature_mapping(struct hid_device *hdev, 222static 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
364static int mt_compute_slot(struct mt_device *td) 402static 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)
594static void mt_remove(struct hid_device *hdev) 634static 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);