diff options
Diffstat (limited to 'drivers/iio/common/hid-sensors')
-rw-r--r-- | drivers/iio/common/hid-sensors/hid-sensor-attributes.c | 151 | ||||
-rw-r--r-- | drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 17 | ||||
-rw-r--r-- | drivers/iio/common/hid-sensors/hid-sensor-trigger.h | 1 |
3 files changed, 163 insertions, 6 deletions
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index 75b54730a963..403dd3d8986e 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c | |||
@@ -26,6 +26,40 @@ | |||
26 | #include <linux/iio/iio.h> | 26 | #include <linux/iio/iio.h> |
27 | #include <linux/iio/sysfs.h> | 27 | #include <linux/iio/sysfs.h> |
28 | 28 | ||
29 | struct { | ||
30 | u32 usage_id; | ||
31 | int unit; /* 0 for default others from HID sensor spec */ | ||
32 | int scale_val0; /* scale, whole number */ | ||
33 | int scale_val1; /* scale, fraction in micros */ | ||
34 | } static unit_conversion[] = { | ||
35 | {HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650}, | ||
36 | {HID_USAGE_SENSOR_ACCEL_3D, | ||
37 | HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0}, | ||
38 | {HID_USAGE_SENSOR_ACCEL_3D, | ||
39 | HID_USAGE_SENSOR_UNITS_G, 9, 806650}, | ||
40 | |||
41 | {HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453}, | ||
42 | {HID_USAGE_SENSOR_GYRO_3D, | ||
43 | HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND, 1, 0}, | ||
44 | {HID_USAGE_SENSOR_GYRO_3D, | ||
45 | HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453}, | ||
46 | |||
47 | {HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000}, | ||
48 | {HID_USAGE_SENSOR_COMPASS_3D, HID_USAGE_SENSOR_UNITS_GAUSS, 1, 0}, | ||
49 | |||
50 | {HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453}, | ||
51 | {HID_USAGE_SENSOR_INCLINOMETER_3D, | ||
52 | HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453}, | ||
53 | {HID_USAGE_SENSOR_INCLINOMETER_3D, | ||
54 | HID_USAGE_SENSOR_UNITS_RADIANS, 1, 0}, | ||
55 | |||
56 | {HID_USAGE_SENSOR_ALS, 0, 1, 0}, | ||
57 | {HID_USAGE_SENSOR_ALS, HID_USAGE_SENSOR_UNITS_LUX, 1, 0}, | ||
58 | |||
59 | {HID_USAGE_SENSOR_PRESSURE, 0, 100000, 0}, | ||
60 | {HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 1, 0}, | ||
61 | }; | ||
62 | |||
29 | static int pow_10(unsigned power) | 63 | static int pow_10(unsigned power) |
30 | { | 64 | { |
31 | int i; | 65 | int i; |
@@ -113,6 +147,26 @@ static u32 convert_to_vtf_format(int size, int exp, int val1, int val2) | |||
113 | return value; | 147 | return value; |
114 | } | 148 | } |
115 | 149 | ||
150 | s32 hid_sensor_read_poll_value(struct hid_sensor_common *st) | ||
151 | { | ||
152 | s32 value = 0; | ||
153 | int ret; | ||
154 | |||
155 | ret = sensor_hub_get_feature(st->hsdev, | ||
156 | st->poll.report_id, | ||
157 | st->poll.index, &value); | ||
158 | |||
159 | if (ret < 0 || value < 0) { | ||
160 | return -EINVAL; | ||
161 | } else { | ||
162 | if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) | ||
163 | value = value * 1000; | ||
164 | } | ||
165 | |||
166 | return value; | ||
167 | } | ||
168 | EXPORT_SYMBOL(hid_sensor_read_poll_value); | ||
169 | |||
116 | int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, | 170 | int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, |
117 | int *val1, int *val2) | 171 | int *val1, int *val2) |
118 | { | 172 | { |
@@ -209,15 +263,108 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, | |||
209 | } | 263 | } |
210 | EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); | 264 | EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); |
211 | 265 | ||
212 | int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, | 266 | /* |
267 | * This fuction applies the unit exponent to the scale. | ||
268 | * For example: | ||
269 | * 9.806650 ->exp:2-> val0[980]val1[665000] | ||
270 | * 9.000806 ->exp:2-> val0[900]val1[80600] | ||
271 | * 0.174535 ->exp:2-> val0[17]val1[453500] | ||
272 | * 1.001745 ->exp:0-> val0[1]val1[1745] | ||
273 | * 1.001745 ->exp:2-> val0[100]val1[174500] | ||
274 | * 1.001745 ->exp:4-> val0[10017]val1[450000] | ||
275 | * 9.806650 ->exp:-2-> val0[0]val1[98066] | ||
276 | */ | ||
277 | static void adjust_exponent_micro(int *val0, int *val1, int scale0, | ||
278 | int scale1, int exp) | ||
279 | { | ||
280 | int i; | ||
281 | int x; | ||
282 | int res; | ||
283 | int rem; | ||
284 | |||
285 | if (exp > 0) { | ||
286 | *val0 = scale0 * pow_10(exp); | ||
287 | res = 0; | ||
288 | if (exp > 6) { | ||
289 | *val1 = 0; | ||
290 | return; | ||
291 | } | ||
292 | for (i = 0; i < exp; ++i) { | ||
293 | x = scale1 / pow_10(5 - i); | ||
294 | res += (pow_10(exp - 1 - i) * x); | ||
295 | scale1 = scale1 % pow_10(5 - i); | ||
296 | } | ||
297 | *val0 += res; | ||
298 | *val1 = scale1 * pow_10(exp); | ||
299 | } else if (exp < 0) { | ||
300 | exp = abs(exp); | ||
301 | if (exp > 6) { | ||
302 | *val0 = *val1 = 0; | ||
303 | return; | ||
304 | } | ||
305 | *val0 = scale0 / pow_10(exp); | ||
306 | rem = scale0 % pow_10(exp); | ||
307 | res = 0; | ||
308 | for (i = 0; i < (6 - exp); ++i) { | ||
309 | x = scale1 / pow_10(5 - i); | ||
310 | res += (pow_10(5 - exp - i) * x); | ||
311 | scale1 = scale1 % pow_10(5 - i); | ||
312 | } | ||
313 | *val1 = rem * pow_10(6 - exp) + res; | ||
314 | } else { | ||
315 | *val0 = scale0; | ||
316 | *val1 = scale1; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | int hid_sensor_format_scale(u32 usage_id, | ||
321 | struct hid_sensor_hub_attribute_info *attr_info, | ||
322 | int *val0, int *val1) | ||
323 | { | ||
324 | int i; | ||
325 | int exp; | ||
326 | |||
327 | *val0 = 1; | ||
328 | *val1 = 0; | ||
329 | |||
330 | for (i = 0; i < ARRAY_SIZE(unit_conversion); ++i) { | ||
331 | if (unit_conversion[i].usage_id == usage_id && | ||
332 | unit_conversion[i].unit == attr_info->units) { | ||
333 | exp = hid_sensor_convert_exponent( | ||
334 | attr_info->unit_expo); | ||
335 | adjust_exponent_micro(val0, val1, | ||
336 | unit_conversion[i].scale_val0, | ||
337 | unit_conversion[i].scale_val1, exp); | ||
338 | break; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | return IIO_VAL_INT_PLUS_MICRO; | ||
343 | } | ||
344 | EXPORT_SYMBOL(hid_sensor_format_scale); | ||
345 | |||
346 | int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev, | ||
213 | u32 usage_id, | 347 | u32 usage_id, |
214 | struct hid_sensor_common *st) | 348 | struct hid_sensor_common *st) |
215 | { | 349 | { |
216 | |||
217 | sensor_hub_input_get_attribute_info(hsdev, | 350 | sensor_hub_input_get_attribute_info(hsdev, |
218 | HID_FEATURE_REPORT, usage_id, | 351 | HID_FEATURE_REPORT, usage_id, |
219 | HID_USAGE_SENSOR_PROP_REPORT_INTERVAL, | 352 | HID_USAGE_SENSOR_PROP_REPORT_INTERVAL, |
220 | &st->poll); | 353 | &st->poll); |
354 | /* Default unit of measure is milliseconds */ | ||
355 | if (st->poll.units == 0) | ||
356 | st->poll.units = HID_USAGE_SENSOR_UNITS_MILLISECOND; | ||
357 | return 0; | ||
358 | |||
359 | } | ||
360 | |||
361 | int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, | ||
362 | u32 usage_id, | ||
363 | struct hid_sensor_common *st) | ||
364 | { | ||
365 | |||
366 | |||
367 | hid_sensor_get_reporting_interval(hsdev, usage_id, st); | ||
221 | 368 | ||
222 | sensor_hub_input_get_attribute_info(hsdev, | 369 | sensor_hub_input_get_attribute_info(hsdev, |
223 | HID_FEATURE_REPORT, usage_id, | 370 | HID_FEATURE_REPORT, usage_id, |
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index dbefbdaf7cd1..73282cee0c81 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c | |||
@@ -28,16 +28,17 @@ | |||
28 | #include <linux/iio/sysfs.h> | 28 | #include <linux/iio/sysfs.h> |
29 | #include "hid-sensor-trigger.h" | 29 | #include "hid-sensor-trigger.h" |
30 | 30 | ||
31 | static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | 31 | int hid_sensor_power_state(struct hid_sensor_common *st, bool state) |
32 | bool state) | ||
33 | { | 32 | { |
34 | struct hid_sensor_common *st = iio_trigger_get_drvdata(trig); | ||
35 | int state_val; | 33 | int state_val; |
36 | int report_val; | 34 | int report_val; |
37 | 35 | ||
38 | if (state) { | 36 | if (state) { |
39 | if (sensor_hub_device_open(st->hsdev)) | 37 | if (sensor_hub_device_open(st->hsdev)) |
40 | return -EIO; | 38 | return -EIO; |
39 | |||
40 | atomic_inc(&st->data_ready); | ||
41 | |||
41 | state_val = hid_sensor_get_usage_index(st->hsdev, | 42 | state_val = hid_sensor_get_usage_index(st->hsdev, |
42 | st->power_state.report_id, | 43 | st->power_state.report_id, |
43 | st->power_state.index, | 44 | st->power_state.index, |
@@ -47,6 +48,8 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
47 | st->report_state.index, | 48 | st->report_state.index, |
48 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); | 49 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); |
49 | } else { | 50 | } else { |
51 | if (!atomic_dec_and_test(&st->data_ready)) | ||
52 | return 0; | ||
50 | sensor_hub_device_close(st->hsdev); | 53 | sensor_hub_device_close(st->hsdev); |
51 | state_val = hid_sensor_get_usage_index(st->hsdev, | 54 | state_val = hid_sensor_get_usage_index(st->hsdev, |
52 | st->power_state.report_id, | 55 | st->power_state.report_id, |
@@ -57,7 +60,6 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
57 | st->report_state.index, | 60 | st->report_state.index, |
58 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM); | 61 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM); |
59 | } | 62 | } |
60 | st->data_ready = state; | ||
61 | 63 | ||
62 | if (state_val >= 0) { | 64 | if (state_val >= 0) { |
63 | state_val += st->power_state.logical_minimum; | 65 | state_val += st->power_state.logical_minimum; |
@@ -75,6 +77,13 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
75 | 77 | ||
76 | return 0; | 78 | return 0; |
77 | } | 79 | } |
80 | EXPORT_SYMBOL(hid_sensor_power_state); | ||
81 | |||
82 | static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | ||
83 | bool state) | ||
84 | { | ||
85 | return hid_sensor_power_state(iio_trigger_get_drvdata(trig), state); | ||
86 | } | ||
78 | 87 | ||
79 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) | 88 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) |
80 | { | 89 | { |
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h index ca02f7811aa8..0f8e78c249d3 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h | |||
@@ -22,5 +22,6 @@ | |||
22 | int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, | 22 | int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, |
23 | struct hid_sensor_common *attrb); | 23 | struct hid_sensor_common *attrb); |
24 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb); | 24 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb); |
25 | int hid_sensor_power_state(struct hid_sensor_common *st, bool state); | ||
25 | 26 | ||
26 | #endif | 27 | #endif |