All of lore.kernel.org
 help / color / mirror / Atom feed
From: Enric Balletbo i Serra <enric.balletbo@collabora.com>
To: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org
Cc: Olof Johansson <olof@lixom.net>, Lee Jones <lee.jones@linaro.org>,
	Jonathan Cameron <jic23@kernel.org>,
	Hartmut Knaack <knaack.h@gmx.de>,
	Lars-Peter Clausen <lars@metafoo.de>,
	Peter Meerwald-Stadler <pmeerw@pmeerw.net>,
	Guenter Roeck <groeck@chromium.org>,
	Gwendal Grignou <gwendal@chromium.org>
Subject: [PATCH 07/10] iio: cros_ec_activity: add ChromeOS EC Activity Sensors
Date: Mon, 18 Jul 2016 09:02:47 +0200	[thread overview]
Message-ID: <1468825370-20075-8-git-send-email-enric.balletbo@collabora.com> (raw)
In-Reply-To: <1468825370-20075-1-git-send-email-enric.balletbo@collabora.com>

Handle activity events detections presented by the ChromeOS
EC Sensor hub. Activities can be simple (low/no motion) or more complex
(riding train). They are being reported by physical devices or the EC
itself.

Signed-off-by: Guenter Roeck <groeck@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
---
 drivers/iio/common/cros_ec_sensors/Kconfig         |  10 +
 drivers/iio/common/cros_ec_sensors/Makefile        |   1 +
 .../iio/common/cros_ec_sensors/cros_ec_activity.c  | 294 +++++++++++++++++++++
 3 files changed, 305 insertions(+)
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_activity.c

diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig
index 02559d2..22b4211 100644
--- a/drivers/iio/common/cros_ec_sensors/Kconfig
+++ b/drivers/iio/common/cros_ec_sensors/Kconfig
@@ -29,3 +29,13 @@ config IIO_CROS_EC_LIGHT_PROX
 	  presented by the ChromeOS EC Sensor hub.
 	  Creates an IIO device for each functions.
 	  Only one source is exposed by the EC.
+
+config IIO_CROS_EC_ACTIVITY
+	tristate "ChromeOS EC Activity Sensors"
+	select IIO_CROS_EC_SENSORS_CORE
+	help
+	  Module to handle activity events detections presented by the ChromeOS
+	  EC Sensor hub.
+	  Activities can be simple (low/no motion) or more complex (riding train).
+	  They are being reported by physical devices or the EC itself.
+	  Creates an IIO device to manage all activities.
diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile
index 7aaf2a2..8f54f1e 100644
--- a/drivers/iio/common/cros_ec_sensors/Makefile
+++ b/drivers/iio/common/cros_ec_sensors/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o
 obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o
 obj-$(CONFIG_IIO_CROS_EC_LIGHT_PROX) += cros_ec_light_prox.o
