diff options
author | Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> | 2015-02-20 00:31:26 +0100 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2015-02-23 15:11:52 +0100 |
commit | cb67126f32f008b9abe97fbfca9b23a797b2458a (patch) | |
tree | 37870932b6f72222d97970452e306b6ecd0b6fc7 /drivers | |
parent | HID: hid-sensor-hub: Allow parallel synchronous reads (diff) | |
download | linux-cb67126f32f008b9abe97fbfca9b23a797b2458a.tar.xz linux-cb67126f32f008b9abe97fbfca9b23a797b2458a.zip |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hid/hid-sensor-hub.c | 30 |
1 files changed, 26 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) for (i = 0; i < hdev->maxcollection; ++i) { struct hid_collection *collection = &hdev->collection[i]; - if (collection->type == HID_COLLECTION_PHYSICAL) + if (collection->type == HID_COLLECTION_PHYSICAL || + collection->type == HID_COLLECTION_APPLICATION) ++count; } @@ -118,7 +119,8 @@ static struct hid_sensor_hub_callbacks *sensor_hub_get_callback( spin_lock(&pdata->dyn_callback_lock); list_for_each_entry(callback, &pdata->dyn_callback_list, list) - if (callback->usage_id == usage_id && + if ((callback->usage_id == usage_id || + callback->usage_id == HID_USAGE_SENSOR_COLLECTION) && (collection_index >= callback->hsdev->start_collection_index) && (collection_index < @@ -157,7 +159,18 @@ int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev, callback->usage_callback = usage_callback; callback->usage_id = usage_id; callback->priv = NULL; - list_add_tail(&callback->list, &pdata->dyn_callback_list); + /* + * If there is a handler registered for the collection type, then + * it will handle all reports for sensors in this collection. If + * there is also an individual sensor handler registration, then + * we want to make sure that the reports are directed to collection + * handler, as this may be a fusion sensor. So add collection handlers + * to the beginning of the list, so that they are matched first. + */ + if (usage_id == HID_USAGE_SENSOR_COLLECTION) + list_add(&callback->list, &pdata->dyn_callback_list); + else + list_add_tail(&callback->list, &pdata->dyn_callback_list); spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags); return 0; @@ -555,6 +568,7 @@ static int sensor_hub_probe(struct hid_device *hdev, int dev_cnt; struct hid_sensor_hub_device *hsdev; struct hid_sensor_hub_device *last_hsdev = NULL; + struct hid_sensor_hub_device *collection_hsdev = NULL; sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL); if (!sd) { @@ -601,7 +615,8 @@ static int sensor_hub_probe(struct hid_device *hdev, for (i = 0; i < hdev->maxcollection; ++i) { struct hid_collection *collection = &hdev->collection[i]; - if (collection->type == HID_COLLECTION_PHYSICAL) { + if (collection->type == HID_COLLECTION_PHYSICAL || + collection->type == HID_COLLECTION_APPLICATION) { hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev), GFP_KERNEL); @@ -638,10 +653,17 @@ static int sensor_hub_probe(struct hid_device *hdev, hid_dbg(hdev, "Adding %s:%d\n", name, hsdev->start_collection_index); sd->hid_sensor_client_cnt++; + if (collection_hsdev) + collection_hsdev->end_collection_index = i; + if (collection->type == HID_COLLECTION_APPLICATION && + collection->usage == HID_USAGE_SENSOR_COLLECTION) + collection_hsdev = hsdev; } } if (last_hsdev) last_hsdev->end_collection_index = i; + if (collection_hsdev) + collection_hsdev->end_collection_index = i; ret = mfd_add_hotplug_devices(&hdev->dev, sd->hid_sensor_hub_client_devs, |