---
drivers/hid/hid-sony.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 69 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index b7a7f0d..ce0526d 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -39,9 +39,11 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/interrupt.h>
+#include <linux/irq_work.h>
#include "hid-ids.h"
@@ -855,9 +857,14 @@ enum sony_iio_axis {
AXIS_ACC_Z,
};
+static void sony_iio_trigger_work(struct irq_work *work);
+
struct sony_iio {
struct sony_sc *sc;
+ struct iio_trigger *trig;
+
u8 buff[16]; /* 3x 16-bit + padding + timestamp */
+ struct irq_work work;
#endif
};
@@ -1076,6 +1083,13 @@ static int sony_raw_event(struct hid_device *hdev,
struct hid_report *report,
sc->last_data[AXIS_ACC_X] = (rd[42] << 8) + rd[41];
sc->last_data[AXIS_ACC_Y] = (rd[44] << 8) + rd[43];
sc->last_data[AXIS_ACC_Z] = (rd[46] << 8) + rd[45];
+
+ if (sc->indio_dev) {
+ struct sony_iio *data;
+
+ data = iio_priv(sc->indio_dev);
+ sony_iio_trigger_work(&data->work);
+ }
#endif
sixaxis_parse_report(sc, rd, size);
} else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
@@ -1869,6 +1883,28 @@ static const struct iio_info sony_iio_info = {
.driver_module = THIS_MODULE,
};
+static void sony_iio_trigger_work(struct irq_work *work)
+{
+ struct sony_iio *data = container_of(work, struct sony_iio, work);
+
+ iio_trigger_poll(data->trig);
+}
+
+static ssize_t sony_iio_trigger_poll(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct iio_trigger *trig = to_iio_trigger(dev);
+ struct sony_iio *data = iio_trigger_get_drvdata(trig);
+
+ irq_work_queue(&data->work);
+
+ return count;
+}
+
+static const struct iio_trigger_ops sony_iio_trigger_ops = {
+ .owner = THIS_MODULE,
+};
+
static irqreturn_t sony_iio_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
@@ -1910,11 +1946,29 @@ static int sony_iio_probe(struct sony_sc *sc)
indio_dev->channels = sony_sixaxis_channels;
indio_dev->num_channels = ARRAY_SIZE(sony_sixaxis_channels);
+ data->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
+ indio_dev->id);
+ if (!data->trig) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ data->trig->dev.parent = &hdev->dev;
+ data->trig->ops = &sony_iio_trigger_ops;
+ iio_trigger_set_drvdata(data->trig, indio_dev);
+ indio_dev->trig = iio_trigger_get(data->trig);
+
+ init_irq_work(&data->work, sony_iio_trigger_work);
+
+ ret = iio_trigger_register(data->trig);
+ if (ret)
+ goto err_trigger_free;
+
ret = iio_triggered_buffer_setup(indio_dev, NULL,
sony_iio_trigger_handler, NULL);
if (ret < 0) {
dev_err(&hdev->dev, "unable to setup iio triggered buffer\n");
- goto err;
+ goto err_trigger_unregister;
}
ret = iio_device_register(indio_dev);
@@ -1926,6 +1980,11 @@ static int sony_iio_probe(struct sony_sc *sc)
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
+err_trigger_unregister:
+ if (data->trig)
+ iio_trigger_unregister(data->trig);
+err_trigger_free:
+ iio_trigger_free(data->trig);
err:
kfree(indio_dev);
sc->indio_dev = NULL;
@@ -1934,11 +1993,19 @@ err:
static void sony_iio_remove(struct sony_sc *sc)
{
+ struct sony_iio *data;
+
if (!sc->indio_dev)
return;
- iio_device_unregister(sc->indio_dev);
+ data = iio_priv(sc->indio_dev);
+
iio_triggered_buffer_cleanup(sc->indio_dev);
+ if (data->trig)
+ iio_trigger_unregister(data->trig);
+ iio_trigger_free(data->trig);
+ iio_device_unregister(sc->indio_dev);
+
kfree(sc->indio_dev);
sc->indio_dev = NULL;
}
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html