diff options
-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 |