drivers/iio/common/cros_ec_sensors/cros_ec_activity.c

Source file repositories/reference/linux-study-clean/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/common/cros_ec_sensors/cros_ec_activity.c
Extension
.c
Size
8777 bytes
Lines
308
Domain
Driver Families
Bucket
drivers/iio
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct cros_ec_sensors_state {
	/* Shared by all sensors */
	struct cros_ec_sensors_core_state core;

	struct iio_chan_spec *channels;

	int body_detection_channel_index;
	int sig_motion_channel_index;
};

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 const struct iio_event_spec cros_ec_body_detect_events[] = {
	{
		.type = IIO_EV_TYPE_CHANGE,
		.dir = IIO_EV_DIR_EITHER,
		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
	},
};

static int cros_ec_activity_sensors_read_raw(struct iio_dev *indio_dev,
					     struct iio_chan_spec const *chan,
					     int *val, int *val2, long mask)
{
	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
	int ret;

	if (chan->type != IIO_PROXIMITY || mask != IIO_CHAN_INFO_RAW)
		return -EINVAL;

	guard(mutex)(&st->core.cmd_lock);
	st->core.param.cmd = MOTIONSENSE_CMD_GET_ACTIVITY;
	st->core.param.get_activity.activity =
		MOTIONSENSE_ACTIVITY_BODY_DETECTION;
	ret = cros_ec_motion_send_host_cmd(&st->core, 0);
	if (ret)
		return ret;

	/*
	 * EC actually report if a body is near (1) or far (0).
	 * Units for proximity sensor after scale is in meter,
	 * so invert the result to return 0m when near and 1m when far.
	 */
	*val = !st->core.resp->get_activity.state;
	return IIO_VAL_INT;
}

static int cros_ec_activity_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 && chan->type != IIO_PROXIMITY)
		return -EINVAL;

	guard(mutex)(&st->core.cmd_lock);
	st->core.param.cmd = MOTIONSENSE_CMD_LIST_ACTIVITIES;
	ret = cros_ec_motion_send_host_cmd(&st->core, 0);
	if (ret)
		return ret;

	switch (chan->type) {
	case IIO_PROXIMITY:
		return !!(st->core.resp->list_activities.enabled &
			 (1 << MOTIONSENSE_ACTIVITY_BODY_DETECTION));
	case IIO_ACTIVITY:
		if (chan->channel2 == IIO_MOD_STILL) {
			return !!(st->core.resp->list_activities.enabled &
				 (1 << MOTIONSENSE_ACTIVITY_SIG_MOTION));
		}

		dev_warn(&indio_dev->dev, "Unknown activity: %d\n",
			 chan->channel2);
		return -EINVAL;
	default:
		dev_warn(&indio_dev->dev, "Unknown channel type: %d\n",
			 chan->type);
		return -EINVAL;
	}
}

Annotation

Implementation Notes