Re: [PATCH 5/9] iio: hid-sensors: Common attribute and trigger

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 09/05/2012 01:56 PM, Srinivas Pandruvada wrote:
> From: srinivas pandruvada <srinivas.pandruvada@xxxxxxxxx>
> 
> This patch contains the common code, which is used by all HID sensors.
> There are some common set of attributes, which every hid sensor
> needs it. This patch contains all such attributes processing.
> Also the trigger interface is common among all HID sensors. This
> patch contains common trigger functions utilized by all HID sensors.
> 
> Signed-off-by: srinivas pandruvada <srinivas.pandruvada@xxxxxxxxx>
Made one trivial change whilst adding this to my tree. There is a
bonus blank line at the end of drivers/iio/common/Kconfig that
git am moaned about.

> ---
>  drivers/iio/Kconfig                                |   1 +
>  drivers/iio/Makefile                               |   1 +
>  drivers/iio/common/Kconfig                         |   6 +
>  drivers/iio/common/Makefile                        |   9 +
>  drivers/iio/common/hid-sensors/Kconfig             |  26 +++
>  drivers/iio/common/hid-sensors/Makefile            |   6 +
>  .../iio/common/hid-sensors/hid-sensor-attributes.c | 250 +++++++++++++++++++++
>  .../iio/common/hid-sensors/hid-sensor-attributes.h |  57 +++++
>  .../iio/common/hid-sensors/hid-sensor-trigger.c    | 102 +++++++++
>  .../iio/common/hid-sensors/hid-sensor-trigger.h    |  26 +++
>  10 files changed, 484 insertions(+)
>  create mode 100644 drivers/iio/common/Kconfig
>  create mode 100644 drivers/iio/common/Makefile
>  create mode 100644 drivers/iio/common/hid-sensors/Kconfig
>  create mode 100644 drivers/iio/common/hid-sensors/Makefile
>  create mode 100644 drivers/iio/common/hid-sensors/hid-sensor-attributes.c
>  create mode 100644 drivers/iio/common/hid-sensors/hid-sensor-attributes.h
>  create mode 100644 drivers/iio/common/hid-sensors/hid-sensor-trigger.c
>  create mode 100644 drivers/iio/common/hid-sensors/hid-sensor-trigger.h
> 
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index 56825e6..c402610 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -59,5 +59,6 @@ source "drivers/iio/amplifiers/Kconfig"
>  source "drivers/iio/light/Kconfig"
>  source "drivers/iio/frequency/Kconfig"
>  source "drivers/iio/dac/Kconfig"
> +source "drivers/iio/common/Kconfig"
>  
>  endif # IIO
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index 34309ab..cfafb0d 100644
> --- a/drivers/iio/Makefile
> +++ b/drivers/iio/Makefile
> @@ -15,3 +15,4 @@ obj-y += amplifiers/
>  obj-y += light/
>  obj-y += frequency/
>  obj-y += dac/
> +obj-y += common/
> diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig
> new file mode 100644
> index 0000000..97ef666
> --- /dev/null
> +++ b/drivers/iio/common/Kconfig
> @@ -0,0 +1,6 @@
> +#
> +# IIO common modules
> +#
> +
> +source "drivers/iio/common/hid-sensors/Kconfig"
> +
> diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile
> new file mode 100644
> index 0000000..8158400
> --- /dev/null
> +++ b/drivers/iio/common/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# Makefile for the IIO common modules.
> +# Common modules contains modules, which can be shared among multiple
> +# IIO modules. For example if the trigger processing is common for
> +# multiple IIO modules then this can be moved to a common module
> +# instead of duplicating in each module.
> +#
> +
> +obj-y += hid-sensors/
> diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig
> new file mode 100644
> index 0000000..8e63d81
> --- /dev/null
> +++ b/drivers/iio/common/hid-sensors/Kconfig
> @@ -0,0 +1,26 @@
> +#
> +# Hid Sensor common modules
> +#
> +menu "Hid Sensor IIO Common"
> +
> +config HID_SENSOR_IIO_COMMON
> +	tristate "Common modules for all HID Sensor IIO drivers"
> +	depends on HID_SENSOR_HUB
> +	select IIO_TRIGGER if IIO_BUFFER
> +	help
> +	  Say yes here to build support for HID sensor to use
> +	  HID sensor common processing for attributes and IIO triggers.
> +	  There are many attributes which can be shared among multiple
> +	  HID sensor drivers, this module contains processing for those
> +	  attributes.
> +
> +config HID_SENSOR_ENUM_BASE_QUIRKS
> +	tristate "ENUM base quirks for HID Sensor IIO drivers"
> +	depends on HID_SENSOR_IIO_COMMON
> +	help
> +	  Say yes here to build support for sensor hub FW using
> +	  enumeration, which is using 1 as base instead of 0.
> +	  Since logical minimum is still set 0 instead of 1,
> +	  there is no easy way to differentiate.
> +
> +endmenu
> diff --git a/drivers/iio/common/hid-sensors/Makefile b/drivers/iio/common/hid-sensors/Makefile
> new file mode 100644
> index 0000000..1f463e0
> --- /dev/null
> +++ b/drivers/iio/common/hid-sensors/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Makefile for the Hid sensor common modules.
> +#
> +
> +obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o
> +hid-sensor-iio-common-y := hid-sensor-attributes.o hid-sensor-trigger.o
> diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
> new file mode 100644
> index 0000000..7537495
> --- /dev/null
> +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
> @@ -0,0 +1,250 @@
> +/*
> + * HID Sensors Driver
> + * Copyright (c) 2012, Intel Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + */
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/slab.h>
> +#include <linux/hid-sensor-hub.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include "hid-sensor-attributes.h"
> +
> +static int pow_10(unsigned power)
> +{
> +	int i;
> +	int ret = 1;
> +	for (i = 0; i < power; ++i)
> +		ret = ret * 10;
> +
> +	return ret;
> +}
> +
> +static void simple_div(int dividend, int divisor, int *whole,
> +				int *micro_frac)
> +{
> +	int rem;
> +	int exp = 0;
> +
> +	*micro_frac = 0;
> +	if (divisor == 0) {
> +		*whole = 0;
> +		return;
> +	}
> +	*whole = dividend/divisor;
> +	rem = dividend % divisor;
> +	if (rem) {
> +		while (rem <= divisor) {
> +			rem *= 10;
> +			exp++;
> +		}
> +		*micro_frac = (rem / divisor) * pow_10(6-exp);
> +	}
> +}
> +
> +static void split_micro_fraction(unsigned int no, int exp, int *val1, int *val2)
> +{
> +	*val1 = no/pow_10(exp);
> +	*val2 = no%pow_10(exp) * pow_10(6-exp);
> +}
> +
> +/*
> +VTF format uses exponent and variable size format.
> +For example if the size is 2 bytes
> +0x0067 with VTF16E14 format -> +1.03
> +To convert just change to 0x67 to decimal and use two decimal as E14 stands
> +for 10^-2.
> +Negative numbers are 2's complement
> +*/
> +static void convert_from_vtf_format(u32 value, int size, int exp,
> +					int *val1, int *val2)
> +{
> +	int sign = 1;
> +
> +	if (value & BIT(size*8 - 1)) {
> +		value =  ((1LL << (size * 8)) - value);
> +		sign = -1;
> +	}
> +	exp = hid_sensor_convert_exponent(exp);
> +	if (exp >= 0) {
> +		*val1 = sign * value * pow_10(exp);
> +		*val2 = 0;
> +	} else {
> +		split_micro_fraction(value, -exp, val1, val2);
> +		if (*val1)
> +			*val1 = sign * (*val1);
> +		else
> +			*val2 = sign * (*val2);
> +	}
> +}
> +
> +static u32 convert_to_vtf_format(int size, int exp, int val1, int val2)
> +{
> +	u32 value;
> +	int sign = 1;
> +
> +	if (val1 < 0 || val2 < 0)
> +		sign = -1;
> +	exp = hid_sensor_convert_exponent(exp);
> +	if (exp < 0) {
> +		value = abs(val1) * pow_10(-exp);
> +		value += abs(val2) / pow_10(6+exp);
> +	} else
> +		value = abs(val1) / pow_10(exp);
> +	if (sign < 0)
> +		value =  ((1LL << (size * 8)) - value);
> +
> +	return value;
> +}
> +
> +int hid_sensor_read_samp_freq_value(struct hid_sensor_iio_common *st,
> +				int *val1, int *val2)
> +{
> +	s32 value;
> +	int ret;
> +
> +	ret = sensor_hub_get_feature(st->hsdev,
> +		st->poll.report_id,
> +		st->poll.index, &value);
> +	if (ret < 0 || value < 0) {
> +		*val1 = *val2 = 0;
> +		return -EINVAL;
> +	} else {
> +		if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND)
> +			simple_div(1000, value, val1, val2);
> +		else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND)
> +			simple_div(1, value, val1, val2);
> +		else {
> +			*val1 = *val2 = 0;
> +			return -EINVAL;
> +		}
> +	}
> +
> +	return IIO_VAL_INT_PLUS_MICRO;
> +}
> +EXPORT_SYMBOL(hid_sensor_read_samp_freq_value);
> +
> +int hid_sensor_write_samp_freq_value(struct hid_sensor_iio_common *st,
> +				int val1, int val2)
> +{
> +	s32 value;
> +	int ret;
> +
> +	if (val1 < 0 || val2 < 0)
> +		ret = -EINVAL;
> +
> +	value = val1 * pow_10(6) + val2;
> +	if (value) {
> +		if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND)
> +			value = pow_10(9)/value;
> +		else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND)
> +			value = pow_10(6)/value;
> +		else
> +			value = 0;
> +	}
> +	ret = sensor_hub_set_feature(st->hsdev,
> +		st->poll.report_id,
> +		st->poll.index, value);
> +	if (ret < 0 || value < 0)
> +		ret = -EINVAL;
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(hid_sensor_write_samp_freq_value);
> +
> +int hid_sensor_read_raw_hyst_value(struct hid_sensor_iio_common *st,
> +				int *val1, int *val2)
> +{
> +	s32 value;
> +	int ret;
> +
> +	ret = sensor_hub_get_feature(st->hsdev,
> +		st->sensitivity.report_id,
> +		st->sensitivity.index, &value);
> +	if (ret < 0 || value < 0) {
> +		*val1 = *val2 = 0;
> +		return -EINVAL;
> +	} else {
> +		convert_from_vtf_format(value, st->sensitivity.size,
> +					st->sensitivity.unit_expo,
> +					val1, val2);
> +	}
> +
> +	return IIO_VAL_INT_PLUS_MICRO;
> +}
> +EXPORT_SYMBOL(hid_sensor_read_raw_hyst_value);
> +
> +int hid_sensor_write_raw_hyst_value(struct hid_sensor_iio_common *st,
> +					int val1, int val2)
> +{
> +	s32 value;
> +	int ret;
> +
> +	value = convert_to_vtf_format(st->sensitivity.size,
> +				st->sensitivity.unit_expo,
> +				val1, val2);
> +	ret = sensor_hub_set_feature(st->hsdev,
> +		st->sensitivity.report_id,
> +		st->sensitivity.index, value);
> +	if (ret < 0 || value < 0)
> +		ret = -EINVAL;
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value);
> +
> +int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
> +					u32 usage_id,
> +					struct hid_sensor_iio_common *st)
> +{
> +
> +	sensor_hub_input_get_attribute_info(hsdev,
> +					HID_FEATURE_REPORT, usage_id,
> +					HID_USAGE_SENSOR_PROP_REPORT_INTERVAL,
> +					&st->poll);
> +
> +	sensor_hub_input_get_attribute_info(hsdev,
> +					HID_FEATURE_REPORT, usage_id,
> +					HID_USAGE_SENSOR_PROP_REPORT_STATE,
> +					&st->report_state);
> +
> +	sensor_hub_input_get_attribute_info(hsdev,
> +					HID_FEATURE_REPORT, usage_id,
> +					HID_USAGE_SENSOR_PROY_POWER_STATE,
> +					&st->power_state);
> +
> +	sensor_hub_input_get_attribute_info(hsdev,
> +			HID_FEATURE_REPORT, usage_id,
> +			HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS,
> +			 &st->sensitivity);
> +
> +	hid_dbg(hsdev->hdev, "common attributes: %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,
> +			st->power_state.index, st->power_state.report_id,
> +			st->sensitivity.index, st->sensitivity.report_id);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(hid_sensor_parse_common_attributes);
> +
> +MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@xxxxxxxxx>");
> +MODULE_DESCRIPTION("HID Sensor common attribute processing");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.h b/drivers/iio/common/hid-sensors/hid-sensor-attributes.h
> new file mode 100644
> index 0000000..a4676a0
> --- /dev/null
> +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.h
> @@ -0,0 +1,57 @@
> +/*
> + * HID Sensors Driver
> + * Copyright (c) 2012, Intel Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + */
> +#ifndef _HID_SENSORS_ATTRIBUTES_H
> +#define _HID_SENSORS_ATTRIBUTES_H
> +
> +/* Common hid sensor iio structure */
> +struct hid_sensor_iio_common {
> +	struct hid_sensor_hub_device *hsdev;
> +	struct platform_device *pdev;
> +	unsigned usage_id;
> +	bool data_ready;
> +	struct hid_sensor_hub_attribute_info poll;
> +	struct hid_sensor_hub_attribute_info report_state;
> +	struct hid_sensor_hub_attribute_info power_state;
> +	struct hid_sensor_hub_attribute_info sensitivity;
> +};
> +
> +/*Convert from hid unit expo to regular exponent*/
> +static inline int hid_sensor_convert_exponent(int unit_expo)
> +{
> +	if (unit_expo < 0x08)
> +		return unit_expo;
> +	else if (unit_expo <= 0x0f)
> +		return -(0x0f-unit_expo+1);
> +	else
> +		return 0;
> +}
> +
> +int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
> +					u32 usage_id,
> +					struct hid_sensor_iio_common *st);
> +int hid_sensor_write_raw_hyst_value(struct hid_sensor_iio_common *st,
> +					int val1, int val2);
> +int hid_sensor_read_raw_hyst_value(struct hid_sensor_iio_common *st,
> +					int *val1, int *val2);
> +int hid_sensor_write_samp_freq_value(struct hid_sensor_iio_common *st,
> +					int val1, int val2);
> +int hid_sensor_read_samp_freq_value(struct hid_sensor_iio_common *st,
> +					int *val1, int *val2);
> +
> +#endif
> diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
> new file mode 100644
> index 0000000..12277e8
> --- /dev/null
> +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
> @@ -0,0 +1,102 @@
> +/*
> + * HID Sensors Driver
> + * Copyright (c) 2012, Intel Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + */
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/slab.h>
> +#include <linux/hid-sensor-hub.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/sysfs.h>
> +#include "hid-sensor-attributes.h"
> +#include "hid-sensor-trigger.h"
> +
> +static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
> +						bool state)
> +{
> +	struct hid_sensor_iio_common *st = trig->private_data;
> +	int state_val;
> +
> +	state_val = state ? 1 : 0;
> +#if (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS) || \
> +	(defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS_MODULE)
> +	++state_val;
> +#endif
> +	st->data_ready = state;
> +	sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
> +					st->power_state.index,
> +					(s32)state_val);
> +
> +	sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
> +					st->report_state.index,
> +					(s32)state_val);
> +
> +	return 0;
> +}
> +
> +void hid_sensor_remove_trigger(struct iio_dev *indio_dev)
> +{
> +	iio_trigger_unregister(indio_dev->trig);
> +	iio_trigger_free(indio_dev->trig);
> +}
> +EXPORT_SYMBOL(hid_sensor_remove_trigger);
> +
> +static const struct iio_trigger_ops hid_sensor_trigger_ops = {
> +	.owner = THIS_MODULE,
> +	.set_trigger_state = &hid_sensor_data_rdy_trigger_set_state,
> +};
> +
> +int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
> +				struct hid_sensor_iio_common *attrb)
> +{
> +	int ret;
> +	struct iio_trigger *trig;
> +
> +	trig = iio_trigger_alloc("%s-dev%d", name, indio_dev->id);
> +	if (trig == NULL) {
> +		dev_err(&indio_dev->dev, "Trigger Allocate Failed\n");
> +		ret = -ENOMEM;
> +		goto error_ret;
> +	}
> +
> +	trig->dev.parent = indio_dev->dev.parent;
> +	trig->private_data = attrb;
> +	trig->ops = &hid_sensor_trigger_ops;
> +	ret = iio_trigger_register(trig);
> +
> +	if (ret) {
> +		dev_err(&indio_dev->dev, "Trigger Register Failed\n");
> +		goto error_free_trig;
> +	}
> +	indio_dev->trig = trig;
> +
> +	return ret;
> +
> +error_free_trig:
> +	iio_trigger_free(trig);
> +error_ret:
> +	return ret;
> +}
> +EXPORT_SYMBOL(hid_sensor_setup_trigger);
> +
> +MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@xxxxxxxxx>");
> +MODULE_DESCRIPTION("HID Sensor trigger processing");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
> new file mode 100644
> index 0000000..fd98297
> --- /dev/null
> +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
> @@ -0,0 +1,26 @@
> +/*
> + * HID Sensors Driver
> + * Copyright (c) 2012, Intel Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + */
> +#ifndef _HID_SENSOR_TRIGGER_H
> +#define _HID_SENSOR_TRIGGER_H
> +
> +int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
> +				struct hid_sensor_iio_common *attrb);
> +void hid_sensor_remove_trigger(struct iio_dev *indio_dev);
> +
> +#endif
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux