aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2015-04-13 17:43:34 -0400
committerJiri Kosina <jkosina@suse.cz>2015-04-13 17:43:34 -0400
commit2e455c27bddbf8cf6d1039daea40de8e6865c453 (patch)
tree3fd892aeae61b105e3c5c979550aabf54109a656
parent05f6d02521d4c7a656c5135d6d81c345ce531ac0 (diff)
parentb2eafd7282fdfd148fc09032540b0ff42bfedfbf (diff)
Merge branch 'for-4.1/sensor-hub' into for-linus
Conflicts: drivers/iio/common/hid-sensors/hid-sensor-trigger.c include/linux/hid-sensor-hub.h
-rw-r--r--Documentation/hid/hid-sensor.txt84
-rw-r--r--drivers/hid/Kconfig15
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-sensor-custom.c849
-rw-r--r--drivers/hid/hid-sensor-hub.c198
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c3
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-attributes.c24
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.c13
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c3
-rw-r--r--drivers/iio/light/hid-sensor-als.c3
-rw-r--r--drivers/iio/light/hid-sensor-prox.c3
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c3
-rw-r--r--drivers/iio/orientation/hid-sensor-incl-3d.c3
-rw-r--r--drivers/iio/pressure/hid-sensor-press.c3
-rw-r--r--drivers/rtc/rtc-hid-sensor-time.c2
-rw-r--r--include/linux/hid-sensor-hub.h55
-rw-r--r--include/linux/hid-sensor-ids.h2
17 files changed, 1154 insertions, 110 deletions
diff --git a/Documentation/hid/hid-sensor.txt b/Documentation/hid/hid-sensor.txt
index 948b0989c433..b287752a31cd 100644
--- a/Documentation/hid/hid-sensor.txt
+++ b/Documentation/hid/hid-sensor.txt
@@ -138,3 +138,87 @@ accelerometer wants to poll X axis value, then it can call this function with
138the usage id of X axis. HID sensors can provide events, so this is not necessary 138the usage id of X axis. HID sensors can provide events, so this is not necessary
139to poll for any field. If there is some new sample, the core driver will call 139to poll for any field. If there is some new sample, the core driver will call
140registered callback function to process the sample. 140registered callback function to process the sample.
141
142
143----------
144
145HID Custom and generic Sensors
146
147HID Sensor specification defines two special sensor usage types. Since they
148don't represent a standard sensor, it is not possible to define using Linux IIO
149type interfaces.
150The purpose of these sensors is to extend the functionality or provide a
151way to obfuscate the data being communicated by a sensor. Without knowing the
152mapping between the data and its encapsulated form, it is difficult for
153an application/driver to determine what data is being communicated by the sensor.
154This allows some differentiating use cases, where vendor can provide applications.
155Some common use cases are debug other sensors or to provide some events like
156keyboard attached/detached or lid open/close.
157
158To allow application to utilize these sensors, here they are exported uses sysfs
159attribute groups, attributes and misc device interface.
160
161An example of this representation on sysfs:
162/sys/devices/pci0000:00/INT33C2:00/i2c-0/i2c-INT33D1:00/0018:8086:09FA.0001/HID-SENSOR-2000e1.6.auto$ tree -R
163.
164????????? enable_sensor
165????????? feature-0-200316
166??????? ????????? feature-0-200316-maximum
167??????? ????????? feature-0-200316-minimum
168??????? ????????? feature-0-200316-name
169??????? ????????? feature-0-200316-size
170??????? ????????? feature-0-200316-unit-expo
171??????? ????????? feature-0-200316-units
172??????? ????????? feature-0-200316-value
173????????? feature-1-200201
174??????? ????????? feature-1-200201-maximum
175??????? ????????? feature-1-200201-minimum
176??????? ????????? feature-1-200201-name
177??????? ????????? feature-1-200201-size
178??????? ????????? feature-1-200201-unit-expo
179??????? ????????? feature-1-200201-units
180??????? ????????? feature-1-200201-value
181????????? input-0-200201
182??????? ????????? input-0-200201-maximum
183??????? ????????? input-0-200201-minimum
184??????? ????????? input-0-200201-name
185??????? ????????? input-0-200201-size
186??????? ????????? input-0-200201-unit-expo
187??????? ????????? input-0-200201-units
188??????? ????????? input-0-200201-value
189????????? input-1-200202
190??????? ????????? input-1-200202-maximum
191??????? ????????? input-1-200202-minimum
192??????? ????????? input-1-200202-name
193??????? ????????? input-1-200202-size
194??????? ????????? input-1-200202-unit-expo
195??????? ????????? input-1-200202-units
196??????? ????????? input-1-200202-value
197
198Here there is a custom sensors with four fields, two feature and two inputs.
199Each field is represented by a set of attributes. All fields except the "value"
200are read only. The value field is a RW field.
201Example
202/sys/bus/platform/devices/HID-SENSOR-2000e1.6.auto/feature-0-200316$ grep -r . *
203feature-0-200316-maximum:6
204feature-0-200316-minimum:0
205feature-0-200316-name:property-reporting-state
206feature-0-200316-size:1
207feature-0-200316-unit-expo:0
208feature-0-200316-units:25
209feature-0-200316-value:1
210
211How to enable such sensor?
212By default sensor can be power gated. To enable sysfs attribute "enable" can be
213used.
214$ echo 1 > enable_sensor
215
216Once enabled and powered on, sensor can report value using HID reports.
217These reports are pushed using misc device interface in a FIFO order.
218/dev$ tree | grep HID-SENSOR-2000e1.6.auto
219??????? ????????? 10:53 -> ../HID-SENSOR-2000e1.6.auto
220????????? HID-SENSOR-2000e1.6.auto
221
222Each reports can be of variable length preceded by a header. This header
223consist of a 32 bit usage id, 64 bit time stamp and 32 bit length field of raw
224data.
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 15901065727f..15338afdf7f9 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -878,6 +878,21 @@ config HID_SENSOR_HUB
878 for events and handle data streams. Each sensor driver can format 878 for events and handle data streams. Each sensor driver can format
879 data and present to user mode using input or IIO interface. 879 data and present to user mode using input or IIO interface.
880 880
881config HID_SENSOR_CUSTOM_SENSOR
882 tristate "HID Sensors hub custom sensor support"
883 depends on HID_SENSOR_HUB
884 default n
885 ---help---
886 HID Sensor hub specification allows definition of some custom and
887 generic sensors. Unlike other HID sensors, they can't be exported
888 via Linux IIO because of custom fields. This is up to the manufacturer
889 to decide how to interpret these special sensor ids and process in
890 the user space. Currently some manufacturers are using these ids for
891 sensor calibration and debugging other sensors. Manufacturers
892 should't use these special custom sensor ids to export any of the
893 standard sensors.
894 Select this config option for custom/generic sensor support.
895
881endmenu 896endmenu
882 897
883endif # HID 898endif # HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 9c399fe394fa..e4a21dfd7ef3 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -100,6 +100,7 @@ obj-$(CONFIG_HID_WACOM) += wacom.o
100obj-$(CONFIG_HID_WALTOP) += hid-waltop.o 100obj-$(CONFIG_HID_WALTOP) += hid-waltop.o
101obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o 101obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o
102obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o 102obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o
103obj-$(CONFIG_HID_SENSOR_CUSTOM_SENSOR) += hid-sensor-custom.o
103 104
104obj-$(CONFIG_USB_HID) += usbhid/ 105obj-$(CONFIG_USB_HID) += usbhid/
105obj-$(CONFIG_USB_MOUSE) += usbhid/ 106obj-$(CONFIG_USB_MOUSE) += usbhid/
diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c
new file mode 100644
index 000000000000..5614fee82347
--- /dev/null
+++ b/drivers/hid/hid-sensor-custom.c
@@ -0,0 +1,849 @@
1/*
2 * hid-sensor-custom.c
3 * Copyright (c) 2015, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/miscdevice.h>
19#include <linux/kfifo.h>
20#include <linux/sched.h>
21#include <linux/wait.h>
22#include <linux/poll.h>
23#include <linux/bsearch.h>
24#include <linux/platform_device.h>
25#include <linux/hid-sensor-hub.h>
26
27#define HID_CUSTOM_NAME_LENGTH 64
28#define HID_CUSTOM_MAX_CORE_ATTRS 10
29#define HID_CUSTOM_TOTAL_ATTRS (HID_CUSTOM_MAX_CORE_ATTRS + 1)
30#define HID_CUSTOM_FIFO_SIZE 4096
31#define HID_CUSTOM_MAX_FEATURE_BYTES 64
32
33struct hid_sensor_custom_field {
34 int report_id;
35 char group_name[HID_CUSTOM_NAME_LENGTH];
36 struct hid_sensor_hub_attribute_info attribute;
37 struct device_attribute sd_attrs[HID_CUSTOM_MAX_CORE_ATTRS];
38 char attr_name[HID_CUSTOM_TOTAL_ATTRS][HID_CUSTOM_NAME_LENGTH];
39 struct attribute *attrs[HID_CUSTOM_TOTAL_ATTRS];
40 struct attribute_group hid_custom_attribute_group;
41};
42
43struct hid_sensor_custom {
44 struct mutex mutex;
45 struct platform_device *pdev;
46 struct hid_sensor_hub_device *hsdev;
47 struct hid_sensor_hub_callbacks callbacks;
48 int sensor_field_count;
49 struct hid_sensor_custom_field *fields;
50 int input_field_count;
51 int input_report_size;
52 int input_report_recd_size;
53 bool input_skip_sample;
54 bool enable;
55 struct hid_sensor_custom_field *power_state;
56 struct hid_sensor_custom_field *report_state;
57 struct miscdevice custom_dev;
58 struct kfifo data_fifo;
59 unsigned long misc_opened;
60 wait_queue_head_t wait;
61};
62
63/* Header for each sample to user space via dev interface */
64struct hid_sensor_sample {
65 u32 usage_id;
66 u64 timestamp;
67 u32 raw_len;
68} __packed;
69
70static struct attribute hid_custom_attrs[] = {
71 {.name = "name", .mode = S_IRUGO},
72 {.name = "units", .mode = S_IRUGO},
73 {.name = "unit-expo", .mode = S_IRUGO},
74 {.name = "minimum", .mode = S_IRUGO},
75 {.name = "maximum", .mode = S_IRUGO},
76 {.name = "size", .mode = S_IRUGO},
77 {.name = "value", .mode = S_IWUSR | S_IRUGO},
78 {.name = NULL}
79};
80
81static const struct hid_custom_usage_desc {
82 int usage_id;
83 char *desc;
84} hid_custom_usage_desc_table[] = {
85 {0x200201, "event-sensor-state"},
86 {0x200202, "event-sensor-event"},
87 {0x200301, "property-friendly-name"},
88 {0x200302, "property-persistent-unique-id"},
89 {0x200303, "property-sensor-status"},
90 {0x200304, "property-min-report-interval"},
91 {0x200305, "property-sensor-manufacturer"},
92 {0x200306, "property-sensor-model"},
93 {0x200307, "property-sensor-serial-number"},
94 {0x200308, "property-sensor-description"},
95 {0x200309, "property-sensor-connection-type"},
96 {0x20030A, "property-sensor-device-path"},
97 {0x20030B, "property-hardware-revision"},
98 {0x20030C, "property-firmware-version"},
99 {0x20030D, "property-release-date"},
100 {0x20030E, "property-report-interval"},
101 {0x20030F, "property-change-sensitivity-absolute"},
102 {0x200310, "property-change-sensitivity-percent-range"},
103 {0x200311, "property-change-sensitivity-percent-relative"},
104 {0x200312, "property-accuracy"},
105 {0x200313, "property-resolution"},
106 {0x200314, "property-maximum"},
107 {0x200315, "property-minimum"},
108 {0x200316, "property-reporting-state"},
109 {0x200317, "property-sampling-rate"},
110 {0x200318, "property-response-curve"},
111 {0x200319, "property-power-state"},
112 {0x200540, "data-field-custom"},
113 {0x200541, "data-field-custom-usage"},
114 {0x200542, "data-field-custom-boolean-array"},
115 {0x200543, "data-field-custom-value"},
116 {0x200544, "data-field-custom-value_1"},
117 {0x200545, "data-field-custom-value_2"},
118 {0x200546, "data-field-custom-value_3"},
119 {0x200547, "data-field-custom-value_4"},
120 {0x200548, "data-field-custom-value_5"},
121 {0x200549, "data-field-custom-value_6"},
122 {0x20054A, "data-field-custom-value_7"},
123 {0x20054B, "data-field-custom-value_8"},
124 {0x20054C, "data-field-custom-value_9"},
125 {0x20054D, "data-field-custom-value_10"},
126 {0x20054E, "data-field-custom-value_11"},
127 {0x20054F, "data-field-custom-value_12"},
128 {0x200550, "data-field-custom-value_13"},
129 {0x200551, "data-field-custom-value_14"},
130 {0x200552, "data-field-custom-value_15"},
131 {0x200553, "data-field-custom-value_16"},
132 {0x200554, "data-field-custom-value_17"},
133 {0x200555, "data-field-custom-value_18"},
134 {0x200556, "data-field-custom-value_19"},
135 {0x200557, "data-field-custom-value_20"},
136 {0x200558, "data-field-custom-value_21"},
137 {0x200559, "data-field-custom-value_22"},
138 {0x20055A, "data-field-custom-value_23"},
139 {0x20055B, "data-field-custom-value_24"},
140 {0x20055C, "data-field-custom-value_25"},
141 {0x20055D, "data-field-custom-value_26"},
142 {0x20055E, "data-field-custom-value_27"},
143 {0x20055F, "data-field-custom-value_28"},
144};
145
146static int usage_id_cmp(const void *p1, const void *p2)
147{
148 if (*(int *)p1 < *(int *)p2)
149 return -1;
150
151 if (*(int *)p1 > *(int *)p2)
152 return 1;
153
154 return 0;
155}
156
157static ssize_t enable_sensor_show(struct device *dev,
158 struct device_attribute *attr, char *buf)
159{
160 struct platform_device *pdev = to_platform_device(dev);
161 struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
162
163 return sprintf(buf, "%d\n", sensor_inst->enable);
164}
165
166static int set_power_report_state(struct hid_sensor_custom *sensor_inst,
167 bool state)
168{
169 int power_val = -1;
170 int report_val = -1;
171 u32 power_state_usage_id;
172 u32 report_state_usage_id;
173 int ret;
174
175 /*
176 * It is possible that the power/report state ids are not present.
177 * In this case this function will return success. But if the
178 * ids are present, then it will return error if set fails.
179 */
180 if (state) {
181 power_state_usage_id =
182 HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
183 report_state_usage_id =
184 HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
185 } else {
186 power_state_usage_id =
187 HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM;
188 report_state_usage_id =
189 HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM;
190 }
191
192 if (sensor_inst->power_state)
193 power_val = hid_sensor_get_usage_index(sensor_inst->hsdev,
194 sensor_inst->power_state->attribute.report_id,
195 sensor_inst->power_state->attribute.index,
196 power_state_usage_id);
197 if (sensor_inst->report_state)
198 report_val = hid_sensor_get_usage_index(sensor_inst->hsdev,
199 sensor_inst->report_state->attribute.report_id,
200 sensor_inst->report_state->attribute.index,
201 report_state_usage_id);
202
203 if (power_val >= 0) {
204 power_val +=
205 sensor_inst->power_state->attribute.logical_minimum;
206 ret = sensor_hub_set_feature(sensor_inst->hsdev,
207 sensor_inst->power_state->attribute.report_id,
208 sensor_inst->power_state->attribute.index,
209 sizeof(power_val),
210 &power_val);
211 if (ret) {
212 hid_err(sensor_inst->hsdev->hdev,
213 "Set power state failed\n");
214 return ret;
215 }
216 }
217
218 if (report_val >= 0) {
219 report_val +=
220 sensor_inst->report_state->attribute.logical_minimum;
221 ret = sensor_hub_set_feature(sensor_inst->hsdev,
222 sensor_inst->report_state->attribute.report_id,
223 sensor_inst->report_state->attribute.index,
224 sizeof(report_val),
225 &report_val);
226 if (ret) {
227 hid_err(sensor_inst->hsdev->hdev,
228 "Set report state failed\n");
229 return ret;
230 }
231 }
232
233 return 0;
234}
235
236static ssize_t enable_sensor_store(struct device *dev,
237 struct device_attribute *attr,
238 const char *buf, size_t count)
239{
240 struct platform_device *pdev = to_platform_device(dev);
241 struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
242 int value;
243 int ret = -EINVAL;
244
245 if (kstrtoint(buf, 0, &value) != 0)
246 return -EINVAL;
247
248 mutex_lock(&sensor_inst->mutex);
249 if (value && !sensor_inst->enable) {
250 ret = sensor_hub_device_open(sensor_inst->hsdev);
251 if (ret)
252 goto unlock_state;
253
254 ret = set_power_report_state(sensor_inst, true);
255 if (ret) {
256 sensor_hub_device_close(sensor_inst->hsdev);
257 goto unlock_state;
258 }
259 sensor_inst->enable = true;
260 } else if (!value && sensor_inst->enable) {
261 ret = set_power_report_state(sensor_inst, false);
262 sensor_hub_device_close(sensor_inst->hsdev);
263 sensor_inst->enable = false;
264 }
265unlock_state:
266 mutex_unlock(&sensor_inst->mutex);
267 if (ret < 0)
268 return ret;
269
270 return count;
271}
272static DEVICE_ATTR_RW(enable_sensor);
273
274static struct attribute *enable_sensor_attrs[] = {
275 &dev_attr_enable_sensor.attr,
276 NULL,
277};
278
279static struct attribute_group enable_sensor_attr_group = {
280 .attrs = enable_sensor_attrs,
281};
282
283static ssize_t show_value(struct device *dev, struct device_attribute *attr,
284 char *buf)
285{
286 struct platform_device *pdev = to_platform_device(dev);
287 struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
288 struct hid_sensor_hub_attribute_info *attribute;
289 int index, usage, field_index;
290 char name[HID_CUSTOM_NAME_LENGTH];
291 bool feature = false;
292 bool input = false;
293 int value = 0;
294
295 if (sscanf(attr->attr.name, "feature-%d-%x-%s", &index, &usage,
296 name) == 3) {
297 feature = true;
298 field_index = index + sensor_inst->input_field_count;
299 } else if (sscanf(attr->attr.name, "input-%d-%x-%s", &index, &usage,
300 name) == 3) {
301 input = true;
302 field_index = index;
303 } else
304 return -EINVAL;
305
306 if (!strncmp(name, "value", strlen("value"))) {
307 u32 report_id;
308 int ret;
309
310 attribute = &sensor_inst->fields[field_index].attribute;
311 report_id = attribute->report_id;
312 if (feature) {
313 u8 values[HID_CUSTOM_MAX_FEATURE_BYTES];
314 int len = 0;
315 u64 value = 0;
316 int i = 0;
317
318 ret = sensor_hub_get_feature(sensor_inst->hsdev,
319 report_id,
320 index,
321 sizeof(values), values);
322 if (ret < 0)
323 return ret;
324
325 while (i < ret) {
326 if (i + attribute->size > ret) {
327 len += snprintf(&buf[len],
328 PAGE_SIZE - len,
329 "%d ", values[i]);
330 break;
331 }
332 switch (attribute->size) {
333 case 2:
334 value = (u64) *(u16 *)&values[i];
335 i += attribute->size;
336 break;
337 case 4:
338 value = (u64) *(u32 *)&values[i];
339 i += attribute->size;
340 break;
341 case 8:
342 value = *(u64 *)&values[i];
343 i += attribute->size;
344 break;
345 default:
346 value = (u64) values[i];
347 ++i;
348 break;
349 }
350 len += snprintf(&buf[len], PAGE_SIZE - len,
351 "%lld ", value);
352 }
353 len += snprintf(&buf[len], PAGE_SIZE - len, "\n");
354
355 return len;
356 } else if (input)
357 value = sensor_hub_input_attr_get_raw_value(
358 sensor_inst->hsdev,
359 sensor_inst->hsdev->usage,
360 usage, report_id,
361 SENSOR_HUB_SYNC);
362 } else if (!strncmp(name, "units", strlen("units")))
363 value = sensor_inst->fields[field_index].attribute.units;
364 else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
365 value = sensor_inst->fields[field_index].attribute.unit_expo;
366 else if (!strncmp(name, "size", strlen("size")))
367 value = sensor_inst->fields[field_index].attribute.size;
368 else if (!strncmp(name, "minimum", strlen("minimum")))
369 value = sensor_inst->fields[field_index].attribute.
370 logical_minimum;
371 else if (!strncmp(name, "maximum", strlen("maximum")))
372 value = sensor_inst->fields[field_index].attribute.
373 logical_maximum;
374 else if (!strncmp(name, "name", strlen("name"))) {
375 struct hid_custom_usage_desc *usage_desc;
376
377 usage_desc = bsearch(&usage, hid_custom_usage_desc_table,
378 ARRAY_SIZE(hid_custom_usage_desc_table),
379 sizeof(struct hid_custom_usage_desc),
380 usage_id_cmp);
381 if (usage_desc)
382 return snprintf(buf, PAGE_SIZE, "%s\n",
383 usage_desc->desc);
384 else
385 return sprintf(buf, "not-specified\n");
386 } else
387 return -EINVAL;
388
389 return sprintf(buf, "%d\n", value);
390}
391
392static ssize_t store_value(struct device *dev, struct device_attribute *attr,
393 const char *buf, size_t count)
394{
395 struct platform_device *pdev = to_platform_device(dev);
396 struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
397 int index, field_index, usage;
398 char name[HID_CUSTOM_NAME_LENGTH];
399 int value;
400
401 if (sscanf(attr->attr.name, "feature-%d-%x-%s", &index, &usage,
402 name) == 3) {
403 field_index = index + sensor_inst->input_field_count;
404 } else
405 return -EINVAL;
406
407 if (!strncmp(name, "value", strlen("value"))) {
408 u32 report_id;
409 int ret;
410
411 if (kstrtoint(buf, 0, &value) != 0)
412 return -EINVAL;
413
414 report_id = sensor_inst->fields[field_index].attribute.
415 report_id;
416 ret = sensor_hub_set_feature(sensor_inst->hsdev, report_id,
417 index, sizeof(value), &value);
418 } else
419 return -EINVAL;
420
421 return count;
422}
423
424static int hid_sensor_capture_sample(struct hid_sensor_hub_device *hsdev,
425 unsigned usage_id, size_t raw_len,
426 char *raw_data, void *priv)
427{
428 struct hid_sensor_custom *sensor_inst = platform_get_drvdata(priv);
429 struct hid_sensor_sample header;
430
431 /* If any error occurs in a sample, rest of the fields are ignored */
432 if (sensor_inst->input_skip_sample) {
433 hid_err(sensor_inst->hsdev->hdev, "Skipped remaining data\n");
434 return 0;
435 }
436
437 hid_dbg(sensor_inst->hsdev->hdev, "%s received %d of %d\n", __func__,
438 (int) (sensor_inst->input_report_recd_size + raw_len),
439 sensor_inst->input_report_size);
440
441 if (!test_bit(0, &sensor_inst->misc_opened))
442 return 0;
443
444 if (!sensor_inst->input_report_recd_size) {
445 int required_size = sizeof(struct hid_sensor_sample) +
446 sensor_inst->input_report_size;
447 header.usage_id = hsdev->usage;
448 header.raw_len = sensor_inst->input_report_size;
449 header.timestamp = ktime_get_real_ns();
450 if (kfifo_avail(&sensor_inst->data_fifo) >= required_size) {
451 kfifo_in(&sensor_inst->data_fifo,
452 (unsigned char *)&header,
453 sizeof(header));
454 } else
455 sensor_inst->input_skip_sample = true;
456 }
457 if (kfifo_avail(&sensor_inst->data_fifo) >= raw_len)
458 kfifo_in(&sensor_inst->data_fifo, (unsigned char *)raw_data,
459 raw_len);
460
461 sensor_inst->input_report_recd_size += raw_len;
462
463 return 0;
464}
465
466static int hid_sensor_send_event(struct hid_sensor_hub_device *hsdev,
467 unsigned usage_id, void *priv)
468{
469 struct hid_sensor_custom *sensor_inst = platform_get_drvdata(priv);
470
471 if (!test_bit(0, &sensor_inst->misc_opened))
472 return 0;
473
474 sensor_inst->input_report_recd_size = 0;
475 sensor_inst->input_skip_sample = false;
476
477 wake_up(&sensor_inst->wait);
478
479 return 0;
480}
481
482static int hid_sensor_custom_add_field(struct hid_sensor_custom *sensor_inst,
483 int index, int report_type,
484 struct hid_report *report,
485 struct hid_field *field)
486{
487 struct hid_sensor_custom_field *sensor_field;
488 void *fields;
489
490 fields = krealloc(sensor_inst->fields,
491 (sensor_inst->sensor_field_count + 1) *
492 sizeof(struct hid_sensor_custom_field), GFP_KERNEL);
493 if (!fields) {
494 kfree(sensor_inst->fields);
495 return -ENOMEM;
496 }
497 sensor_inst->fields = fields;
498 sensor_field = &sensor_inst->fields[sensor_inst->sensor_field_count];
499 sensor_field->attribute.usage_id = sensor_inst->hsdev->usage;
500 if (field->logical)
501 sensor_field->attribute.attrib_id = field->logical;
502 else
503 sensor_field->attribute.attrib_id = field->usage[0].hid;
504
505 sensor_field->attribute.index = index;
506 sensor_field->attribute.report_id = report->id;
507 sensor_field->attribute.units = field->unit;
508 sensor_field->attribute.unit_expo = field->unit_exponent;
509 sensor_field->attribute.size = (field->report_size / 8);
510 sensor_field->attribute.logical_minimum = field->logical_minimum;
511 sensor_field->attribute.logical_maximum = field->logical_maximum;
512
513 if (report_type == HID_FEATURE_REPORT)
514 snprintf(sensor_field->group_name,
515 sizeof(sensor_field->group_name), "feature-%x-%x",
516 sensor_field->attribute.index,
517 sensor_field->attribute.attrib_id);
518 else if (report_type == HID_INPUT_REPORT) {
519 snprintf(sensor_field->group_name,
520 sizeof(sensor_field->group_name),
521 "input-%x-%x", sensor_field->attribute.index,
522 sensor_field->attribute.attrib_id);
523 sensor_inst->input_field_count++;
524 sensor_inst->input_report_size += (field->report_size *
525 field->report_count) / 8;
526 }
527
528 memset(&sensor_field->hid_custom_attribute_group, 0,
529 sizeof(struct attribute_group));
530 sensor_inst->sensor_field_count++;
531
532 return 0;
533}
534
535static int hid_sensor_custom_add_fields(struct hid_sensor_custom *sensor_inst,
536 struct hid_report_enum *report_enum,
537 int report_type)
538{
539 int i;
540 int ret;
541 struct hid_report *report;
542 struct hid_field *field;
543 struct hid_sensor_hub_device *hsdev = sensor_inst->hsdev;
544
545 list_for_each_entry(report, &report_enum->report_list, list) {
546 for (i = 0; i < report->maxfield; ++i) {
547 field = report->field[i];
548 if (field->maxusage &&
549 ((field->usage[0].collection_index >=
550 hsdev->start_collection_index) &&
551 (field->usage[0].collection_index <
552 hsdev->end_collection_index))) {
553
554 ret = hid_sensor_custom_add_field(sensor_inst,
555 i,
556 report_type,
557 report,
558 field);
559 if (ret)
560 return ret;
561
562 }
563 }
564 }
565
566 return 0;
567}
568
569static int hid_sensor_custom_add_attributes(struct hid_sensor_custom
570 *sensor_inst)
571{
572 struct hid_sensor_hub_device *hsdev = sensor_inst->hsdev;
573 struct hid_device *hdev = hsdev->hdev;
574 int ret = -1;
575 int i, j;
576
577 for (j = 0; j < HID_REPORT_TYPES; ++j) {
578 if (j == HID_OUTPUT_REPORT)
579 continue;
580
581 ret = hid_sensor_custom_add_fields(sensor_inst,
582 &hdev->report_enum[j], j);
583 if (ret)
584 return ret;
585
586 }
587
588 /* Create sysfs attributes */
589 for (i = 0; i < sensor_inst->sensor_field_count; ++i) {
590 j = 0;
591 while (j < HID_CUSTOM_TOTAL_ATTRS &&
592 hid_custom_attrs[j].name) {
593 struct device_attribute *device_attr;
594
595 device_attr = &sensor_inst->fields[i].sd_attrs[j];
596
597 snprintf((char *)&sensor_inst->fields[i].attr_name[j],
598 HID_CUSTOM_NAME_LENGTH, "%s-%s",
599 sensor_inst->fields[i].group_name,
600 hid_custom_attrs[j].name);
601 sysfs_attr_init(&device_attr->attr);
602 device_attr->attr.name =
603 (char *)&sensor_inst->fields[i].attr_name[j];
604 device_attr->attr.mode = hid_custom_attrs[j].mode;
605 device_attr->show = show_value;
606 if (hid_custom_attrs[j].mode & S_IWUSR)
607 device_attr->store = store_value;
608 sensor_inst->fields[i].attrs[j] = &device_attr->attr;
609 ++j;
610 }
611 sensor_inst->fields[i].attrs[j] = NULL;
612 sensor_inst->fields[i].hid_custom_attribute_group.attrs =
613 sensor_inst->fields[i].attrs;
614 sensor_inst->fields[i].hid_custom_attribute_group.name =
615 sensor_inst->fields[i].group_name;
616 ret = sysfs_create_group(&sensor_inst->pdev->dev.kobj,
617 &sensor_inst->fields[i].
618 hid_custom_attribute_group);
619 if (ret)
620 break;
621
622 /* For power or report field store indexes */
623 if (sensor_inst->fields[i].attribute.attrib_id ==
624 HID_USAGE_SENSOR_PROY_POWER_STATE)
625 sensor_inst->power_state = &sensor_inst->fields[i];
626 else if (sensor_inst->fields[i].attribute.attrib_id ==
627 HID_USAGE_SENSOR_PROP_REPORT_STATE)
628 sensor_inst->report_state = &sensor_inst->fields[i];
629 }
630
631 return ret;
632}
633
634static void hid_sensor_custom_remove_attributes(struct hid_sensor_custom *
635 sensor_inst)
636{
637 int i;
638
639 for (i = 0; i < sensor_inst->sensor_field_count; ++i)
640 sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
641 &sensor_inst->fields[i].
642 hid_custom_attribute_group);
643
644 kfree(sensor_inst->fields);
645}
646
647static ssize_t hid_sensor_custom_read(struct file *file, char __user *buf,
648 size_t count, loff_t *f_ps)
649{
650 struct hid_sensor_custom *sensor_inst;
651 unsigned int copied;
652 int ret;
653
654 sensor_inst = container_of(file->private_data,
655 struct hid_sensor_custom, custom_dev);
656
657 if (count < sizeof(struct hid_sensor_sample))
658 return -EINVAL;
659
660 do {
661 if (kfifo_is_empty(&sensor_inst->data_fifo)) {
662 if (file->f_flags & O_NONBLOCK)
663 return -EAGAIN;
664
665 ret = wait_event_interruptible(sensor_inst->wait,
666 !kfifo_is_empty(&sensor_inst->data_fifo));
667 if (ret)
668 return ret;
669 }
670 ret = kfifo_to_user(&sensor_inst->data_fifo, buf, count,
671 &copied);
672 if (ret)
673 return ret;
674
675 } while (copied == 0);
676
677 return copied;
678}
679
680static int hid_sensor_custom_release(struct inode *inode, struct file *file)
681{
682 struct hid_sensor_custom *sensor_inst;
683
684 sensor_inst = container_of(file->private_data,
685 struct hid_sensor_custom, custom_dev);
686
687 clear_bit(0, &sensor_inst->misc_opened);
688
689 return 0;
690}
691
692static int hid_sensor_custom_open(struct inode *inode, struct file *file)
693{
694 struct hid_sensor_custom *sensor_inst;
695
696 sensor_inst = container_of(file->private_data,
697 struct hid_sensor_custom, custom_dev);
698 /* We essentially have single reader and writer */
699 if (test_and_set_bit(0, &sensor_inst->misc_opened))
700 return -EBUSY;
701
702 return nonseekable_open(inode, file);
703}
704
705static unsigned int hid_sensor_custom_poll(struct file *file,
706 struct poll_table_struct *wait)
707{
708 struct hid_sensor_custom *sensor_inst;
709 unsigned int mask = 0;
710
711 sensor_inst = container_of(file->private_data,
712 struct hid_sensor_custom, custom_dev);
713
714 poll_wait(file, &sensor_inst->wait, wait);
715
716 if (!kfifo_is_empty(&sensor_inst->data_fifo))
717 mask = POLLIN | POLLRDNORM;
718
719 return mask;
720}
721
722static const struct file_operations hid_sensor_custom_fops = {
723 .open = hid_sensor_custom_open,
724 .read = hid_sensor_custom_read,
725 .release = hid_sensor_custom_release,
726 .poll = hid_sensor_custom_poll,
727 .llseek = noop_llseek,
728};
729
730static int hid_sensor_custom_dev_if_add(struct hid_sensor_custom *sensor_inst)
731{
732 int ret;
733
734 ret = kfifo_alloc(&sensor_inst->data_fifo, HID_CUSTOM_FIFO_SIZE,
735 GFP_KERNEL);
736 if (ret)
737 return ret;
738
739 init_waitqueue_head(&sensor_inst->wait);
740
741 sensor_inst->custom_dev.minor = MISC_DYNAMIC_MINOR;
742 sensor_inst->custom_dev.name = dev_name(&sensor_inst->pdev->dev);
743 sensor_inst->custom_dev.fops = &hid_sensor_custom_fops,
744 ret = misc_register(&sensor_inst->custom_dev);
745 if (ret) {
746 kfifo_free(&sensor_inst->data_fifo);
747 return ret;
748 }
749 return 0;
750}
751
752static void hid_sensor_custom_dev_if_remove(struct hid_sensor_custom
753 *sensor_inst)
754{
755 wake_up(&sensor_inst->wait);
756 misc_deregister(&sensor_inst->custom_dev);
757 kfifo_free(&sensor_inst->data_fifo);
758
759}
760
761static int hid_sensor_custom_probe(struct platform_device *pdev)
762{
763 struct hid_sensor_custom *sensor_inst;
764 struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
765 int ret;
766
767 sensor_inst = devm_kzalloc(&pdev->dev, sizeof(*sensor_inst),
768 GFP_KERNEL);
769 if (!sensor_inst)
770 return -ENOMEM;
771
772 sensor_inst->callbacks.capture_sample = hid_sensor_capture_sample;
773 sensor_inst->callbacks.send_event = hid_sensor_send_event;
774 sensor_inst->callbacks.pdev = pdev;
775 sensor_inst->hsdev = hsdev;
776 sensor_inst->pdev = pdev;
777 mutex_init(&sensor_inst->mutex);
778 platform_set_drvdata(pdev, sensor_inst);
779 ret = sensor_hub_register_callback(hsdev, hsdev->usage,
780 &sensor_inst->callbacks);
781 if (ret < 0) {
782 dev_err(&pdev->dev, "callback reg failed\n");
783 return ret;
784 }
785
786 ret = sysfs_create_group(&sensor_inst->pdev->dev.kobj,
787 &enable_sensor_attr_group);
788 if (ret)
789 goto err_remove_callback;
790
791 ret = hid_sensor_custom_add_attributes(sensor_inst);
792 if (ret)
793 goto err_remove_group;
794
795 ret = hid_sensor_custom_dev_if_add(sensor_inst);
796 if (ret)
797 goto err_remove_attributes;
798
799 return 0;
800
801err_remove_attributes:
802 hid_sensor_custom_remove_attributes(sensor_inst);
803err_remove_group:
804 sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
805 &enable_sensor_attr_group);
806err_remove_callback:
807 sensor_hub_remove_callback(hsdev, hsdev->usage);
808
809 return ret;
810}
811
812static int hid_sensor_custom_remove(struct platform_device *pdev)
813{
814 struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
815 struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
816
817 hid_sensor_custom_dev_if_remove(sensor_inst);
818 hid_sensor_custom_remove_attributes(sensor_inst);
819 sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
820 &enable_sensor_attr_group);
821 sensor_hub_remove_callback(hsdev, hsdev->usage);
822
823 return 0;
824}
825
826static struct platform_device_id hid_sensor_custom_ids[] = {
827 {
828 .name = "HID-SENSOR-2000e1",
829 },
830 {
831 .name = "HID-SENSOR-2000e2",
832 },
833 { /* sentinel */ }
834};
835MODULE_DEVICE_TABLE(platform, hid_sensor_custom_ids);
836
837static struct platform_driver hid_sensor_custom_platform_driver = {
838 .id_table = hid_sensor_custom_ids,
839 .driver = {
840 .name = KBUILD_MODNAME,
841 },
842 .probe = hid_sensor_custom_probe,
843 .remove = hid_sensor_custom_remove,
844};
845module_platform_driver(hid_sensor_custom_platform_driver);
846
847MODULE_DESCRIPTION("HID Sensor Custom and Generic sensor Driver");
848MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
849MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index e54ce1097e2c..c3f6f1e311ea 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -29,29 +29,10 @@
29#define HID_SENSOR_HUB_ENUM_QUIRK 0x01 29#define HID_SENSOR_HUB_ENUM_QUIRK 0x01
30 30
31/** 31/**
32 * struct sensor_hub_pending - Synchronous read pending information
33 * @status: Pending status true/false.
34 * @ready: Completion synchronization data.
35 * @usage_id: Usage id for physical device, E.g. Gyro usage id.
36 * @attr_usage_id: Usage Id of a field, E.g. X-AXIS for a gyro.
37 * @raw_size: Response size for a read request.
38 * @raw_data: Place holder for received response.
39 */
40struct sensor_hub_pending {
41 bool status;
42 struct completion ready;
43 u32 usage_id;
44 u32 attr_usage_id;
45 int raw_size;
46 u8 *raw_data;
47};
48
49/**
50 * struct sensor_hub_data - Hold a instance data for a HID hub device 32 * struct sensor_hub_data - Hold a instance data for a HID hub device
51 * @hsdev: Stored hid instance for current hub device. 33 * @hsdev: Stored hid instance for current hub device.
52 * @mutex: Mutex to serialize synchronous request. 34 * @mutex: Mutex to serialize synchronous request.
53 * @lock: Spin lock to protect pending request structure. 35 * @lock: Spin lock to protect pending request structure.
54 * @pending: Holds information of pending sync read request.
55 * @dyn_callback_list: Holds callback function 36 * @dyn_callback_list: Holds callback function
56 * @dyn_callback_lock: spin lock to protect callback list 37 * @dyn_callback_lock: spin lock to protect callback list
57 * @hid_sensor_hub_client_devs: Stores all MFD cells for a hub instance. 38 * @hid_sensor_hub_client_devs: Stores all MFD cells for a hub instance.
@@ -61,7 +42,6 @@ struct sensor_hub_pending {
61struct sensor_hub_data { 42struct sensor_hub_data {
62 struct mutex mutex; 43 struct mutex mutex;
63 spinlock_t lock; 44 spinlock_t lock;
64 struct sensor_hub_pending pending;
65 struct list_head dyn_callback_list; 45 struct list_head dyn_callback_list;
66 spinlock_t dyn_callback_lock; 46 spinlock_t dyn_callback_lock;
67 struct mfd_cell *hid_sensor_hub_client_devs; 47 struct mfd_cell *hid_sensor_hub_client_devs;
@@ -106,7 +86,8 @@ static int sensor_hub_get_physical_device_count(struct hid_device *hdev)
106 86
107 for (i = 0; i < hdev->maxcollection; ++i) { 87 for (i = 0; i < hdev->maxcollection; ++i) {
108 struct hid_collection *collection = &hdev->collection[i]; 88 struct hid_collection *collection = &hdev->collection[i];
109 if (collection->type == HID_COLLECTION_PHYSICAL) 89 if (collection->type == HID_COLLECTION_PHYSICAL ||
90 collection->type == HID_COLLECTION_APPLICATION)
110 ++count; 91 ++count;
111 } 92 }
112 93
@@ -139,7 +120,8 @@ static struct hid_sensor_hub_callbacks *sensor_hub_get_callback(
139 120
140 spin_lock_irqsave(&pdata->dyn_callback_lock, flags); 121 spin_lock_irqsave(&pdata->dyn_callback_lock, flags);
141 list_for_each_entry(callback, &pdata->dyn_callback_list, list) 122 list_for_each_entry(callback, &pdata->dyn_callback_list, list)
142 if (callback->usage_id == usage_id && 123 if ((callback->usage_id == usage_id ||
124 callback->usage_id == HID_USAGE_SENSOR_COLLECTION) &&
143 (collection_index >= 125 (collection_index >=
144 callback->hsdev->start_collection_index) && 126 callback->hsdev->start_collection_index) &&
145 (collection_index < 127 (collection_index <
@@ -179,7 +161,18 @@ int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
179 callback->usage_callback = usage_callback; 161 callback->usage_callback = usage_callback;
180 callback->usage_id = usage_id; 162 callback->usage_id = usage_id;
181 callback->priv = NULL; 163 callback->priv = NULL;
182 list_add_tail(&callback->list, &pdata->dyn_callback_list); 164 /*
165 * If there is a handler registered for the collection type, then
166 * it will handle all reports for sensors in this collection. If
167 * there is also an individual sensor handler registration, then
168 * we want to make sure that the reports are directed to collection
169 * handler, as this may be a fusion sensor. So add collection handlers
170 * to the beginning of the list, so that they are matched first.
171 */
172 if (usage_id == HID_USAGE_SENSOR_COLLECTION)
173 list_add(&callback->list, &pdata->dyn_callback_list);
174 else
175 list_add_tail(&callback->list, &pdata->dyn_callback_list);
183 spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags); 176 spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);
184 177
185 return 0; 178 return 0;
@@ -208,10 +201,14 @@ int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,
208EXPORT_SYMBOL_GPL(sensor_hub_remove_callback); 201EXPORT_SYMBOL_GPL(sensor_hub_remove_callback);
209 202
210int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, 203int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
211 u32 field_index, s32 value) 204 u32 field_index, int buffer_size, void *buffer)
212{ 205{
213 struct hid_report *report; 206 struct hid_report *report;
214 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); 207 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
208 __s32 *buf32 = buffer;
209 int i = 0;
210 int remaining_bytes;
211 __s32 value;
215 int ret = 0; 212 int ret = 0;
216 213
217 mutex_lock(&data->mutex); 214 mutex_lock(&data->mutex);
@@ -220,7 +217,21 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
220 ret = -EINVAL; 217 ret = -EINVAL;
221 goto done_proc; 218 goto done_proc;
222 } 219 }
223 hid_set_field(report->field[field_index], 0, value); 220
221 remaining_bytes = do_div(buffer_size, sizeof(__s32));
222 if (buffer_size) {
223 for (i = 0; i < buffer_size; ++i) {
224 hid_set_field(report->field[field_index], i,
225 (__force __s32)cpu_to_le32(*buf32));
226 ++buf32;
227 }
228 }
229 if (remaining_bytes) {
230 value = 0;
231 memcpy(&value, (u8 *)buf32, remaining_bytes);
232 hid_set_field(report->field[field_index], i,
233 (__force __s32)cpu_to_le32(value));
234 }
224 hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT); 235 hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT);
225 hid_hw_wait(hsdev->hdev); 236 hid_hw_wait(hsdev->hdev);
226 237
@@ -232,10 +243,11 @@ done_proc:
232EXPORT_SYMBOL_GPL(sensor_hub_set_feature); 243EXPORT_SYMBOL_GPL(sensor_hub_set_feature);
233 244
234int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, 245int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
235 u32 field_index, s32 *value) 246 u32 field_index, int buffer_size, void *buffer)
236{ 247{
237 struct hid_report *report; 248 struct hid_report *report;
238 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); 249 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
250 int report_size;
239 int ret = 0; 251 int ret = 0;
240 252
241 mutex_lock(&data->mutex); 253 mutex_lock(&data->mutex);
@@ -247,7 +259,17 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
247 } 259 }
248 hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT); 260 hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
249 hid_hw_wait(hsdev->hdev); 261 hid_hw_wait(hsdev->hdev);
250 *value = report->field[field_index]->value[0]; 262
263 /* calculate number of bytes required to read this field */
264 report_size = DIV_ROUND_UP(report->field[field_index]->report_size,
265 8) *
266 report->field[field_index]->report_count;
267 if (!report_size) {
268 ret = -EINVAL;
269 goto done_proc;
270 }
271 ret = min(report_size, buffer_size);
272 memcpy(buffer, report->field[field_index]->value, ret);
251 273
252done_proc: 274done_proc:
253 mutex_unlock(&data->mutex); 275 mutex_unlock(&data->mutex);
@@ -259,47 +281,54 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
259 281
260int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, 282int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
261 u32 usage_id, 283 u32 usage_id,
262 u32 attr_usage_id, u32 report_id) 284 u32 attr_usage_id, u32 report_id,
285 enum sensor_hub_read_flags flag)
263{ 286{
264 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); 287 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
265 unsigned long flags; 288 unsigned long flags;
266 struct hid_report *report; 289 struct hid_report *report;
267 int ret_val = 0; 290 int ret_val = 0;
268 291
269 mutex_lock(&data->mutex); 292 report = sensor_hub_report(report_id, hsdev->hdev,
270 memset(&data->pending, 0, sizeof(data->pending)); 293 HID_INPUT_REPORT);
271 init_completion(&data->pending.ready);
272 data->pending.usage_id = usage_id;
273 data->pending.attr_usage_id = attr_usage_id;
274 data->pending.raw_size = 0;
275
276 spin_lock_irqsave(&data->lock, flags);
277 data->pending.status = true;
278 spin_unlock_irqrestore(&data->lock, flags);
279 report = sensor_hub_report(report_id, hsdev->hdev, HID_INPUT_REPORT);
280 if (!report) 294 if (!report)
281 goto err_free; 295 return -EINVAL;
282 296
283 hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT); 297 mutex_lock(&hsdev->mutex);
284 wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5); 298 if (flag == SENSOR_HUB_SYNC) {
285 switch (data->pending.raw_size) { 299 memset(&hsdev->pending, 0, sizeof(hsdev->pending));
286 case 1: 300 init_completion(&hsdev->pending.ready);
287 ret_val = *(u8 *)data->pending.raw_data; 301 hsdev->pending.usage_id = usage_id;
288 break; 302 hsdev->pending.attr_usage_id = attr_usage_id;
289 case 2: 303 hsdev->pending.raw_size = 0;
290 ret_val = *(u16 *)data->pending.raw_data; 304
291 break; 305 spin_lock_irqsave(&data->lock, flags);
292 case 4: 306 hsdev->pending.status = true;
293 ret_val = *(u32 *)data->pending.raw_data; 307 spin_unlock_irqrestore(&data->lock, flags);
294 break;
295 default:
296 ret_val = 0;
297 } 308 }
298 kfree(data->pending.raw_data); 309 mutex_lock(&data->mutex);
299 310 hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
300err_free:
301 data->pending.status = false;
302 mutex_unlock(&data->mutex); 311 mutex_unlock(&data->mutex);
312 if (flag == SENSOR_HUB_SYNC) {
313 wait_for_completion_interruptible_timeout(
314 &hsdev->pending.ready, HZ*5);
315 switch (hsdev->pending.raw_size) {
316 case 1:
317 ret_val = *(u8 *)hsdev->pending.raw_data;
318 break;
319 case 2:
320 ret_val = *(u16 *)hsdev->pending.raw_data;
321 break;
322 case 4:
323 ret_val = *(u32 *)hsdev->pending.raw_data;
324 break;
325 default:
326 ret_val = 0;
327 }
328 kfree(hsdev->pending.raw_data);
329 hsdev->pending.status = false;
330 }
331 mutex_unlock(&hsdev->mutex);
303 332
304 return ret_val; 333 return ret_val;
305} 334}
@@ -455,16 +484,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
455 report->field[i]->report_count)/8); 484 report->field[i]->report_count)/8);
456 sz = (report->field[i]->report_size * 485 sz = (report->field[i]->report_size *
457 report->field[i]->report_count)/8; 486 report->field[i]->report_count)/8;
458 if (pdata->pending.status && pdata->pending.attr_usage_id ==
459 report->field[i]->usage->hid) {
460 hid_dbg(hdev, "data was pending ...\n");
461 pdata->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);
462 if (pdata->pending.raw_data)
463 pdata->pending.raw_size = sz;
464 else
465 pdata->pending.raw_size = 0;
466 complete(&pdata->pending.ready);
467 }
468 collection = &hdev->collection[ 487 collection = &hdev->collection[
469 report->field[i]->usage->collection_index]; 488 report->field[i]->usage->collection_index];
470 hid_dbg(hdev, "collection->usage %x\n", 489 hid_dbg(hdev, "collection->usage %x\n",
@@ -474,8 +493,23 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
474 report->field[i]->physical, 493 report->field[i]->physical,
475 report->field[i]->usage[0].collection_index, 494 report->field[i]->usage[0].collection_index,
476 &hsdev, &priv); 495 &hsdev, &priv);
477 496 if (!callback) {
478 if (callback && callback->capture_sample) { 497 ptr += sz;
498 continue;
499 }
500 if (hsdev->pending.status && (hsdev->pending.attr_usage_id ==
501 report->field[i]->usage->hid ||
502 hsdev->pending.attr_usage_id ==
503 report->field[i]->logical)) {
504 hid_dbg(hdev, "data was pending ...\n");
505 hsdev->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);
506 if (hsdev->pending.raw_data)
507 hsdev->pending.raw_size = sz;
508 else
509 hsdev->pending.raw_size = 0;
510 complete(&hsdev->pending.ready);
511 }
512 if (callback->capture_sample) {
479 if (report->field[i]->logical) 513 if (report->field[i]->logical)
480 callback->capture_sample(hsdev, 514 callback->capture_sample(hsdev,
481 report->field[i]->logical, sz, ptr, 515 report->field[i]->logical, sz, ptr,
@@ -572,6 +606,7 @@ static int sensor_hub_probe(struct hid_device *hdev,
572 int dev_cnt; 606 int dev_cnt;
573 struct hid_sensor_hub_device *hsdev; 607 struct hid_sensor_hub_device *hsdev;
574 struct hid_sensor_hub_device *last_hsdev = NULL; 608 struct hid_sensor_hub_device *last_hsdev = NULL;
609 struct hid_sensor_hub_device *collection_hsdev = NULL;
575 610
576 sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL); 611 sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL);
577 if (!sd) { 612 if (!sd) {
@@ -618,7 +653,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
618 for (i = 0; i < hdev->maxcollection; ++i) { 653 for (i = 0; i < hdev->maxcollection; ++i) {
619 struct hid_collection *collection = &hdev->collection[i]; 654 struct hid_collection *collection = &hdev->collection[i];
620 655
621 if (collection->type == HID_COLLECTION_PHYSICAL) { 656 if (collection->type == HID_COLLECTION_PHYSICAL ||
657 collection->type == HID_COLLECTION_APPLICATION) {
622 658
623 hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev), 659 hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev),
624 GFP_KERNEL); 660 GFP_KERNEL);
@@ -630,6 +666,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
630 hsdev->hdev = hdev; 666 hsdev->hdev = hdev;
631 hsdev->vendor_id = hdev->vendor; 667 hsdev->vendor_id = hdev->vendor;
632 hsdev->product_id = hdev->product; 668 hsdev->product_id = hdev->product;
669 hsdev->usage = collection->usage;
670 mutex_init(&hsdev->mutex);
633 hsdev->start_collection_index = i; 671 hsdev->start_collection_index = i;
634 if (last_hsdev) 672 if (last_hsdev)
635 last_hsdev->end_collection_index = i; 673 last_hsdev->end_collection_index = i;
@@ -653,10 +691,17 @@ static int sensor_hub_probe(struct hid_device *hdev,
653 hid_dbg(hdev, "Adding %s:%d\n", name, 691 hid_dbg(hdev, "Adding %s:%d\n", name,
654 hsdev->start_collection_index); 692 hsdev->start_collection_index);
655 sd->hid_sensor_client_cnt++; 693 sd->hid_sensor_client_cnt++;
694 if (collection_hsdev)
695 collection_hsdev->end_collection_index = i;
696 if (collection->type == HID_COLLECTION_APPLICATION &&
697 collection->usage == HID_USAGE_SENSOR_COLLECTION)
698 collection_hsdev = hsdev;
656 } 699 }
657 } 700 }
658 if (last_hsdev) 701 if (last_hsdev)
659 last_hsdev->end_collection_index = i; 702 last_hsdev->end_collection_index = i;
703 if (collection_hsdev)
704 collection_hsdev->end_collection_index = i;
660 705
661 ret = mfd_add_hotplug_devices(&hdev->dev, 706 ret = mfd_add_hotplug_devices(&hdev->dev,
662 sd->hid_sensor_hub_client_devs, 707 sd->hid_sensor_hub_client_devs,
@@ -676,13 +721,18 @@ static void sensor_hub_remove(struct hid_device *hdev)
676{ 721{
677 struct sensor_hub_data *data = hid_get_drvdata(hdev); 722 struct sensor_hub_data *data = hid_get_drvdata(hdev);
678 unsigned long flags; 723 unsigned long flags;
724 int i;
679 725
680 hid_dbg(hdev, " hardware removed\n"); 726 hid_dbg(hdev, " hardware removed\n");
681 hid_hw_close(hdev); 727 hid_hw_close(hdev);
682 hid_hw_stop(hdev); 728 hid_hw_stop(hdev);
683 spin_lock_irqsave(&data->lock, flags); 729 spin_lock_irqsave(&data->lock, flags);
684 if (data->pending.status) 730 for (i = 0; i < data->hid_sensor_client_cnt; ++i) {
685 complete(&data->pending.ready); 731 struct hid_sensor_hub_device *hsdev =
732 data->hid_sensor_hub_client_devs[i].platform_data;
733 if (hsdev->pending.status)
734 complete(&hsdev->pending.ready);
735 }
686 spin_unlock_irqrestore(&data->lock, flags); 736 spin_unlock_irqrestore(&data->lock, flags);
687 mfd_remove_devices(&hdev->dev); 737 mfd_remove_devices(&hdev->dev);
688 hid_set_drvdata(hdev, NULL); 738 hid_set_drvdata(hdev, NULL);
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index df6a593bd4bd..2b4fad6998c1 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -123,7 +123,8 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
123 *val = sensor_hub_input_attr_get_raw_value( 123 *val = sensor_hub_input_attr_get_raw_value(
124 accel_state->common_attributes.hsdev, 124 accel_state->common_attributes.hsdev,
125 HID_USAGE_SENSOR_ACCEL_3D, address, 125 HID_USAGE_SENSOR_ACCEL_3D, address,
126 report_id); 126 report_id,
127 SENSOR_HUB_SYNC);
127 else { 128 else {
128 *val = 0; 129 *val = 0;
129 hid_sensor_power_state(&accel_state->common_attributes, 130 hid_sensor_power_state(&accel_state->common_attributes,
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
index 25b01e156d82..e81f434760f4 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
@@ -153,8 +153,8 @@ s32 hid_sensor_read_poll_value(struct hid_sensor_common *st)
153 int ret; 153 int ret;
154 154
155 ret = sensor_hub_get_feature(st->hsdev, 155 ret = sensor_hub_get_feature(st->hsdev,
156 st->poll.report_id, 156 st->poll.report_id,
157 st->poll.index, &value); 157 st->poll.index, sizeof(value), &value);
158 158
159 if (ret < 0 || value < 0) { 159 if (ret < 0 || value < 0) {
160 return -EINVAL; 160 return -EINVAL;
@@ -174,8 +174,8 @@ int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st,
174 int ret; 174 int ret;
175 175
176 ret = sensor_hub_get_feature(st->hsdev, 176 ret = sensor_hub_get_feature(st->hsdev,
177 st->poll.report_id, 177 st->poll.report_id,
178 st->poll.index, &value); 178 st->poll.index, sizeof(value), &value);
179 if (ret < 0 || value < 0) { 179 if (ret < 0 || value < 0) {
180 *val1 = *val2 = 0; 180 *val1 = *val2 = 0;
181 return -EINVAL; 181 return -EINVAL;
@@ -212,9 +212,8 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st,
212 else 212 else
213 value = 0; 213 value = 0;
214 } 214 }
215 ret = sensor_hub_set_feature(st->hsdev, 215 ret = sensor_hub_set_feature(st->hsdev, st->poll.report_id,
216 st->poll.report_id, 216 st->poll.index, sizeof(value), &value);
217 st->poll.index, value);
218 if (ret < 0 || value < 0) 217 if (ret < 0 || value < 0)
219 ret = -EINVAL; 218 ret = -EINVAL;
220 219
@@ -229,8 +228,9 @@ int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st,
229 int ret; 228 int ret;
230 229
231 ret = sensor_hub_get_feature(st->hsdev, 230 ret = sensor_hub_get_feature(st->hsdev,
232 st->sensitivity.report_id, 231 st->sensitivity.report_id,
233 st->sensitivity.index, &value); 232 st->sensitivity.index, sizeof(value),
233 &value);
234 if (ret < 0 || value < 0) { 234 if (ret < 0 || value < 0) {
235 *val1 = *val2 = 0; 235 *val1 = *val2 = 0;
236 return -EINVAL; 236 return -EINVAL;
@@ -253,9 +253,9 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st,
253 value = convert_to_vtf_format(st->sensitivity.size, 253 value = convert_to_vtf_format(st->sensitivity.size,
254 st->sensitivity.unit_expo, 254 st->sensitivity.unit_expo,
255 val1, val2); 255 val1, val2);
256 ret = sensor_hub_set_feature(st->hsdev, 256 ret = sensor_hub_set_feature(st->hsdev, st->sensitivity.report_id,
257 st->sensitivity.report_id, 257 st->sensitivity.index, sizeof(value),
258 st->sensitivity.index, value); 258 &value);
259 if (ret < 0 || value < 0) 259 if (ret < 0 || value < 0)
260 ret = -EINVAL; 260 ret = -EINVAL;
261 261
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 2f1d535b94c4..610fc98f88ef 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -68,20 +68,21 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state)
68 if (state_val >= 0) { 68 if (state_val >= 0) {
69 state_val += st->power_state.logical_minimum; 69 state_val += st->power_state.logical_minimum;
70 sensor_hub_set_feature(st->hsdev, st->power_state.report_id, 70 sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
71 st->power_state.index, 71 st->power_state.index, sizeof(state_val),
72 (s32)state_val); 72 &state_val);
73 } 73 }
74 74
75 if (report_val >= 0) { 75 if (report_val >= 0) {
76 report_val += st->report_state.logical_minimum; 76 report_val += st->report_state.logical_minimum;
77 sensor_hub_set_feature(st->hsdev, st->report_state.report_id, 77 sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
78 st->report_state.index, 78 st->report_state.index,
79 (s32)report_val); 79 sizeof(report_val),
80 &report_val);
80 } 81 }
81 82
82 sensor_hub_get_feature(st->hsdev, st->power_state.report_id, 83 sensor_hub_get_feature(st->hsdev, st->power_state.report_id,
83 st->power_state.index, 84 st->power_state.index,
84 &state_val); 85 sizeof(state_val), &state_val);
85 if (state && poll_value) 86 if (state && poll_value)
86 msleep_interruptible(poll_value * 2); 87 msleep_interruptible(poll_value * 2);
87 88
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index a3c3e19de527..b5883b6f4e50 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -123,7 +123,8 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
123 *val = sensor_hub_input_attr_get_raw_value( 123 *val = sensor_hub_input_attr_get_raw_value(
124 gyro_state->common_attributes.hsdev, 124 gyro_state->common_attributes.hsdev,
125 HID_USAGE_SENSOR_GYRO_3D, address, 125 HID_USAGE_SENSOR_GYRO_3D, address,
126 report_id); 126 report_id,
127 SENSOR_HUB_SYNC);
127 else { 128 else {
128 *val = 0; 129 *val = 0;
129 hid_sensor_power_state(&gyro_state->common_attributes, 130 hid_sensor_power_state(&gyro_state->common_attributes,
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 948acfc38b8c..1609ecdd01b0 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -101,7 +101,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
101 *val = sensor_hub_input_attr_get_raw_value( 101 *val = sensor_hub_input_attr_get_raw_value(
102 als_state->common_attributes.hsdev, 102 als_state->common_attributes.hsdev,
103 HID_USAGE_SENSOR_ALS, address, 103 HID_USAGE_SENSOR_ALS, address,
104 report_id); 104 report_id,
105 SENSOR_HUB_SYNC);
105 hid_sensor_power_state(&als_state->common_attributes, 106 hid_sensor_power_state(&als_state->common_attributes,
106 false); 107 false);
107 } else { 108 } else {
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index 3ecf79ed08ac..91ecc46ffeaa 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -96,7 +96,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
96 *val = sensor_hub_input_attr_get_raw_value( 96 *val = sensor_hub_input_attr_get_raw_value(
97 prox_state->common_attributes.hsdev, 97 prox_state->common_attributes.hsdev,
98 HID_USAGE_SENSOR_PROX, address, 98 HID_USAGE_SENSOR_PROX, address,
99 report_id); 99 report_id,
100 SENSOR_HUB_SYNC);
100 hid_sensor_power_state(&prox_state->common_attributes, 101 hid_sensor_power_state(&prox_state->common_attributes,
101 false); 102 false);
102 } else { 103 } else {
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index d22993b4066a..4f9c0be24451 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -170,7 +170,8 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
170 *val = sensor_hub_input_attr_get_raw_value( 170 *val = sensor_hub_input_attr_get_raw_value(
171 magn_state->common_attributes.hsdev, 171 magn_state->common_attributes.hsdev,
172 HID_USAGE_SENSOR_COMPASS_3D, address, 172 HID_USAGE_SENSOR_COMPASS_3D, address,
173 report_id); 173 report_id,
174 SENSOR_HUB_SYNC);
174 else { 175 else {
175 *val = 0; 176 *val = 0;
176 hid_sensor_power_state(&magn_state->common_attributes, 177 hid_sensor_power_state(&magn_state->common_attributes,
diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index 73854460bb2c..5930fa32a2ab 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -124,7 +124,8 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
124 *val = sensor_hub_input_attr_get_raw_value( 124 *val = sensor_hub_input_attr_get_raw_value(
125 incl_state->common_attributes.hsdev, 125 incl_state->common_attributes.hsdev,
126 HID_USAGE_SENSOR_INCLINOMETER_3D, address, 126 HID_USAGE_SENSOR_INCLINOMETER_3D, address,
127 report_id); 127 report_id,
128 SENSOR_HUB_SYNC);
128 else { 129 else {
129 hid_sensor_power_state(&incl_state->common_attributes, 130 hid_sensor_power_state(&incl_state->common_attributes,
130 false); 131 false);
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index 1af314926ebd..7bb8d4c1f7df 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -100,7 +100,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
100 *val = sensor_hub_input_attr_get_raw_value( 100 *val = sensor_hub_input_attr_get_raw_value(
101 press_state->common_attributes.hsdev, 101 press_state->common_attributes.hsdev,
102 HID_USAGE_SENSOR_PRESSURE, address, 102 HID_USAGE_SENSOR_PRESSURE, address,
103 report_id); 103 report_id,
104 SENSOR_HUB_SYNC);
104 hid_sensor_power_state(&press_state->common_attributes, 105 hid_sensor_power_state(&press_state->common_attributes,
105 false); 106 false);
106 } else { 107 } else {
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
index ae7c2ba440cf..af4f85a66b39 100644
--- a/drivers/rtc/rtc-hid-sensor-time.c
+++ b/drivers/rtc/rtc-hid-sensor-time.c
@@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
213 /* get a report with all values through requesting one value */ 213 /* get a report with all values through requesting one value */
214 sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev, 214 sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
215 HID_USAGE_SENSOR_TIME, hid_time_addresses[0], 215 HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
216 time_state->info[0].report_id); 216 time_state->info[0].report_id, SENSOR_HUB_SYNC);
217 /* wait for all values (event) */ 217 /* wait for all values (event) */
218 ret = wait_for_completion_killable_timeout( 218 ret = wait_for_completion_killable_timeout(
219 &time_state->comp_last_time, HZ*6); 219 &time_state->comp_last_time, HZ*6);
diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h
index 4173a8fdad9e..0408421d885f 100644
--- a/include/linux/hid-sensor-hub.h
+++ b/include/linux/hid-sensor-hub.h
@@ -49,19 +49,43 @@ struct hid_sensor_hub_attribute_info {
49}; 49};
50 50
51/** 51/**
52 * struct sensor_hub_pending - Synchronous read pending information
53 * @status: Pending status true/false.
54 * @ready: Completion synchronization data.
55 * @usage_id: Usage id for physical device, E.g. Gyro usage id.
56 * @attr_usage_id: Usage Id of a field, E.g. X-AXIS for a gyro.
57 * @raw_size: Response size for a read request.
58 * @raw_data: Place holder for received response.
59 */
60struct sensor_hub_pending {
61 bool status;
62 struct completion ready;
63 u32 usage_id;
64 u32 attr_usage_id;
65 int raw_size;
66 u8 *raw_data;
67};
68
69/**
52 * struct hid_sensor_hub_device - Stores the hub instance data 70 * struct hid_sensor_hub_device - Stores the hub instance data
53 * @hdev: Stores the hid instance. 71 * @hdev: Stores the hid instance.
54 * @vendor_id: Vendor id of hub device. 72 * @vendor_id: Vendor id of hub device.
55 * @product_id: Product id of hub device. 73 * @product_id: Product id of hub device.
74 * @usage: Usage id for this hub device instance.
56 * @start_collection_index: Starting index for a phy type collection 75 * @start_collection_index: Starting index for a phy type collection
57 * @end_collection_index: Last index for a phy type collection 76 * @end_collection_index: Last index for a phy type collection
77 * @mutex: synchronizing mutex.
78 * @pending: Holds information of pending sync read request.
58 */ 79 */
59struct hid_sensor_hub_device { 80struct hid_sensor_hub_device {
60 struct hid_device *hdev; 81 struct hid_device *hdev;
61 u32 vendor_id; 82 u32 vendor_id;
62 u32 product_id; 83 u32 product_id;
84 u32 usage;
63 int start_collection_index; 85 int start_collection_index;
64 int end_collection_index; 86 int end_collection_index;
87 struct mutex mutex;
88 struct sensor_hub_pending pending;
65}; 89};
66 90
67/** 91/**
@@ -152,40 +176,51 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
152* @usage_id: Attribute usage id of parent physical device as per spec 176* @usage_id: Attribute usage id of parent physical device as per spec
153* @attr_usage_id: Attribute usage id as per spec 177* @attr_usage_id: Attribute usage id as per spec
154* @report_id: Report id to look for 178* @report_id: Report id to look for
179* @flag: Synchronous or asynchronous read
155* 180*
156* Issues a synchronous read request for an input attribute. Returns 181* Issues a synchronous or asynchronous read request for an input attribute.
157* data upto 32 bits. Since client can get events, so this call should 182* Returns data upto 32 bits.
158* not be used for data paths, this will impact performance.
159*/ 183*/
160 184
185enum sensor_hub_read_flags {
186 SENSOR_HUB_SYNC,
187 SENSOR_HUB_ASYNC,
188};
189
161int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, 190int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
162 u32 usage_id, 191 u32 usage_id,
163 u32 attr_usage_id, u32 report_id); 192 u32 attr_usage_id, u32 report_id,
193 enum sensor_hub_read_flags flag
194);
195
164/** 196/**
165* sensor_hub_set_feature() - Feature set request 197* sensor_hub_set_feature() - Feature set request
166* @hsdev: Hub device instance. 198* @hsdev: Hub device instance.
167* @report_id: Report id to look for 199* @report_id: Report id to look for
168* @field_index: Field index inside a report 200* @field_index: Field index inside a report
169* @value: Value to set 201* @buffer_size: size of the buffer
202* @buffer: buffer to use in the feature set
170* 203*
171* Used to set a field in feature report. For example this can set polling 204* Used to set a field in feature report. For example this can set polling
172* interval, sensitivity, activate/deactivate state. 205* interval, sensitivity, activate/deactivate state.
173*/ 206*/
174int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, 207int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
175 u32 field_index, s32 value); 208 u32 field_index, int buffer_size, void *buffer);
176 209
177/** 210/**
178* sensor_hub_get_feature() - Feature get request 211* sensor_hub_get_feature() - Feature get request
179* @hsdev: Hub device instance. 212* @hsdev: Hub device instance.
180* @report_id: Report id to look for 213* @report_id: Report id to look for
181* @field_index: Field index inside a report 214* @field_index: Field index inside a report
182* @value: Place holder for return value 215* @buffer_size: size of the buffer
216* @buffer: buffer to copy output
183* 217*
184* Used to get a field in feature report. For example this can get polling 218* Used to get a field in feature report. For example this can get polling
185* interval, sensitivity, activate/deactivate state. 219* interval, sensitivity, activate/deactivate state. On success it returns
220* number of bytes copied to buffer. On failure, it returns value < 0.
186*/ 221*/
187int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, 222int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
188 u32 field_index, s32 *value); 223 u32 field_index, int buffer_size, void *buffer);
189 224
190/* hid-sensor-attributes */ 225/* hid-sensor-attributes */
191 226
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