iio: Add relative sensitivity support
authorYe Xiang <xiang.ye@intel.com>
Sun, 7 Feb 2021 07:00:46 +0000 (15:00 +0800)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Thu, 11 Mar 2021 20:47:09 +0000 (20:47 +0000)
Some hid sensors may use relative sensitivity such as als sensor.
This patch adds relative sensitivity checking for all hid sensors.

Signed-off-by: Ye Xiang <xiang.ye@intel.com>
Acked-by: Jiri Kosina <jkosina@suse.cz>
Link: https://lore.kernel.org/r/20210207070048.23935-2-xiang.ye@intel.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/common/hid-sensors/hid-sensor-attributes.c
drivers/iio/industrialio-core.c
include/linux/hid-sensor-hub.h
include/linux/hid-sensor-ids.h
include/linux/iio/types.h

index d349ace..cb52b4f 100644 (file)
@@ -263,6 +263,29 @@ int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st,
 }
 EXPORT_SYMBOL(hid_sensor_read_raw_hyst_value);
 
+int hid_sensor_read_raw_hyst_rel_value(struct hid_sensor_common *st, int *val1,
+                                      int *val2)
+{
+       s32 value;
+       int ret;
+
+       ret = sensor_hub_get_feature(st->hsdev,
+                                    st->sensitivity_rel.report_id,
+                                    st->sensitivity_rel.index, sizeof(value),
+                                    &value);
+       if (ret < 0 || value < 0) {
+               *val1 = *val2 = 0;
+               return -EINVAL;
+       }
+
+       convert_from_vtf_format(value, st->sensitivity_rel.size,
+                               st->sensitivity_rel.unit_expo, val1, val2);
+
+       return IIO_VAL_INT_PLUS_MICRO;
+}
+EXPORT_SYMBOL(hid_sensor_read_raw_hyst_rel_value);
+
+
 int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st,
                                        int val1, int val2)
 {
@@ -294,6 +317,37 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st,
 }
 EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value);
 
+int hid_sensor_write_raw_hyst_rel_value(struct hid_sensor_common *st,
+                                       int val1, int val2)
+{
+       s32 value;
+       int ret;
+
+       if (val1 < 0 || val2 < 0)
+               return -EINVAL;
+
+       value = convert_to_vtf_format(st->sensitivity_rel.size,
+                               st->sensitivity_rel.unit_expo,
+                               val1, val2);
+       ret = sensor_hub_set_feature(st->hsdev, st->sensitivity_rel.report_id,
+                                    st->sensitivity_rel.index, sizeof(value),
+                                    &value);
+       if (ret < 0 || value < 0)
+               return -EINVAL;
+
+       ret = sensor_hub_get_feature(st->hsdev,
+                                    st->sensitivity_rel.report_id,
+                                    st->sensitivity_rel.index, sizeof(value),
+                                    &value);
+       if (ret < 0 || value < 0)
+               return -EINVAL;
+
+       st->raw_hystersis = value;
+
+       return 0;
+}
+EXPORT_SYMBOL(hid_sensor_write_raw_hyst_rel_value);
+
 /*
  * This fuction applies the unit exponent to the scale.
  * For example:
@@ -478,16 +532,28 @@ int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
                        HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS,
                         &st->sensitivity);
 
+       sensor_hub_input_get_attribute_info(hsdev,
+                       HID_FEATURE_REPORT, usage_id,
+                       HID_USAGE_SENSOR_PROP_SENSITIVITY_REL_PCT,
+                       &st->sensitivity_rel);
        /*
         * Set Sensitivity field ids, when there is no individual modifier, will
-        * check absolute sensitivity of data field
+        * check absolute sensitivity and relative sensitivity of data field
         */
-       for (i = 0; i < sensitivity_addresses_len && st->sensitivity.index < 0; i++) {
-               sensor_hub_input_get_attribute_info(hsdev,
-                               HID_FEATURE_REPORT, usage_id,
+       for (i = 0; i < sensitivity_addresses_len; i++) {
+               if (st->sensitivity.index < 0)
+                       sensor_hub_input_get_attribute_info(
+                               hsdev, HID_FEATURE_REPORT, usage_id,
                                HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS |
                                        sensitivity_addresses[i],
                                &st->sensitivity);
+
+               if (st->sensitivity_rel.index < 0)
+                       sensor_hub_input_get_attribute_info(
+                               hsdev, HID_FEATURE_REPORT, usage_id,
+                               HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_REL_PCT |
+                                       sensitivity_addresses[i],
+                               &st->sensitivity_rel);
        }
 
        st->raw_hystersis = -1;
index 2e2970f..cb2735d 100644 (file)
@@ -157,6 +157,7 @@ static const char * const iio_chan_info_postfix[] = {
        [IIO_CHAN_INFO_PHASE] = "phase",
        [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain",
        [IIO_CHAN_INFO_HYSTERESIS] = "hysteresis",
+       [IIO_CHAN_INFO_HYSTERESIS_RELATIVE] = "hysteresis_relative",
        [IIO_CHAN_INFO_INT_TIME] = "integration_time",
        [IIO_CHAN_INFO_ENABLE] = "en",
        [IIO_CHAN_INFO_CALIBHEIGHT] = "calibheight",
index 637ec53..c27329e 100644 (file)
@@ -231,6 +231,7 @@ struct hid_sensor_common {
        struct hid_sensor_hub_attribute_info report_state;
        struct hid_sensor_hub_attribute_info power_state;
        struct hid_sensor_hub_attribute_info sensitivity;
+       struct hid_sensor_hub_attribute_info sensitivity_rel;
        struct hid_sensor_hub_attribute_info report_latency;
        struct work_struct work;
 };
@@ -253,8 +254,12 @@ int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
                                        u32 sensitivity_addresses_len);
 int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st,
                                        int val1, int val2);
+int hid_sensor_write_raw_hyst_rel_value(struct hid_sensor_common *st, int val1,
+                                       int val2);
 int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st,
                                        int *val1, int *val2);
+int hid_sensor_read_raw_hyst_rel_value(struct hid_sensor_common *st,
+                                      int *val1, int *val2);
 int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st,
                                        int val1, int val2);
 int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st,
index 3bbdbcc..ac63115 100644 (file)
 /* Per data field properties */
 #define HID_USAGE_SENSOR_DATA_MOD_NONE                                 0x00
 #define HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS               0x1000
+#define HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_REL_PCT            0xE000
 
 /* Power state enumerations */
 #define HID_USAGE_SENSOR_PROP_POWER_STATE_UNDEFINED_ENUM       0x200850
index 1e3ed6f..5aa7f66 100644 (file)
@@ -50,6 +50,7 @@ enum iio_chan_info_enum {
        IIO_CHAN_INFO_PHASE,
        IIO_CHAN_INFO_HARDWAREGAIN,
        IIO_CHAN_INFO_HYSTERESIS,
+       IIO_CHAN_INFO_HYSTERESIS_RELATIVE,
        IIO_CHAN_INFO_INT_TIME,
        IIO_CHAN_INFO_ENABLE,
        IIO_CHAN_INFO_CALIBHEIGHT,