diff options
Diffstat (limited to 'drivers/iio/common/hid-sensors/hid-sensor-trigger.c')
| -rw-r--r-- | drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 138 |
1 files changed, 138 insertions, 0 deletions
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 00000000000..a3109a6f4d8 --- /dev/null +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -0,0 +1,138 @@ +/* + * 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-trigger.h" + +int hid_sensor_power_state(struct hid_sensor_common *st, bool state) +{ + int state_val; + int report_val; + + if (state) { + if (sensor_hub_device_open(st->hsdev)) + return -EIO; + + atomic_inc(&st->data_ready); + + state_val = hid_sensor_get_usage_index(st->hsdev, + st->power_state.report_id, + st->power_state.index, + HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM); + report_val = hid_sensor_get_usage_index(st->hsdev, + st->report_state.report_id, + st->report_state.index, + HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); + } else { + if (!atomic_dec_and_test(&st->data_ready)) + return 0; + sensor_hub_device_close(st->hsdev); + state_val = hid_sensor_get_usage_index(st->hsdev, + st->power_state.report_id, + st->power_state.index, + HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM); + report_val = hid_sensor_get_usage_index(st->hsdev, + st->report_state.report_id, + st->report_state.index, + HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM); + } + + if (state_val >= 0) { + state_val += st->power_state.logical_minimum; + sensor_hub_set_feature(st->hsdev, st->power_state.report_id, + st->power_state.index, + (s32)state_val); + } + + if (report_val >= 0) { + report_val += st->report_state.logical_minimum; + sensor_hub_set_feature(st->hsdev, st->report_state.report_id, + st->report_state.index, + (s32)report_val); + } + + sensor_hub_get_feature(st->hsdev, st->power_state.report_id, + st->power_state.index, + &state_val); + return 0; +} +EXPORT_SYMBOL(hid_sensor_power_state); + +static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + return hid_sensor_power_state(iio_trigger_get_drvdata(trig), state); +} + +void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) +{ + iio_trigger_unregister(attrb->trigger); + iio_trigger_free(attrb->trigger); +} +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_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; + iio_trigger_set_drvdata(trig, 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 = attrb->trigger = 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@intel.com>"); +MODULE_DESCRIPTION("HID Sensor trigger processing"); +MODULE_LICENSE("GPL"); |
