diff options
author | Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> | 2015-02-19 18:31:26 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2015-02-23 09:11:52 -0500 |
commit | cb67126f32f008b9abe97fbfca9b23a797b2458a (patch) | |
tree | 37870932b6f72222d97970452e306b6ecd0b6fc7 | |
parent | e651a1da442ae02a50081e38309dea5e89da2d41 (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.c | 30 | ||||
-rw-r--r-- | include/linux/hid-sensor-ids.h | 2 |
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 |