iio: hid-sensors: Increase the precision of scale to fix wrong reading interpretation.
authorSong Hongyan <hongyan.song@intel.com>
Tue, 25 Oct 2016 01:30:07 +0000 (01:30 +0000)
committerJonathan Cameron <jic23@kernel.org>
Sat, 5 Nov 2016 17:50:56 +0000 (17:50 +0000)
While testing, it was observed that on some platforms the scale value
from iio sysfs for gyroscope is always 0 (E.g. Yoga 260). This results
in the final angular velocity component values to be zeros.

This is caused by insufficient precision of scale value displayed in sysfs.
If the precision is changed to nano from current micro, then this is
sufficient to display the scale value on this platform.
Since this can be a problem for all other HID sensors, increase scale
precision of all HID sensors to nano from current micro.

Results on Yoga 260:

name scale before scale now
--------------------------------------------
gyro_3d 0.000000 0.000000174
als 0.001000 0.001000000
magn_3d 0.000001 0.000001000
accel_3d 0.000009 0.000009806

Signed-off-by: Song Hongyan <hongyan.song@intel.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
drivers/iio/common/hid-sensors/hid-sensor-attributes.c

index dc33c1dd5191a57aaa8c3c66cdaa75a31866463c..b5beea53d6f6551aba68e570be25deca87d8288c 100644 (file)
@@ -30,26 +30,26 @@ static struct {
        u32 usage_id;
        int unit; /* 0 for default others from HID sensor spec */
        int scale_val0; /* scale, whole number */
-       int scale_val1; /* scale, fraction in micros */
+       int scale_val1; /* scale, fraction in nanos */
 } unit_conversion[] = {
-       {HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650},
+       {HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650000},
        {HID_USAGE_SENSOR_ACCEL_3D,
                HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0},
        {HID_USAGE_SENSOR_ACCEL_3D,
-               HID_USAGE_SENSOR_UNITS_G, 9, 806650},
+               HID_USAGE_SENSOR_UNITS_G, 9, 806650000},
 
-       {HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453},
+       {HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453293},
        {HID_USAGE_SENSOR_GYRO_3D,
                HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND, 1, 0},
        {HID_USAGE_SENSOR_GYRO_3D,
-               HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453},
+               HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453293},
 
-       {HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000},
+       {HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000000},
        {HID_USAGE_SENSOR_COMPASS_3D, HID_USAGE_SENSOR_UNITS_GAUSS, 1, 0},
 
-       {HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453},
+       {HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453293},
        {HID_USAGE_SENSOR_INCLINOMETER_3D,
-               HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453},
+               HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453293},
        {HID_USAGE_SENSOR_INCLINOMETER_3D,
                HID_USAGE_SENSOR_UNITS_RADIANS, 1, 0},
 
@@ -57,7 +57,7 @@ static struct {
        {HID_USAGE_SENSOR_ALS, HID_USAGE_SENSOR_UNITS_LUX, 1, 0},
 
        {HID_USAGE_SENSOR_PRESSURE, 0, 100, 0},
-       {HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 0, 1000},
+       {HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 0, 1000000},
 };
 
 static int pow_10(unsigned power)
@@ -266,15 +266,15 @@ EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value);
 /*
  * This fuction applies the unit exponent to the scale.
  * For example:
- * 9.806650 ->exp:2-> val0[980]val1[665000]
- * 9.000806 ->exp:2-> val0[900]val1[80600]
- * 0.174535 ->exp:2-> val0[17]val1[453500]
- * 1.001745 ->exp:0-> val0[1]val1[1745]
- * 1.001745 ->exp:2-> val0[100]val1[174500]
- * 1.001745 ->exp:4-> val0[10017]val1[450000]
- * 9.806650 ->exp:-2-> val0[0]val1[98066]
+ * 9.806650000 ->exp:2-> val0[980]val1[665000000]
+ * 9.000806000 ->exp:2-> val0[900]val1[80600000]
+ * 0.174535293 ->exp:2-> val0[17]val1[453529300]
+ * 1.001745329 ->exp:0-> val0[1]val1[1745329]
+ * 1.001745329 ->exp:2-> val0[100]val1[174532900]
+ * 1.001745329 ->exp:4-> val0[10017]val1[453290000]
+ * 9.806650000 ->exp:-2-> val0[0]val1[98066500]
  */
-static void adjust_exponent_micro(int *val0, int *val1, int scale0,
+static void adjust_exponent_nano(int *val0, int *val1, int scale0,
                                  int scale1, int exp)
 {
        int i;
@@ -285,32 +285,32 @@ static void adjust_exponent_micro(int *val0, int *val1, int scale0,
        if (exp > 0) {
                *val0 = scale0 * pow_10(exp);
                res = 0;
-               if (exp > 6) {
+               if (exp > 9) {
                        *val1 = 0;
                        return;
                }
                for (i = 0; i < exp; ++i) {
-                       x = scale1 / pow_10(5 - i);
+                       x = scale1 / pow_10(8 - i);
                        res += (pow_10(exp - 1 - i) * x);
-                       scale1 = scale1 % pow_10(5 - i);
+                       scale1 = scale1 % pow_10(8 - i);
                }
                *val0 += res;
                        *val1 = scale1 * pow_10(exp);
        } else if (exp < 0) {
                exp = abs(exp);
-               if (exp > 6) {
+               if (exp > 9) {
                        *val0 = *val1 = 0;
                        return;
                }
                *val0 = scale0 / pow_10(exp);
                rem = scale0 % pow_10(exp);
                res = 0;
-               for (i = 0; i < (6 - exp); ++i) {
-                       x = scale1 / pow_10(5 - i);
-                       res += (pow_10(5 - exp - i) * x);
-                       scale1 = scale1 % pow_10(5 - i);
+               for (i = 0; i < (9 - exp); ++i) {
+                       x = scale1 / pow_10(8 - i);
+                       res += (pow_10(8 - exp - i) * x);
+                       scale1 = scale1 % pow_10(8 - i);
                }
-               *val1 = rem * pow_10(6 - exp) + res;
+               *val1 = rem * pow_10(9 - exp) + res;
        } else {
                *val0 = scale0;
                *val1 = scale1;
@@ -332,14 +332,14 @@ int hid_sensor_format_scale(u32 usage_id,
                        unit_conversion[i].unit == attr_info->units) {
                        exp  = hid_sensor_convert_exponent(
                                                attr_info->unit_expo);
-                       adjust_exponent_micro(val0, val1,
+                       adjust_exponent_nano(val0, val1,
                                        unit_conversion[i].scale_val0,
                                        unit_conversion[i].scale_val1, exp);
                        break;
                }
        }
 
-       return IIO_VAL_INT_PLUS_MICRO;
+       return IIO_VAL_INT_PLUS_NANO;
 }
 EXPORT_SYMBOL(hid_sensor_format_scale);