+obj-$(CONFIG_IIO_CROS_EC_ACTIVITY) += cros_ec_activity.o
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c b/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c
new file mode 100644
index 0000000..b2e39d6
--- /dev/null
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c
@@ -0,0 +1,294 @@
+/*
+ * cros_ec_sensors_activity - Driver for activities/gesture recognition.
+ *
+ * Copyright (C) 2015 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver uses the cros-ec interface to communicate with the Chrome OS
+ * EC about accelerometer data. Accelerometer access is presented through
+ * iio sysfs.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/iio/iio.h>
+#include <linux/kernel.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+
+#include "cros_ec_sensors_core.h"
+
+/* st data for ec_sensors iio driver. */
+struct cros_ec_sensors_state {
+	/* Shared by all sensors */
+	struct cros_ec_sensors_core_state core;
+
+	struct iio_chan_spec *channels;
+	unsigned int nb_activities;
+};
+
+static const struct iio_event_spec cros_ec_activity_single_shot[] = {
+	{
+		.type = IIO_EV_TYPE_CHANGE,
+		/* significant motion trigger when we get out of still. */
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
+	 },
+};
+
+static int ec_sensors_read(struct iio_dev *indio_dev,
+			  struct iio_chan_spec const *chan,
+			  int *val, int *val2, long mask)
+{
+	dev_warn(&indio_dev->dev, "%s: Not Expected: %d\n", __func__,
+		 chan->channel2);
+	return -EPERM;
+}
+
+static int ec_sensors_write(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val, int val2, long mask)
+{
+	dev_warn(&indio_dev->dev, "%s: Not Expected: %d\n", __func__,
+		 chan->channel2);
+	return -EPERM;
+}
+
+static int cros_ec_read_event_config(struct iio_dev *indio_dev,
+				     const struct iio_chan_spec *chan,
+				     enum iio_event_type type,
+				     enum iio_event_direction dir)
+{
+	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
+	int ret;
+
+	if (chan->type != IIO_ACTIVITY)
+		return -EINVAL;
+
+	mutex_lock(&st->core.cmd_lock);
+	st->core.param.cmd = MOTIONSENSE_CMD_LIST_ACTIVITIES;
+	if (cros_ec_motion_send_host_cmd(&st->core, 0) == EC_RES_SUCCESS) {
+		switch (chan->channel2) {
+		case IIO_MOD_STILL:
+			ret = !!(st->core.resp->list_activities.enabled &
+				 (1 << MOTIONSENSE_ACTIVITY_SIG_MOTION));
+			break;
+		case IIO_MOD_DOUBLE_TAP:
+			ret = !!(st->core.resp->list_activities.enabled &
+				 (1 << MOTIONSENSE_ACTIVITY_DOUBLE_TAP));
+			break;
+		default:
+			dev_warn(&indio_dev->dev, "Unknown activity: %d\n",
+				 chan->channel2);
+			ret = -EINVAL;
+		}
+	} else {
+		ret = -EIO;
+	}
+	mutex_unlock(&st->core.cmd_lock);
+	return ret;
+}
+
+static int cros_ec_write_event_config(struct iio_dev *indio_dev,
+				      const struct iio_chan_spec *chan,
+				      enum iio_event_type type,
+				      enum iio_event_direction dir, int state)
+{
+	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
+	int ret;
+
+	if (chan->type != IIO_ACTIVITY)
+		return -EINVAL;
+
+	mutex_lock(&st->core.cmd_lock);
+	st->core.param.cmd = MOTIONSENSE_CMD_SET_ACTIVITY;
+	switch (chan->channel2) {
+	case IIO_MOD_STILL:
+		st->core.param.set_activity.activity =
+			MOTIONSENSE_ACTIVITY_SIG_MOTION;
+		break;
+	case IIO_MOD_DOUBLE_TAP:
+		st->core.param.set_activity.activity =
+			MOTIONSENSE_ACTIVITY_DOUBLE_TAP;
+		break;
+	default:
+		dev_warn(&indio_dev->dev, "Unknown activity: %d\n",
+			 chan->channel2);
+	}
+	st->core.param.set_activity.enable = state;
+
+	ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+
+	mutex_unlock(&st->core.cmd_lock);
+	return ret;
+}
+
+/* Not implemented */
+static int cros_ec_read_event_value(struct iio_dev *indio_dev,
+				    const struct iio_chan_spec *chan,
+				    enum iio_event_type type,
+				    enum iio_event_direction dir,
+				    enum iio_event_info info,
+				    int *val, int *val2)
+{
+	dev_warn(&indio_dev->dev, "%s: Not Expected: %d\n", __func__,
+		 chan->channel2);
+	return -EPERM;
+}
+
+static int cros_ec_write_event_value(struct iio_dev *indio_dev,
+				     const struct iio_chan_spec *chan,
+				     enum iio_event_type type,
+				     enum iio_event_direction dir,
+				     enum iio_event_info info,
+				     int val, int val2)
+{
+	dev_warn(&indio_dev->dev, "%s: Not Expected: %d\n", __func__,
+		 chan->channel2);
+	return -EPERM;
+}
+
+static const struct iio_info ec_sensors_info = {
+	.read_raw = &ec_sensors_read,
+	.write_raw = &ec_sensors_write,
+	.read_event_config = cros_ec_read_event_config,
+	.write_event_config = cros_ec_write_event_config,
+	.read_event_value = cros_ec_read_event_value,
+	.write_event_value = cros_ec_write_event_value,
+};
+
+static int cros_ec_sensors_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
+	struct cros_ec_device *ec_device;
+	struct iio_dev *indio_dev;
+	struct cros_ec_sensors_state *st;
+	struct iio_chan_spec *channel;
+	unsigned long activities;
+	int i, index, ret, nb_activities;
+
+	if (!ec_dev || !ec_dev->ec_dev) {
+		dev_warn(&pdev->dev, "No CROS EC device found.\n");
+		return -EINVAL;
+	}
+	ec_device = ec_dev->ec_dev;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
+	if (ret)
+		return ret;
+
+	indio_dev->info = &ec_sensors_info;
+	st = iio_priv(indio_dev);
+	st->core.type = st->core.resp->info.type;
+	st->core.loc = st->core.resp->info.location;
+
+	/*
+	 * List all available activities
+	 */
+	st->core.param.cmd = MOTIONSENSE_CMD_LIST_ACTIVITIES;
+	ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+	if (ret)
+		return ret;
+	activities = st->core.resp->list_activities.enabled |
+		     st->core.resp->list_activities.disabled;
+	nb_activities = hweight_long(activities) + 1;
+
+	if (!activities)
+		return -ENODEV;
+
+	/* Allocate a channel per activity and one for timestamp */
+	st->channels = devm_kcalloc(&pdev->dev, nb_activities,
+				    sizeof(*st->channels), GFP_KERNEL);
+	if (!st->channels)
+		return -ENOMEM;
+
+	channel = &st->channels[0];
+	index = 0;
+	for_each_set_bit(i, &activities, BITS_PER_LONG) {
+		channel->scan_index = index;
+
+		/* List all available activities */
+		channel->type = IIO_ACTIVITY;
+		channel->modified = 1;
+		channel->event_spec = cros_ec_activity_single_shot;
+		channel->num_event_specs =
+				ARRAY_SIZE(cros_ec_activity_single_shot);
+		switch (i) {
+		case MOTIONSENSE_ACTIVITY_SIG_MOTION:
+			channel->channel2 = IIO_MOD_STILL;
+			break;
+		case MOTIONSENSE_ACTIVITY_DOUBLE_TAP:
+			channel->channel2 = IIO_MOD_DOUBLE_TAP;
+			break;
+		default:
+			dev_warn(&pdev->dev, "Unknown activity: %d\n", i);
+			continue;
+		}
+		channel->ext_info = cros_ec_sensors_limited_info;
+		channel++;
+		index++;
+	}
+
+	/* Timestamp */
+	channel->scan_index = index;
+	channel->type = IIO_TIMESTAMP;
+	channel->channel = -1;
+	channel->scan_type.sign = 's';
+	channel->scan_type.realbits = 64;
+	channel->scan_type.storagebits = 64;
+
+	indio_dev->channels = st->channels;
+	indio_dev->num_channels = index + 1;
+
+	st->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
+
+	/* Driver is incomplete: by itself, no way to get event directly */
+	ret = iio_device_register(indio_dev);
+	return ret;
+}
+
+static int cros_ec_sensors_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	iio_device_unregister(indio_dev);
+	return 0;
+}
+
+static const struct platform_device_id cros_ec_sensors_ids[] = {
+	{
+		.name = "cros-ec-activity",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
+
+static struct platform_driver cros_ec_sensors_platform_driver = {
+	.driver = {
+		.name	= "cros-ec-activity",
+	},
+	.probe		= cros_ec_sensors_probe,
+	.remove		= cros_ec_sensors_remove,
+	.id_table	= cros_ec_sensors_ids,
+};
+module_platform_driver(cros_ec_sensors_platform_driver);
+
+MODULE_DESCRIPTION("ChromeOS EC activity sensors driver");
+MODULE_LICENSE("GPL v2");
-- 
2.1.0

  parent reply	other threads:[~2016-07-18  7:03 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-18  7:02 [PATCH 00/10] Add support for cros-ec-sensors Enric Balletbo i Serra
2016-07-18  7:02 ` [PATCH 01/10] mfd: cros_ec: add ChromeOS EC sensor platform information Enric Balletbo i Serra
2016-07-18 13:43   ` Jonathan Cameron
2016-07-18  7:02 ` [PATCH 02/10] mfd: cros_ec: update MOTIONSENSE definitions and commands Enric Balletbo i Serra
2016-07-18 13:49   ` Jonathan Cameron
2016-07-19 18:00     ` Enric Balletbo Serra
2016-07-21  6:18       ` Jonathan Cameron
2016-07-18  7:02 ` [PATCH 03/10] iio: core: Add double tap as possible gesture Enric Balletbo i Serra
2016-07-18 13:54   ` Jonathan Cameron
2016-07-18  7:02 ` [PATCH 04/10] iio: cros_ec: Add common functions for cros_ec sensors Enric Balletbo i Serra
2016-07-18  7:29   ` Peter Meerwald-Stadler
2016-07-18 15:51     ` Jonathan Cameron
2016-07-20  7:57       ` Enric Balletbo Serra
2016-07-20  8:18         ` Peter Meerwald-Stadler
2016-07-18  7:02 ` [PATCH 05/10] iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver Enric Balletbo i Serra
2016-07-18 16:09   ` Jonathan Cameron
2016-07-18  7:02 ` [PATCH 06/10] iio: cros_ec_light_prox: add ChromeOS EC Light and Proximity Sensors Enric Balletbo i Serra
2016-07-18 16:11   ` Jonathan Cameron
2016-07-18  7:02 ` Enric Balletbo i Serra [this message]
2016-07-18 16:16   ` [PATCH 07/10] iio: cros_ec_activity: add ChromeOS EC Activity Sensors Jonathan Cameron
2016-07-18  7:02 ` [PATCH 08/10] iio: cros_ec_sensors_ring: add ChromeOS EC Sensors Ring Enric Balletbo i Serra
2016-07-18 16:27   ` Jonathan Cameron
2016-07-26 23:29     ` Gwendal Grignou
2016-07-27  0:17   ` Guenter Roeck
2016-07-18  7:02 ` [PATCH 09/10] platform/chrome: Introduce a new function to check EC features Enric Balletbo i Serra
2016-07-18  7:02 ` [PATCH 10/10] platform/chrome: cros_ec_dev - Register cros-ec sensors Enric Balletbo i Serra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1468825370-20075-8-git-send-email-enric.balletbo@collabora.com \
    --to=enric.balletbo@collabora.com \
    --cc=groeck@chromium.org \
    --cc=gwendal@chromium.org \
    --cc=jic23@kernel.org \
    --cc=knaack.h@gmx.de \
    --cc=lars@metafoo.de \
    --cc=lee.jones@linaro.org \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=olof@lixom.net \
    --cc=pmeerw@pmeerw.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.