summaryrefslogtreecommitdiff
path: root/drivers/iio/common/hid-sensors
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/common/hid-sensors')
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-attributes.c44
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.c80
2 files changed, 124 insertions, 0 deletions
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
index 0e05f6d1e761..f5d4d786e193 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
@@ -410,6 +410,48 @@ int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev,
}
+static void hid_sensor_get_report_latency_info(struct hid_sensor_hub_device *hsdev,
+ u32 usage_id,
+ struct hid_sensor_common *st)
+{
+ sensor_hub_input_get_attribute_info(hsdev, HID_FEATURE_REPORT,
+ usage_id,
+ HID_USAGE_SENSOR_PROP_REPORT_LATENCY,
+ &st->report_latency);
+
+ hid_dbg(hsdev->hdev, "Report latency attributes: %x:%x\n",
+ st->report_latency.index, st->report_latency.report_id);
+}
+
+int hid_sensor_get_report_latency(struct hid_sensor_common *st)
+{
+ int ret;
+ int value;
+
+ ret = sensor_hub_get_feature(st->hsdev, st->report_latency.report_id,
+ st->report_latency.index, sizeof(value),
+ &value);
+ if (ret < 0)
+ return ret;
+
+ return value;
+}
+EXPORT_SYMBOL(hid_sensor_get_report_latency);
+
+int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms)
+{
+ return sensor_hub_set_feature(st->hsdev, st->report_latency.report_id,
+ st->report_latency.index,
+ sizeof(latency_ms), &latency_ms);
+}
+EXPORT_SYMBOL(hid_sensor_set_report_latency);
+
+bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st)
+{
+ return st->report_latency.index > 0 && st->report_latency.report_id > 0;
+}
+EXPORT_SYMBOL(hid_sensor_batch_mode_supported);
+
int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
u32 usage_id,
struct hid_sensor_common *st)
@@ -451,6 +493,8 @@ int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
} else
st->timestamp_ns_scale = 1000000000;
+ hid_sensor_get_report_latency_info(hsdev, usage_id, st);
+
hid_dbg(hsdev->hdev, "common attributes: %x:%x, %x:%x, %x:%x %x:%x %x:%x\n",
st->poll.index, st->poll.report_id,
st->report_state.index, st->report_state.report_id,
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 0b5dea050239..16ade0a0327b 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -26,9 +26,84 @@
#include <linux/hid-sensor-hub.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
+#include <linux/iio/buffer.h>
#include <linux/iio/sysfs.h>
#include "hid-sensor-trigger.h"
+static ssize_t _hid_sensor_set_report_latency(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
+ int integer, fract, ret;
+ int latency;
+
+ ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract);
+ if (ret)
+ return ret;
+
+ latency = integer * 1000 + fract / 1000;
+ ret = hid_sensor_set_report_latency(attrb, latency);
+ if (ret < 0)
+ return len;
+
+ attrb->latency_ms = hid_sensor_get_report_latency(attrb);
+
+ return len;
+}
+
+static ssize_t _hid_sensor_get_report_latency(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
+ int latency;
+
+ latency = hid_sensor_get_report_latency(attrb);
+ if (latency < 0)
+ return latency;
+
+ return sprintf(buf, "%d.%06u\n", latency / 1000, (latency % 1000) * 1000);
+}
+
+static ssize_t _hid_sensor_get_fifo_state(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
+ int latency;
+
+ latency = hid_sensor_get_report_latency(attrb);
+ if (latency < 0)
+ return latency;
+
+ return sprintf(buf, "%d\n", !!latency);
+}
+
+static IIO_DEVICE_ATTR(hwfifo_timeout, 0644,
+ _hid_sensor_get_report_latency,
+ _hid_sensor_set_report_latency, 0);
+static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
+ _hid_sensor_get_fifo_state, NULL, 0);
+
+static const struct attribute *hid_sensor_fifo_attributes[] = {
+ &iio_dev_attr_hwfifo_timeout.dev_attr.attr,
+ &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
+ NULL,
+};
+
+static void hid_sensor_setup_batch_mode(struct iio_dev *indio_dev,
+ struct hid_sensor_common *st)
+{
+ if (!hid_sensor_batch_mode_supported(st))
+ return;
+
+ iio_buffer_set_attrs(indio_dev->buffer, hid_sensor_fifo_attributes);
+}
+
static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state)
{
int state_val;
@@ -141,6 +216,9 @@ static void hid_sensor_set_power_work(struct work_struct *work)
sizeof(attrb->raw_hystersis),
&attrb->raw_hystersis);
+ if (attrb->latency_ms > 0)
+ hid_sensor_set_report_latency(attrb, attrb->latency_ms);
+
_hid_sensor_power_state(attrb, true);
}
@@ -192,6 +270,8 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
attrb->trigger = trig;
indio_dev->trig = iio_trigger_get(trig);
+ hid_sensor_setup_batch_mode(indio_dev, attrb);
+
ret = pm_runtime_set_active(&indio_dev->dev);
if (ret)
goto error_unreg_trigger;