aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>2015-02-19 18:31:26 -0500
committerJiri Kosina <jkosina@suse.cz>2015-02-23 09:11:52 -0500
commitcb67126f32f008b9abe97fbfca9b23a797b2458a (patch)
tree37870932b6f72222d97970452e306b6ecd0b6fc7
parente651a1da442ae02a50081e38309dea5e89da2d41 (diff)
HID: hid-sensor-hub: Add support for application collection
Section 4.2.5 of HID Sensor hub specification allows two methods defining sensor devices. - Each sensor device by its own collection - A top level application collection object, including multiple sensors. In the first method, each sensor can be in its own sensor application collection without a physical collection. In the second method there is a usage id for collection type, which is defined as an application collection, with multiple physical collections in it. It is possible to define fusion sensor with this and may have its own handler. If there is a callback registered for the collection type, then forward all reports for sensors in its collection to this handler. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-sensor-hub.c30
-rw-r--r--include/linux/hid-sensor-ids.h2
2 files changed, 28 insertions, 4 deletions
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 62fadf8c86fc..c325f85fa3a6 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -86,7 +86,8 @@ static int sensor_hub_get_physical_device_count(struct hid_device *hdev)
86 86
87 for (i = 0; i < hdev->maxcollection; ++i) { 87 for (i = 0; i < hdev->maxcollection; ++i) {
88 struct hid_collection *collection = &hdev->collection[i]; 88 struct hid_collection *collection = &hdev->collection[i];
89 if (collection->type == HID_COLLECTION_PHYSICAL) 89 if (collection->type == HID_COLLECTION_PHYSICAL ||
90 collection->type == HID_COLLECTION_APPLICATION)
90 ++count; 91 ++count;
91 } 92 }
92 93
@@ -118,7 +119,8 @@ static struct hid_sensor_hub_callbacks *sensor_hub_get_callback(
118 119
119 spin_lock(&pdata->dyn_callback_lock); 120 spin_lock(&pdata->dyn_callback_lock);
120 list_for_each_entry(callback, &pdata->dyn_callback_list, list) 121 list_for_each_entry(callback, &pdata->dyn_callback_list, list)
121 if (callback->usage_id == usage_id && 122 if ((callback->usage_id == usage_id ||
123 callback->usage_id == HID_USAGE_SENSOR_COLLECTION) &&
122 (collection_index >= 124 (collection_index >=
123 callback->hsdev->start_collection_index) && 125 callback->hsdev->start_collection_index) &&
124 (collection_index < 126 (collection_index <
@@ -157,7 +159,18 @@ int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
157 callback->usage_callback = usage_callback; 159 callback->usage_callback = usage_callback;
158 callback->usage_id = usage_id; 160 callback->usage_id = usage_id;
159 callback->priv = NULL; 161 callback->priv = NULL;
160 list_add_tail(&callback->list, &pdata->dyn_callback_list); 162 /*
163 * If there is a handler registered for the collection type, then
164 * it will handle all reports for sensors in this collection. If
165 * there is also an individual sensor handler registration, then
166 * we want to make sure that the reports are directed to collection
167 * handler, as this may be a fusion sensor. So add collection handlers
168 * to the beginning of the list, so that they are matched first.
169 */
170 if (usage_id == HID_USAGE_SENSOR_COLLECTION)
171 list_add(&callback->list, &pdata->dyn_callback_list);
172 else
173 list_add_tail(&callback->list, &pdata->dyn_callback_list);
161 spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags); 174 spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);
162 175
163 return 0; 176 return 0;
@@ -555,6 +568,7 @@ static int sensor_hub_probe(struct hid_device *hdev,
555 int dev_cnt; 568 int dev_cnt;
556 struct hid_sensor_hub_device *hsdev; 569 struct hid_sensor_hub_device *hsdev;
557 struct hid_sensor_hub_device *last_hsdev = NULL; 570 struct hid_sensor_hub_device *last_hsdev = NULL;
571 struct hid_sensor_hub_device *collection_hsdev = NULL;
558 572
559 sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL); 573 sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL);
560 if (!sd) { 574 if (!sd) {
@@ -601,7 +615,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
601 for (i = 0; i < hdev->maxcollection; ++i) { 615 for (i = 0; i < hdev->maxcollection; ++i) {
602 struct hid_collection *collection = &hdev->collection[i]; 616 struct hid_collection *collection = &hdev->collection[i];
603 617
604 if (collection->type == HID_COLLECTION_PHYSICAL) { 618 if (collection->type == HID_COLLECTION_PHYSICAL ||
619 collection->type == HID_COLLECTION_APPLICATION) {
605 620
606 hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev), 621 hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev),
607 GFP_KERNEL); 622 GFP_KERNEL);
@@ -638,10 +653,17 @@ static int sensor_hub_probe(struct hid_device *hdev,
638 hid_dbg(hdev, "Adding %s:%d\n", name, 653 hid_dbg(hdev, "Adding %s:%d\n", name,
639 hsdev->start_collection_index); 654 hsdev->start_collection_index);
640 sd->hid_sensor_client_cnt++; 655 sd->hid_sensor_client_cnt++;
656 if (collection_hsdev)
657 collection_hsdev->end_collection_index = i;
658 if (collection->type == HID_COLLECTION_APPLICATION &&
659 collection->usage == HID_USAGE_SENSOR_COLLECTION)
660 collection_hsdev = hsdev;
641 } 661 }
642 } 662 }
643 if (last_hsdev) 663 if (last_hsdev)
644 last_hsdev->end_collection_index = i; 664 last_hsdev->end_collection_index = i;
665 if (collection_hsdev)
666 collection_hsdev->end_collection_index = i;
645 667
646 ret = mfd_add_hotplug_devices(&hdev->dev, 668 ret = mfd_add_hotplug_devices(&hdev->dev,
647 sd->hid_sensor_hub_client_devs, 669 sd->hid_sensor_hub_client_devs,
diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h
index 109f0e633e01..f2ee90aed0c2 100644
--- a/include/linux/hid-sensor-ids.h
+++ b/include/linux/hid-sensor-ids.h
@@ -21,6 +21,8 @@
21 21
22#define HID_MAX_PHY_DEVICES 0xFF 22#define HID_MAX_PHY_DEVICES 0xFF
23 23
24#define HID_USAGE_SENSOR_COLLECTION 0x200001
25
24/* Accel 3D (200073) */ 26/* Accel 3D (200073) */
25#define HID_USAGE_SENSOR_ACCEL_3D 0x200073 27#define HID_USAGE_SENSOR_ACCEL_3D 0x200073
26#define HID_USAGE_SENSOR_DATA_ACCELERATION 0x200452 28#define HID_USAGE_SENSOR_DATA_ACCELERATION 0x200452