aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/common/hid-sensors
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-03 11:34:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-03 11:34:00 -0400
commit5142c33ed86acbcef5c63a63d2b7384b9210d39f (patch)
tree6a0a36207ab436e1ef03bfefa7dac8f3a0cdfae5 /drivers/iio/common/hid-sensors
parent5da77761e6fd51f633b4f31051c4f839e01c29c0 (diff)
parent7eb843aa5050a395bc922db1b41b7237f238d2ba (diff)
Merge tag 'staging-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging into next
Pull staging driver updates from Greg KH: "Here is the big staging driver pull request for 3.16-rc1. Lots of stuff here, tons of cleanup patches, a few new drivers, and some removed as well, but I think we are still adding a few thousand more lines than we remove, due to the new drivers being bigger than the ones deleted. One notible bit of work did stand out, Jes Sorensen has gone on a tear, fixing up a wireless driver to be "more sane" than it originally was from the vendor, with over 500 patches merged here. Good stuff, and a number of users laptops are better off for it. All of this has been in linux-next for a while" * tag 'staging-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1703 commits) staging: skein: fix sparse warning for static declarations staging/mt29f_spinand: coding style fixes staging: silicom: fix sparse warning for static variable staging: lustre: Fix coding style staging: android: binder.c: Use more appropriate functions for euid retrieval staging: lustre: fix integer as NULL pointer warnings Revert "staging: dgap: remove unneeded kfree() in dgap_tty_register_ports()" Staging: rtl8192u: r8192U_wx.c Fixed a misplaced brace staging: ion: shrink highmem pages on kswapd staging: ion: use compound pages on high order pages for system heap staging: ion: remove struct ion_page_pool_item staging: ion: simplify ion_page_pool_total() staging: ion: tidy up a bit staging: rtl8723au: Remove redundant casting in usb_ops_linux.c staging: rtl8723au: Remove redundant casting in rtl8723a_hal_init.c staging: rtl8723au: Remove redundant casting in rtw_xmit.c staging: rtl8723au: Remove redundant casting in rtw_wlan_util.c staging: rtl8723au: Remove redundant casting in rtw_sta_mgt.c staging: rtl8723au: Remove redundant casting in rtw_recv.c staging: rtl8723au: Remove redundant casting in rtw_mlme.c ...
Diffstat (limited to 'drivers/iio/common/hid-sensors')
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-attributes.c151
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.c17
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.h1
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
29struct {
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
29static int pow_10(unsigned power) 63static 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
150s32 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}
168EXPORT_SYMBOL(hid_sensor_read_poll_value);
169
116int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, 170int 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}
210EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); 264EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value);
211 265
212int 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 */
277static 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
320int 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}
344EXPORT_SYMBOL(hid_sensor_format_scale);
345
346int 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
361int 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
31static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, 31int 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}
80EXPORT_SYMBOL(hid_sensor_power_state);
81
82static 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
79void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) 88void 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 @@
22int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, 22int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
23 struct hid_sensor_common *attrb); 23 struct hid_sensor_common *attrb);
24void hid_sensor_remove_trigger(struct hid_sensor_common *attrb); 24void hid_sensor_remove_trigger(struct hid_sensor_common *attrb);
25int hid_sensor_power_state(struct hid_sensor_common *st, bool state);
25 26
26#endif 27#endif