diff options
| author | Eric Tashakkor <w36098@motorola.com> | 2014-04-03 08:40:27 -0500 |
|---|---|---|
| committer | ERIC TASHAKKOR <w36098@motorola.com> | 2014-04-11 13:21:21 +0000 |
| commit | f44afc705c2c3dc7c944b8b5e9e972c844f09881 (patch) | |
| tree | 95e4f983e2ea5a6cb2d90664b09a9760b9c6411a | |
| parent | e2dce2b183866d0a347f7a21b80dc54d1c405cd5 (diff) | |
| download | olio-linux-3.10-f44afc705c2c3dc7c944b8b5e9e972c844f09881.tar.xz olio-linux-3.10-f44afc705c2c3dc7c944b8b5e9e972c844f09881.zip | |
IKXCLOCK-627 Remove Custom input.h Changes from M4 Drivers.
Converted the gesture driver to IIO and sysfs (see other M4 drivers).
Converted the passive driver to IIO and sysfs (see other M4 drivers).
Removed fusion data from the mpu9150 driver (needs to be refactored).
Removed custom EV_REL and EV_MSC events and restored stock MAX_* values.
Updated pedometer and heartrate drivers to match gesture and passive.
Updated the ALS driver to init the samplerate to -1 (disabled).
Change-Id: I324bd3a4ee0a4bcbb76f36300d51c5b743aa44f9
Signed-off-by: Eric Tashakkor <w36098@motorola.com>
| -rw-r--r-- | drivers/iio/industrialio-core.c | 2 | ||||
| -rw-r--r-- | drivers/misc/m4sensorhub_als.c | 1 | ||||
| -rw-r--r-- | drivers/misc/m4sensorhub_gesture.c | 649 | ||||
| -rw-r--r-- | drivers/misc/m4sensorhub_heartrate.c | 28 | ||||
| -rw-r--r-- | drivers/misc/m4sensorhub_mpu9150.c | 355 | ||||
| -rw-r--r-- | drivers/misc/m4sensorhub_passive.c | 604 | ||||
| -rw-r--r-- | drivers/misc/m4sensorhub_pedometer.c | 28 | ||||
| -rw-r--r-- | drivers/staging/iio/Documentation/iio_event_monitor.c | 2 | ||||
| -rw-r--r-- | include/linux/iio/m4sensorhub/m4sensorhub_gesture.h | 37 | ||||
| -rw-r--r-- | include/linux/iio/m4sensorhub/m4sensorhub_passive.h | 40 | ||||
| -rw-r--r-- | include/linux/iio/types.h | 2 | ||||
| -rw-r--r-- | include/linux/mod_devicetable.h | 5 | ||||
| -rw-r--r-- | include/uapi/linux/input.h | 37 |
13 files changed, 815 insertions, 975 deletions
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 2b823655fef..0b0de28f31e 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -68,6 +68,8 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_PRESSURE] = "pressure", [IIO_HEARTRATE] = "heartrate", [IIO_PEDOMETER] = "pedometer", + [IIO_PASSIVE] = "passive", + [IIO_GESTURE] = "gesture", }; static const char * const iio_modifier_names[] = { diff --git a/drivers/misc/m4sensorhub_als.c b/drivers/misc/m4sensorhub_als.c index da3b7a00d1a..1835efab2c0 100644 --- a/drivers/misc/m4sensorhub_als.c +++ b/drivers/misc/m4sensorhub_als.c @@ -322,6 +322,7 @@ static int m4als_probe(struct platform_device *pdev) dd->pdev = pdev; mutex_init(&(dd->mutex)); platform_set_drvdata(pdev, dd); + dd->samplerate = -1; /* We always start disabled */ dd->m4 = m4sensorhub_client_get_drvdata(); if (dd->m4 == NULL) { diff --git a/drivers/misc/m4sensorhub_gesture.c b/drivers/misc/m4sensorhub_gesture.c index eb814fa220b..2686a0f9501 100644 --- a/drivers/misc/m4sensorhub_gesture.c +++ b/drivers/misc/m4sensorhub_gesture.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Motorola, Inc. + * Copyright (C) 2012-2014 Motorola, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Adds ability to program periodic interrupts from user space that * can wake the phone out of low power modes. @@ -23,414 +23,431 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/miscdevice.h> #include <linux/platform_device.h> -#include <linux/proc_fs.h> -#include <linux/input.h> +#include <linux/fs.h> #include <linux/m4sensorhub.h> -#include <linux/m4sensorhub_client_ioctl.h> -#include <linux/uaccess.h> -#include <linux/m4sensorhub/MemMapGesture.h> #include <linux/slab.h> +#include <linux/iio/iio.h> +#include <linux/iio/types.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/events.h> +#include <linux/iio/buffer.h> +#include <linux/iio/kfifo_buf.h> +#include <linux/iio/m4sensorhub/m4sensorhub_gesture.h> -#define GESTURE_CLIENT_DRIVER_NAME "m4sensorhub_gesture" +#define m4ges_err(format, args...) KDEBUG(M4SH_ERROR, format, ## args) -struct gesture_client { - struct m4sensorhub_data *m4sensorhub; - struct input_dev *input_dev; - struct memMapGesture gesture_data; -}; +#define M4GES_IRQ_ENABLED_BIT 0 -static bool read_gesture_value(struct gesture_client *list, - signed char *value, - eGestureType gesture) -{ - if (list->gesture_data.gesture1 == gesture) { - *value = list->gesture_data.value1; - return true; - } else if (list->gesture_data.gesture2 == gesture) { - *value = list->gesture_data.value2; - return true; - } else if (list->gesture_data.gesture3 == gesture) { - *value = list->gesture_data.value3; - return true; - } else { - *value = 0; - return false; - } -} +struct m4ges_driver_data { + struct platform_device *pdev; + struct m4sensorhub_data *m4; + struct mutex mutex; /* controls driver entry points */ + + struct m4sensorhub_gesture_iio_data iiodat; + int16_t samplerate; + uint16_t status; +}; -static struct gesture_client *misc_gesture_data; -static int gesture_client_open(struct inode *inode, struct file *file) +static void m4ges_isr(enum m4sensorhub_irqs int_event, void *handle) { int err = 0; + struct iio_dev *iio = handle; + struct m4ges_driver_data *dd = iio_priv(iio); + int size = 0; + + mutex_lock(&(dd->mutex)); - err = nonseekable_open(inode, file); + size = m4sensorhub_reg_getsize(dd->m4, M4SH_REG_GESTURE_GESTURE1); + err = m4sensorhub_reg_read(dd->m4, M4SH_REG_GESTURE_GESTURE1, + (char *)&(dd->iiodat.gesture_type)); if (err < 0) { - KDEBUG(M4SH_ERROR, "%s failed\n", __func__); - return err; + m4ges_err("%s: Failed to read gesture_type data.\n", __func__); + goto m4ges_isr_fail; + } else if (err != size) { + m4ges_err("%s: Read %d bytes instead of %d for %s.\n", + __func__, err, size, "gesture_type"); + err = -EBADE; + goto m4ges_isr_fail; } - file->private_data = misc_gesture_data; - return 0; -} + size = m4sensorhub_reg_getsize(dd->m4, M4SH_REG_GESTURE_CONFIDENCE1); + err = m4sensorhub_reg_read(dd->m4, M4SH_REG_GESTURE_CONFIDENCE1, + (char *)&(dd->iiodat.gesture_confidence)); + if (err < 0) { + m4ges_err("%s: Failed to read gesture_confidence data.\n", + __func__); + goto m4ges_isr_fail; + } else if (err != size) { + m4ges_err("%s: Read %d bytes instead of %d for %s.\n", + __func__, err, size, "gesture_confidence"); + err = -EBADE; + goto m4ges_isr_fail; + } -static int gesture_client_close(struct inode *inode, struct file *file) -{ - KDEBUG(M4SH_DEBUG, "gesture_client in %s\n", __func__); - return 0; -} + size = m4sensorhub_reg_getsize(dd->m4, M4SH_REG_GESTURE_VALUE1); + err = m4sensorhub_reg_read(dd->m4, M4SH_REG_GESTURE_VALUE1, + (char *)&(dd->iiodat.gesture_value)); + if (err < 0) { + m4ges_err("%s: Failed to read gesture_value data.\n", __func__); + goto m4ges_isr_fail; + } else if (err != size) { + m4ges_err("%s: Read %d bytes instead of %d for %s.\n", + __func__, err, size, "gesture_value"); + err = -EBADE; + goto m4ges_isr_fail; + } -static char m4_read_gesture_data(struct gesture_client *gesture_client_data) -{ - int ret; - struct memMapGesture *gdata = &(gesture_client_data->gesture_data); + dd->iiodat.timestamp = iio_get_time_ns(); + iio_push_to_buffers(iio, (unsigned char *)&(dd->iiodat)); - ret = m4sensorhub_reg_read_n(gesture_client_data->m4sensorhub, - M4SH_REG_GESTURE_VERSION, - (char *)gdata, - sizeof(gesture_client_data->gesture_data)); +m4ges_isr_fail: + if (err < 0) + m4ges_err("%s: Failed with error code %d.\n", __func__, err); - if (ret != sizeof(gesture_client_data->gesture_data)) - goto ERR; + mutex_unlock(&(dd->mutex)); - KDEBUG(M4SH_DEBUG, "Gesture1 = %d, gesture2 = %d, gesture3 = %d\n", - gdata->gesture1, gdata->gesture2, gdata->gesture3); - KDEBUG(M4SH_DEBUG, "Confidence1 = %d, confidence2 = %d, confidence3 = %d\n", - gdata->confidence1, gdata->confidence2, gdata->confidence3); - KDEBUG(M4SH_DEBUG, "Value1 = %d, value2 = %d, value3 = %d\n", - gdata->value1, gdata->value2, gdata->value3); - return 0; -ERR: - KDEBUG(M4SH_ERROR, "Gesture read failed\n"); - return -1; + return; } -static void m4_handle_gesture_irq(enum m4sensorhub_irqs int_event, - void *gesture_data) +static int m4ges_set_samplerate(struct iio_dev *iio, int16_t rate) { - signed char value; - /*Trigger broadcast of display gesture intent*/ - struct gesture_client *gesture_client_data = - (struct gesture_client *)gesture_data; - - struct memMapGesture *gdata = &(gesture_client_data->gesture_data); + int err = 0; + struct m4ges_driver_data *dd = iio_priv(iio); - if (m4_read_gesture_data(gesture_client_data) < 0) { - KDEBUG(M4SH_ERROR, "m4_read_gesture_data returned \ - error %s\n", __func__); - return; - } + /* + * Currently, there is no concept of setting a sample rate for this + * sensor, so this function only enables/disables interrupt reporting. + */ + dd->samplerate = rate; - if (read_gesture_value(gesture_client_data, &value, GESTURE_TILT_SCROLL)) { - input_event(gesture_client_data->input_dev, EV_ABS, - ABS_TILTSCROLL, value); + if (rate >= 0) { + /* Enable the IRQ if necessary */ + if (!(dd->status & (1 << M4GES_IRQ_ENABLED_BIT))) { + err = m4sensorhub_irq_enable(dd->m4, + M4SH_IRQ_GESTURE_DETECTED); + if (err < 0) { + m4ges_err("%s: Failed to enable irq.\n", + __func__); + goto m4ges_set_samplerate_fail; + } + dd->status = dd->status | (1 << M4GES_IRQ_ENABLED_BIT); + } } else { - if (read_gesture_value(gesture_client_data, &value, GESTURE_WRIST_ROTATE)) { - /* send event to stop scrolling for wrist rotate */ - input_event(gesture_client_data->input_dev, EV_ABS, - ABS_TILTSCROLL, 0); + /* Disable the IRQ if necessary */ + if (dd->status & (1 << M4GES_IRQ_ENABLED_BIT)) { + err = m4sensorhub_irq_disable(dd->m4, + M4SH_IRQ_GESTURE_DETECTED); + if (err < 0) { + m4ges_err("%s: Failed to disable irq.\n", + __func__); + goto m4ges_set_samplerate_fail; + } + dd->status = dd->status & ~(1 << M4GES_IRQ_ENABLED_BIT); } } - input_event(gesture_client_data->input_dev, EV_MSC, - MSC_GESTURE1, gdata->gesture1); - input_event(gesture_client_data->input_dev, EV_MSC, - MSC_GESTURE2, gdata->gesture2); - input_event(gesture_client_data->input_dev, EV_MSC, - MSC_GESTURE3, gdata->gesture3); - input_event(gesture_client_data->input_dev, EV_MSC, - MSC_GESTURE_CONFIDENCE1, gdata->confidence1); - input_event(gesture_client_data->input_dev, EV_MSC, - MSC_GESTURE_CONFIDENCE2, gdata->confidence2); - input_event(gesture_client_data->input_dev, EV_MSC, - MSC_GESTURE_CONFIDENCE3, gdata->confidence3); - input_event(gesture_client_data->input_dev, EV_MSC, - MSC_GESTURE_VALUE1, gdata->value1); - input_event(gesture_client_data->input_dev, EV_MSC, - MSC_GESTURE_VALUE2, gdata->value2); - input_event(gesture_client_data->input_dev, EV_MSC, - MSC_GESTURE_VALUE3, gdata->value3); +m4ges_set_samplerate_fail: + return err; +} - input_sync(gesture_client_data->input_dev); +static ssize_t m4ges_setrate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iio_dev *iio = platform_get_drvdata(pdev); + struct m4ges_driver_data *dd = iio_priv(iio); + ssize_t size = 0; + mutex_lock(&(dd->mutex)); + size = snprintf(buf, PAGE_SIZE, "Current rate: %hd\n", dd->samplerate); + mutex_unlock(&(dd->mutex)); + return size; } - -/* - * Handle commands from user-space. - */ -static long gesture_client_ioctl(struct file *filp, - unsigned int cmd, unsigned long arg) +static ssize_t m4ges_setrate_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) { - int ret = 0; - void __user *argp = (void __user *)arg; - struct gesture_client *gesture_client_data = filp->private_data; - unsigned char byte; + int err = 0; + struct platform_device *pdev = to_platform_device(dev); + struct iio_dev *iio = platform_get_drvdata(pdev); + struct m4ges_driver_data *dd = iio_priv(iio); + int value = 0; - switch (cmd) { - case M4_SENSOR_IOCTL_SET_SCREEN_ON_GESTURE_STATUS: - /* TODO - Turn on/off the gesture feature on M4 */ - break; - case M4_SENSOR_IOCTL_SET_SCREEN_STATUS: - if (copy_from_user(&byte, argp, sizeof(byte))) { - KDEBUG(M4SH_ERROR, "Copy frm usr err:screen status\n"); - ret = -EFAULT; - break; - } - /* validate data */ - if (byte > 1) { - KDEBUG(M4SH_DEBUG, "Invalid screen status=0x%x", byte); - ret = -EINVAL; - break; - } - KDEBUG(M4SH_DEBUG, "Screen status set to = 0x%x", byte); - ret = m4sensorhub_reg_write_1byte( - gesture_client_data->m4sensorhub, - M4SH_REG_USERSETTINGS_SCREENSTATUS, byte, 0xFF); - if (ret != 1) - KDEBUG(M4SH_ERROR, "Error writing screen status\n"); - break; - default: - KDEBUG(M4SH_ERROR, "Invalid IOCTL Command in %s\n", __func__); - ret = -EINVAL; + mutex_lock(&(dd->mutex)); + + err = kstrtoint(buf, 10, &value); + if (err < 0) { + m4ges_err("%s: Failed to convert value.\n", __func__); + goto m4ges_enable_store_exit; + } + + if ((value < -1) || (value > 32767)) { + m4ges_err("%s: Invalid samplerate %d passed.\n", + __func__, value); + err = -EINVAL; + goto m4ges_enable_store_exit; } - return ret; + + err = m4ges_set_samplerate(iio, value); + if (err < 0) { + m4ges_err("%s: Failed to set sample rate.\n", __func__); + goto m4ges_enable_store_exit; + } + +m4ges_enable_store_exit: + if (err < 0) { + m4ges_err("%s: Failed with error code %d.\n", __func__, err); + size = err; + } + + mutex_unlock(&(dd->mutex)); + + return size; } +static IIO_DEVICE_ATTR(setrate, S_IRUSR | S_IWUSR, + m4ges_setrate_show, m4ges_setrate_store, 0); -static ssize_t m4_gesture_status(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t m4ges_iiodata_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct platform_device *pdev = to_platform_device(dev); - struct gesture_client *gesture_client_data = platform_get_drvdata(pdev); - - if (m4_read_gesture_data(gesture_client_data) < 0) - KDEBUG(M4SH_ERROR, "%s: Read gesture data failed \n", __func__); - KDEBUG(M4SH_DEBUG, "%s:Gesture1,2,3 = %d %d %d conf1,2,3 = %d %d %d value1,2,3 = %d %d %d\n", - __func__, gesture_client_data->gesture_data.gesture1, - gesture_client_data->gesture_data.gesture2, - gesture_client_data->gesture_data.gesture3, - gesture_client_data->gesture_data.confidence1, - gesture_client_data->gesture_data.confidence2, - gesture_client_data->gesture_data.confidence3, - gesture_client_data->gesture_data.value1, - gesture_client_data->gesture_data.value2, - gesture_client_data->gesture_data.value3); + struct iio_dev *iio = platform_get_drvdata(pdev); + struct m4ges_driver_data *dd = iio_priv(iio); + ssize_t size = 0; - return sprintf(buf, "gesture1,2,3=%d %d %d,confidence1,2,3=%d %d %d value1,2,3 = %d %d %d\n", - gesture_client_data->gesture_data.gesture1, - gesture_client_data->gesture_data.gesture2, - gesture_client_data->gesture_data.gesture3, - gesture_client_data->gesture_data.confidence1, - gesture_client_data->gesture_data.confidence2, - gesture_client_data->gesture_data.confidence3, - gesture_client_data->gesture_data.value1, - gesture_client_data->gesture_data.value2, - gesture_client_data->gesture_data.value3); + mutex_lock(&(dd->mutex)); + size = snprintf(buf, PAGE_SIZE, + "%s%hhu\n%s%hhu\n%s%hhd\n", + "gesture_type: ", dd->iiodat.gesture_type, + "gesture_confidence: ", dd->iiodat.gesture_confidence, + "gesture_value: ", dd->iiodat.gesture_value); + mutex_unlock(&(dd->mutex)); + return size; } +static IIO_DEVICE_ATTR(iiodata, S_IRUGO, m4ges_iiodata_show, NULL, 0); + +static struct attribute *m4ges_iio_attributes[] = { + &iio_dev_attr_setrate.dev_attr.attr, + &iio_dev_attr_iiodata.dev_attr.attr, + NULL, +}; -static DEVICE_ATTR(gesture_status, 0444, m4_gesture_status, NULL); +static const struct attribute_group m4ges_iio_attr_group = { + .attrs = m4ges_iio_attributes, +}; -static const struct file_operations gesture_client_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = gesture_client_ioctl, - .open = gesture_client_open, - .release = gesture_client_close, +static const struct iio_info m4ges_iio_info = { + .driver_module = THIS_MODULE, + .attrs = &m4ges_iio_attr_group, }; -static struct miscdevice gesture_client_miscdrv = { - .minor = MISC_DYNAMIC_MINOR, - .name = GESTURE_CLIENT_DRIVER_NAME, - .fops = &gesture_client_fops, +static const struct iio_chan_spec m4ges_iio_channels[] = { + { + .type = IIO_GESTURE, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = M4GES_DATA_STRUCT_SIZE_BITS, + .storagebits = M4GES_DATA_STRUCT_SIZE_BITS, + .shift = 0, + }, + }, }; -static int gesture_driver_init(struct init_calldata *p_arg) +static void m4ges_remove_iiodev(struct iio_dev *iio) { - int ret = 0; - struct m4sensorhub_data *m4sensorhub = p_arg->p_m4sensorhub_data; - ret = m4sensorhub_irq_register(m4sensorhub, M4SH_IRQ_GESTURE_DETECTED, - m4_handle_gesture_irq, - misc_gesture_data); - if (ret < 0) { - KDEBUG(M4SH_ERROR, "Error registering int %d (%d)\n", - M4SH_IRQ_GESTURE_DETECTED, ret); - return ret; - } - ret = m4sensorhub_irq_enable(m4sensorhub, M4SH_IRQ_GESTURE_DETECTED); - if (ret < 0) { - KDEBUG(M4SH_ERROR, "Error enabling int %d (%d)\n", - M4SH_IRQ_GESTURE_DETECTED, ret); - goto exit; - } - return ret; + struct m4ges_driver_data *dd = iio_priv(iio); -exit: - m4sensorhub_irq_unregister(m4sensorhub, M4SH_IRQ_GESTURE_DETECTED); - return ret; + /* Remember, only call when dd->mutex is locked */ + iio_kfifo_free(iio->buffer); + iio_buffer_unregister(iio); + iio_device_unregister(iio); + mutex_destroy(&(dd->mutex)); + iio_device_free(iio); /* dd is freed here */ + return; } -static int gesture_client_probe(struct platform_device *pdev) +static int m4ges_create_iiodev(struct iio_dev *iio) { - int ret = -1; - struct gesture_client *gesture_client_data; - struct m4sensorhub_data *m4sensorhub = m4sensorhub_client_get_drvdata(); + int err = 0; + struct m4ges_driver_data *dd = iio_priv(iio); - if (!m4sensorhub) - return -EFAULT; + iio->name = M4GES_DRIVER_NAME; + iio->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_HARDWARE; + iio->num_channels = 1; + iio->info = &m4ges_iio_info; + iio->channels = m4ges_iio_channels; - gesture_client_data = kzalloc(sizeof(*gesture_client_data), - GFP_KERNEL); - if (!gesture_client_data) { - KDEBUG(M4SH_ERROR, "%s failed: unable to allocate" - "for client_data\n", __func__); - return -ENOMEM; + iio->buffer = iio_kfifo_allocate(iio); + if (iio->buffer == NULL) { + m4ges_err("%s: Failed to allocate IIO buffer.\n", __func__); + err = -ENOMEM; + goto m4ges_create_iiodev_kfifo_fail; } - gesture_client_data->m4sensorhub = m4sensorhub; - platform_set_drvdata(pdev, gesture_client_data); + iio->buffer->scan_timestamp = true; + iio->buffer->access->set_bytes_per_datum(iio->buffer, + sizeof(dd->iiodat)); + err = iio_buffer_register(iio, iio->channels, iio->num_channels); + if (err < 0) { + m4ges_err("%s: Failed to register IIO buffer.\n", __func__); + goto m4ges_create_iiodev_buffer_fail; + } - gesture_client_data->input_dev = input_allocate_device(); - if (!gesture_client_data->input_dev) { - ret = -ENOMEM; - KDEBUG(M4SH_ERROR, "%s: input device allocate failed: %d\n", - __func__, ret); - goto free_mem; + err = iio_device_register(iio); + if (err < 0) { + m4ges_err("%s: Failed to register IIO device.\n", __func__); + goto m4ges_create_iiodev_iioreg_fail; } - gesture_client_data->input_dev->name = GESTURE_CLIENT_DRIVER_NAME; - set_bit(EV_MSC, gesture_client_data->input_dev->evbit); - set_bit(MSC_GESTURE1, gesture_client_data->input_dev->mscbit); - set_bit(MSC_GESTURE2, gesture_client_data->input_dev->mscbit); - set_bit(MSC_GESTURE3, gesture_client_data->input_dev->mscbit); - set_bit(MSC_GESTURE_CONFIDENCE1, gesture_client_data->input_dev->mscbit); - set_bit(MSC_GESTURE_CONFIDENCE2, gesture_client_data->input_dev->mscbit); - set_bit(MSC_GESTURE_CONFIDENCE3, gesture_client_data->input_dev->mscbit); - set_bit(MSC_GESTURE_VALUE1, gesture_client_data->input_dev->mscbit); - set_bit(MSC_GESTURE_VALUE2, gesture_client_data->input_dev->mscbit); - set_bit(MSC_GESTURE_VALUE3, gesture_client_data->input_dev->mscbit); + goto m4ges_create_iiodev_exit; - set_bit(EV_ABS, gesture_client_data->input_dev->evbit); - input_set_abs_params(gesture_client_data->input_dev, ABS_TILTSCROLL, - -128, 127, 0, 0); +m4ges_create_iiodev_iioreg_fail: + iio_buffer_unregister(iio); +m4ges_create_iiodev_buffer_fail: + iio_kfifo_free(iio->buffer); +m4ges_create_iiodev_kfifo_fail: + iio_device_free(iio); /* dd is freed here */ +m4ges_create_iiodev_exit: + return err; +} - if (input_register_device(gesture_client_data->input_dev)) { - KDEBUG(M4SH_ERROR, "%s: input device register failed\n", - __func__); - input_free_device(gesture_client_data->input_dev); - goto free_mem; - } +static int m4ges_driver_init(struct init_calldata *p_arg) +{ + struct iio_dev *iio = p_arg->p_data; + struct m4ges_driver_data *dd = iio_priv(iio); + int err = 0; - ret = misc_register(&gesture_client_miscdrv); - if (ret < 0) { - KDEBUG(M4SH_ERROR, "Error registering %s driver\n", __func__); - goto unregister_input_device; - } - misc_gesture_data = gesture_client_data; - ret = m4sensorhub_register_initcall(gesture_driver_init, - gesture_client_data); - if (ret < 0) { - KDEBUG(M4SH_ERROR, "Unable to register init function" - "for gesture client = %d\n", ret); - goto unregister_misc_device; + mutex_lock(&(dd->mutex)); + + dd->m4 = p_arg->p_m4sensorhub_data; + if (dd->m4 == NULL) { + m4ges_err("%s: M4 sensor data is NULL.\n", __func__); + err = -ENODATA; + goto m4ges_driver_init_fail; } - if (device_create_file(&pdev->dev, &dev_attr_gesture_status)) { - KDEBUG(M4SH_ERROR, "Error creating %s sys entry\n", __func__); - ret = -1; - goto unregister_initcall; + + err = m4sensorhub_irq_register(dd->m4, + M4SH_IRQ_GESTURE_DETECTED, m4ges_isr, iio); + if (err < 0) { + m4ges_err("%s: Failed to register M4 IRQ.\n", __func__); + goto m4ges_driver_init_fail; } - KDEBUG(M4SH_INFO, "Initialized %s driver\n", __func__); - return 0; -unregister_initcall: - m4sensorhub_unregister_initcall(gesture_driver_init); -unregister_misc_device: - misc_gesture_data = NULL; - misc_deregister(&gesture_client_miscdrv); -unregister_input_device: - input_unregister_device(gesture_client_data->input_dev); -free_mem: - platform_set_drvdata(pdev, NULL); - gesture_client_data->m4sensorhub = NULL; - kfree(gesture_client_data); - gesture_client_data = NULL; - return ret; + goto m4ges_driver_init_exit; + +m4ges_driver_init_fail: + m4ges_err("%s: Init failed with error code %d.\n", __func__, err); +m4ges_driver_init_exit: + mutex_unlock(&(dd->mutex)); + return err; } -static int __exit gesture_client_remove(struct platform_device *pdev) +static int m4ges_probe(struct platform_device *pdev) { - struct gesture_client *gesture_client_data = - platform_get_drvdata(pdev); + struct m4ges_driver_data *dd = NULL; + struct iio_dev *iio = NULL; + int err = 0; - device_remove_file(&pdev->dev, &dev_attr_gesture_status); - m4sensorhub_irq_disable(gesture_client_data->m4sensorhub, - M4SH_IRQ_GESTURE_DETECTED); - m4sensorhub_irq_unregister(gesture_client_data->m4sensorhub, - M4SH_IRQ_GESTURE_DETECTED); - m4sensorhub_unregister_initcall(gesture_driver_init); - misc_gesture_data = NULL; - misc_deregister(&gesture_client_miscdrv); - input_unregister_device(gesture_client_data->input_dev); - platform_set_drvdata(pdev, NULL); - gesture_client_data->m4sensorhub = NULL; - kfree(gesture_client_data); - gesture_client_data = NULL; - return 0; -} + iio = iio_device_alloc(sizeof(dd)); + if (iio == NULL) { + m4ges_err("%s: Failed to allocate IIO data.\n", __func__); + err = -ENOMEM; + goto m4ges_probe_fail_noiio; + } + + dd = iio_priv(iio); + dd->pdev = pdev; + mutex_init(&(dd->mutex)); + platform_set_drvdata(pdev, iio); + dd->samplerate = -1; /* We always start disabled */ + + err = m4ges_create_iiodev(iio); /* iio and dd are freed on fail */ + if (err < 0) { + m4ges_err("%s: Failed to create IIO device.\n", __func__); + goto m4ges_probe_fail_noiio; + } + + err = m4sensorhub_register_initcall(m4ges_driver_init, iio); + if (err < 0) { + m4ges_err("%s: Failed to register initcall.\n", __func__); + goto m4ges_probe_fail; + } -static void gesture_client_shutdown(struct platform_device *pdev) -{ - return; -} -#ifdef CONFIG_PM -static int gesture_client_suspend(struct platform_device *pdev, - pm_message_t message) -{ return 0; + +m4ges_probe_fail: + mutex_destroy(&(dd->mutex)); + m4ges_remove_iiodev(iio); /* iio and dd are freed here */ +m4ges_probe_fail_noiio: + m4ges_err("%s: Probe failed with error code %d.\n", __func__, err); + return err; } -static int gesture_client_resume(struct platform_device *pdev) +static int __exit m4ges_remove(struct platform_device *pdev) { + struct iio_dev *iio = platform_get_drvdata(pdev); + struct m4ges_driver_data *dd = NULL; + + if (iio == NULL) + goto m4ges_remove_exit; + + dd = iio_priv(iio); + if (dd == NULL) + goto m4ges_remove_exit; + + mutex_lock(&(dd->mutex)); + if (dd->status & (1 << M4GES_IRQ_ENABLED_BIT)) { + m4sensorhub_irq_disable(dd->m4, + M4SH_IRQ_GESTURE_DETECTED); + dd->status = dd->status & ~(1 << M4GES_IRQ_ENABLED_BIT); + } + m4sensorhub_irq_unregister(dd->m4, + M4SH_IRQ_GESTURE_DETECTED); + m4sensorhub_unregister_initcall(m4ges_driver_init); + mutex_destroy(&(dd->mutex)); + m4ges_remove_iiodev(iio); /* dd is freed here */ + +m4ges_remove_exit: return 0; } -#else -#define gesture_client_suspend NULL -#define gesture_client_resume NULL -#endif static struct of_device_id m4gesture_match_tbl[] = { { .compatible = "mot,m4gesture" }, {}, }; -static struct platform_driver gesture_client_driver = { - .probe = gesture_client_probe, - .remove = __exit_p(gesture_client_remove), - .shutdown = gesture_client_shutdown, - .suspend = gesture_client_suspend, - .resume = gesture_client_resume, +static struct platform_driver m4ges_driver = { + .probe = m4ges_probe, + .remove = __exit_p(m4ges_remove), + .shutdown = NULL, + .suspend = NULL, + .resume = NULL, .driver = { - .name = GESTURE_CLIENT_DRIVER_NAME, + .name = M4GES_DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = of_match_ptr(m4gesture_match_tbl), }, }; -static int __init gesture_client_init(void) +static int __init m4ges_init(void) { - return platform_driver_register(&gesture_client_driver); + return platform_driver_register(&m4ges_driver); } -static void __exit gesture_client_exit(void) +static void __exit m4ges_exit(void) { - platform_driver_unregister(&gesture_client_driver); + platform_driver_unregister(&m4ges_driver); } -module_init(gesture_client_init); -module_exit(gesture_client_exit); +module_init(m4ges_init); +module_exit(m4ges_exit); -MODULE_ALIAS("platform:gesture_client"); +MODULE_ALIAS("platform:m4ges"); MODULE_DESCRIPTION("M4 Sensor Hub Gesture client driver"); MODULE_AUTHOR("Motorola"); MODULE_LICENSE("GPL"); - diff --git a/drivers/misc/m4sensorhub_heartrate.c b/drivers/misc/m4sensorhub_heartrate.c index 8f6ea2f1648..a35be957f15 100644 --- a/drivers/misc/m4sensorhub_heartrate.c +++ b/drivers/misc/m4sensorhub_heartrate.c @@ -315,35 +315,19 @@ static int m4hrt_driver_init(struct init_calldata *p_arg) goto m4hrt_driver_init_fail; } - err = m4hrt_create_iiodev(iio); - if (err < 0) { - m4hrt_err("%s: Failed to create IIO device.\n", __func__); - goto m4hrt_driver_init_fail; - } - err = m4sensorhub_irq_register(dd->m4, M4SH_IRQ_HEARTRATESENSOR_DATA_READY, m4hrt_isr, iio); if (err < 0) { m4hrt_err("%s: Failed to register M4 IRQ.\n", __func__); - goto m4hrt_driver_init_irq_fail; + goto m4hrt_driver_init_fail; } - /* - * NOTE: We're intentionally unlocking here instead of - * at function end (after error cases). The reason - * is that the mutex ceases to exist because IIO is - * freed, so we would cause a panic putting the unlock - * after m4hrt_driver_init_exit. - */ - mutex_unlock(&(dd->mutex)); - goto m4hrt_driver_init_exit; -m4hrt_driver_init_irq_fail: - m4hrt_remove_iiodev(iio); /* dd is freed here */ m4hrt_driver_init_fail: m4hrt_err("%s: Init failed with error code %d.\n", __func__, err); m4hrt_driver_init_exit: + mutex_unlock(&(dd->mutex)); return err; } @@ -366,6 +350,12 @@ static int m4hrt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, iio); dd->samplerate = -1; /* We always start disabled */ + err = m4hrt_create_iiodev(iio); /* iio and dd are freed on fail */ + if (err < 0) { + m4hrt_err("%s: Failed to create IIO device.\n", __func__); + goto m4hrt_probe_fail_noiio; + } + err = m4sensorhub_register_initcall(m4hrt_driver_init, iio); if (err < 0) { m4hrt_err("%s: Failed to register initcall.\n", __func__); @@ -376,7 +366,7 @@ static int m4hrt_probe(struct platform_device *pdev) m4hrt_probe_fail: mutex_destroy(&(dd->mutex)); - iio_device_free(iio); /* dd is freed here */ + m4hrt_remove_iiodev(iio); /* iio and dd are freed here */ m4hrt_probe_fail_noiio: m4hrt_err("%s: Probe failed with error code %d.\n", __func__, err); return err; diff --git a/drivers/misc/m4sensorhub_mpu9150.c b/drivers/misc/m4sensorhub_mpu9150.c index 72334661dcb..c1785faaea9 100644 --- a/drivers/misc/m4sensorhub_mpu9150.c +++ b/drivers/misc/m4sensorhub_mpu9150.c @@ -31,7 +31,6 @@ #include <linux/m4sensorhub/MemMapGyroSensor.h> #include <linux/m4sensorhub/MemMapAccelSensor.h> #include <linux/m4sensorhub/MemMapCompassSensor.h> -#include <linux/m4sensorhub/MemMapFusionSensor.h> #include <linux/uaccess.h> #include <linux/slab.h> @@ -61,30 +60,10 @@ struct mpu9150_compass_data { int cz; int ca; }; -struct mpu9150_accel_local_data { - int lx; - int ly; - int lz; -}; -struct mpu9150_accel_world_data { - int wx; - int wy; - int wz; -}; -struct mpu9150_euler_data { - int roll; - int pitch; - int yaw; -}; -struct mpu9150_heading_data { - int heading; - int accuracy; -}; enum mpu9150_sensor { TYPE_GYRO, TYPE_COMPASS, TYPE_ACCEL, - TYPE_FUSION, NUM_TYPES, /* Leave as last element */ } sensor; @@ -96,10 +75,6 @@ struct mpu9150_client { struct mpu9150_accel_data accel_data; struct mpu9150_gyro_data gyro_data; struct mpu9150_compass_data compass_data; - struct mpu9150_accel_local_data accel_local_data; - struct mpu9150_accel_world_data accel_world_data; - struct mpu9150_euler_data euler_data; - struct mpu9150_heading_data heading_data; }; struct mpu9150_client *misc_mpu9150_data; @@ -159,44 +134,6 @@ static void m4_report_mpu9150_inputevent( /* TODO : accuracy needs to be sent out through sysfs*/ input_sync(mpu9150_client_data->input_dev); break; - case TYPE_FUSION: - input_report_rel(mpu9150_client_data->input_dev, REL_X, - mpu9150_client_data->accel_data.x); - input_report_rel(mpu9150_client_data->input_dev, REL_Y, - mpu9150_client_data->accel_data.y); - input_report_rel(mpu9150_client_data->input_dev, REL_Z, - mpu9150_client_data->accel_data.z); - input_report_rel(mpu9150_client_data->input_dev, REL_GX, - mpu9150_client_data->gyro_data.rx); - input_report_rel(mpu9150_client_data->input_dev, REL_GY, - mpu9150_client_data->gyro_data.ry); - input_report_rel(mpu9150_client_data->input_dev, REL_GZ, - mpu9150_client_data->gyro_data.rz); - input_report_rel(mpu9150_client_data->input_dev, REL_LX, - mpu9150_client_data->accel_local_data.lx); - input_report_rel(mpu9150_client_data->input_dev, REL_LY, - mpu9150_client_data->accel_local_data.ly); - input_report_rel(mpu9150_client_data->input_dev, REL_LZ, - mpu9150_client_data->accel_local_data.lz); - input_report_rel(mpu9150_client_data->input_dev, REL_WX, - mpu9150_client_data->accel_world_data.wx); - input_report_rel(mpu9150_client_data->input_dev, REL_WY, - mpu9150_client_data->accel_world_data.wy); - input_report_rel(mpu9150_client_data->input_dev, REL_WZ, - mpu9150_client_data->accel_world_data.wz); - input_report_rel(mpu9150_client_data->input_dev, REL_ROLL, - mpu9150_client_data->euler_data.roll); - input_report_rel(mpu9150_client_data->input_dev, REL_PITCH, - mpu9150_client_data->euler_data.pitch); - input_report_rel(mpu9150_client_data->input_dev, REL_YAW, - mpu9150_client_data->euler_data.yaw); - input_report_rel(mpu9150_client_data->input_dev, REL_HEADING, - mpu9150_client_data->heading_data.heading); - input_report_rel(mpu9150_client_data->input_dev, - REL_HEADING_ACCURACY, - mpu9150_client_data->heading_data.accuracy); - input_sync(mpu9150_client_data->input_dev); - break; default: break; } @@ -222,10 +159,6 @@ static void m4_set_mpu9150_delay(struct mpu9150_client *mpu9150_client_data, m4sensorhub_reg_write(mpu9150_client_data->m4sensorhub, M4SH_REG_COMPASS_SAMPLERATE, (char *)&delay, m4sh_no_mask); break; - case TYPE_FUSION: - m4sensorhub_reg_write(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_SAMPLERATE, (char *)&delay, m4sh_no_mask); - break; default: return; break; @@ -242,7 +175,6 @@ static void m4_set_mpu9150_delay(struct mpu9150_client *mpu9150_client_data, static void m4_read_mpu9150_data(struct mpu9150_client *mpu9150_client_data, enum mpu9150_sensor type) { - sFusionData fusiondata; sCompassData compassdata; sAccelData acceldata; sGyroData gyrodata; @@ -287,72 +219,7 @@ static void m4_read_mpu9150_data(struct mpu9150_client *mpu9150_client_data, mpu9150_client_data->compass_data.ca = compassdata.accuracy; break; - case TYPE_FUSION: - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_ACCEL_X, (char *)&acceldata.x); - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_ACCEL_Y, (char *)&acceldata.y); - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_ACCEL_Z, (char *)&acceldata.z); - mpu9150_client_data->accel_data.x = acceldata.x; - mpu9150_client_data->accel_data.y = acceldata.y; - mpu9150_client_data->accel_data.z = acceldata.z; - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_GYRO_X, (char *)&gyrodata.x); - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_GYRO_Y, (char *)&gyrodata.y); - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_GYRO_Z, (char *)&gyrodata.z); - mpu9150_client_data->gyro_data.rx = gyrodata.x; - mpu9150_client_data->gyro_data.ry = gyrodata.y; - mpu9150_client_data->gyro_data.rz = gyrodata.z; - - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_LOCALX, (char *)&fusiondata.localX); - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_LOCALY, (char *)&fusiondata.localY); - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_LOCALZ, (char *)&fusiondata.localZ); - mpu9150_client_data->accel_local_data.lx = fusiondata.localX; - mpu9150_client_data->accel_local_data.ly = fusiondata.localY; - mpu9150_client_data->accel_local_data.lz = fusiondata.localZ; - - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_WORLDX, (char *)&fusiondata.worldX); - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_WORLDY, (char *)&fusiondata.worldY); - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_WORLDZ, (char *)&fusiondata.worldZ); - mpu9150_client_data->accel_world_data.wx = fusiondata.worldX; - mpu9150_client_data->accel_world_data.wy = fusiondata.worldY; - mpu9150_client_data->accel_world_data.wz = fusiondata.worldZ; - - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_EULERPITCH, - (char *)&fusiondata.eulerPitch); - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_EULERROLL, - (char *)&fusiondata.eulerRoll); - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_EULERYAW, - (char *)&fusiondata.eulerYaw); - mpu9150_client_data->euler_data.pitch = fusiondata.eulerPitch; - mpu9150_client_data->euler_data.roll = fusiondata.eulerRoll; - mpu9150_client_data->euler_data.yaw = fusiondata.eulerYaw; - - - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_HEADING, - (char *)&fusiondata.heading); - m4sensorhub_reg_read(mpu9150_client_data->m4sensorhub, - M4SH_REG_FUSION_HEADING_ACCURACY, - (char *)&fusiondata.heading_accuracy); - mpu9150_client_data->heading_data.heading = fusiondata.heading; - mpu9150_client_data->heading_data.accuracy = - fusiondata.heading_accuracy; - - break; default: break; } @@ -384,15 +251,6 @@ static void m4_handle_mpu9150_compass_irq(enum m4sensorhub_irqs int_event, m4_report_mpu9150_inputevent(mpu9150_client_data, TYPE_COMPASS); } -static void m4_handle_mpu9150_fusion_irq(enum m4sensorhub_irqs int_event, - void *mpu9150_data) -{ - struct mpu9150_client *mpu9150_client_data = mpu9150_data; - - m4_read_mpu9150_data(mpu9150_client_data, TYPE_FUSION); - m4_report_mpu9150_inputevent(mpu9150_client_data, TYPE_FUSION); -} - static ssize_t m4_mpu9150_write_accel_setdelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -514,125 +372,6 @@ static const struct attribute_group mpu9150_control_group = { .attrs = mpu9150_control_attributes, }; #ifdef MPU9150_DEBUG -static ssize_t m4_mpu9150_local_x(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mpu9150_client *mpu9150_client_data = platform_get_drvdata(pdev); - - KDEBUG(M4SH_DEBUG, "%s : x_local = %d\n", - __func__, mpu9150_client_data->accel_local_data.lx); - return sprintf(buf, "%d\n", mpu9150_client_data->accel_local_data.lx); -} - -static ssize_t m4_mpu9150_local_y(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mpu9150_client *mpu9150_client_data = platform_get_drvdata(pdev); - - KDEBUG(M4SH_DEBUG, "%s : y_local = %d\n", - __func__, mpu9150_client_data->accel_local_data.ly); - return sprintf(buf, "%d\n", mpu9150_client_data->accel_local_data.ly); -} - -static ssize_t m4_mpu9150_local_z(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mpu9150_client *mpu9150_client_data = platform_get_drvdata(pdev); - - KDEBUG(M4SH_DEBUG, "%s : z_local = %d\n", - __func__, mpu9150_client_data->accel_local_data.lz); - return sprintf(buf, "%d\n", mpu9150_client_data->accel_local_data.lz); -} -static ssize_t m4_mpu9150_world_x(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mpu9150_client *mpu9150_client_data = platform_get_drvdata(pdev); - - KDEBUG(M4SH_DEBUG, "%s : x_world = %d\n", - __func__, mpu9150_client_data->accel_world_data.wx); - return sprintf(buf, "%d\n", mpu9150_client_data->accel_world_data.wx); -} - -static ssize_t m4_mpu9150_world_y(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mpu9150_client *mpu9150_client_data = platform_get_drvdata(pdev); - - KDEBUG(M4SH_DEBUG, "%s : y_world = %d\n", - __func__, mpu9150_client_data->accel_world_data.wy); - return sprintf(buf, "%d\n", mpu9150_client_data->accel_world_data.wy); -} - -static ssize_t m4_mpu9150_world_z(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mpu9150_client *mpu9150_client_data = platform_get_drvdata(pdev); - - KDEBUG(M4SH_DEBUG, "%s : z_world = %d\n", - __func__, mpu9150_client_data->accel_world_data.wz); - return sprintf(buf, "%d\n", mpu9150_client_data->accel_world_data.wz); -} -static ssize_t m4_mpu9150_pitch(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mpu9150_client *mpu9150_client_data = platform_get_drvdata(pdev); - - KDEBUG(M4SH_DEBUG, "%s : pitch = %d\n", - __func__, mpu9150_client_data->euler_data.pitch); - return sprintf(buf, "%d\n", mpu9150_client_data->euler_data.pitch); -} - -static ssize_t m4_mpu9150_roll(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mpu9150_client *mpu9150_client_data = platform_get_drvdata(pdev); - - KDEBUG(M4SH_DEBUG, "%s : roll = %d\n", - __func__, mpu9150_client_data->euler_data.roll); - return sprintf(buf, "%d\n", mpu9150_client_data->euler_data.roll); -} - -static ssize_t m4_mpu9150_yaw(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mpu9150_client *mpu9150_client_data = platform_get_drvdata(pdev); - - KDEBUG(M4SH_DEBUG, "%s : yaw = %d\n", - __func__, mpu9150_client_data->euler_data.yaw); - return sprintf(buf, "%d\n", mpu9150_client_data->euler_data.yaw); -} - -static ssize_t m4_mpu9150_heading(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mpu9150_client *mpu9150_client_data = platform_get_drvdata(pdev); - - KDEBUG(M4SH_DEBUG, "%s : heading = %d\n", - __func__, mpu9150_client_data->heading_data.heading); - return sprintf(buf, "%d\n", mpu9150_client_data->heading_data.heading); -} - -static ssize_t m4_mpu9150_heading_acc(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct mpu9150_client *mpu9150_client_data = platform_get_drvdata(pdev); - - KDEBUG(M4SH_DEBUG, "%s : heading_acc = %d\n", - __func__, mpu9150_client_data->heading_data.accuracy); - return sprintf(buf, "%d\n", mpu9150_client_data->heading_data.accuracy); -} - static ssize_t m4_mpu9150_x(struct device *dev, struct device_attribute *attr, char *buf) { @@ -743,17 +482,6 @@ static ssize_t m4_mpu9150_rz(struct device *dev, } -static DEVICE_ATTR(x_local, 0444, m4_mpu9150_local_x, NULL); -static DEVICE_ATTR(y_local, 0444, m4_mpu9150_local_y, NULL); -static DEVICE_ATTR(z_local, 0444, m4_mpu9150_local_z, NULL); -static DEVICE_ATTR(x_world, 0444, m4_mpu9150_world_x, NULL); -static DEVICE_ATTR(y_world, 0444, m4_mpu9150_world_y, NULL); -static DEVICE_ATTR(z_world, 0444, m4_mpu9150_world_z, NULL); -static DEVICE_ATTR(pitch, 0444, m4_mpu9150_pitch, NULL); -static DEVICE_ATTR(roll, 0444, m4_mpu9150_roll, NULL); -static DEVICE_ATTR(yaw, 0444, m4_mpu9150_yaw, NULL); -static DEVICE_ATTR(heading, 0444, m4_mpu9150_heading, NULL); -static DEVICE_ATTR(heading_acc, 0444, m4_mpu9150_heading_acc, NULL); static DEVICE_ATTR(raw_x, 0444, m4_mpu9150_x, NULL); static DEVICE_ATTR(raw_y, 0444, m4_mpu9150_y, NULL); static DEVICE_ATTR(raw_z, 0444, m4_mpu9150_z, NULL); @@ -766,17 +494,6 @@ static DEVICE_ATTR(ry, 0444, m4_mpu9150_ry, NULL); static DEVICE_ATTR(rz, 0444, m4_mpu9150_rz, NULL); static struct attribute *mpu9150_attributes[] = { - &dev_attr_x_local.attr, - &dev_attr_y_local.attr, - &dev_attr_z_local.attr, - &dev_attr_x_world.attr, - &dev_attr_y_world.attr, - &dev_attr_z_world.attr, - &dev_attr_pitch.attr, - &dev_attr_roll.attr, - &dev_attr_yaw.attr, - &dev_attr_heading.attr, - &dev_attr_heading_acc.attr, &dev_attr_raw_x.attr, &dev_attr_raw_y.attr, &dev_attr_raw_z.attr, @@ -838,20 +555,8 @@ static int mpu9150_irq_init(struct mpu9150_client *mpu9150_client_data) M4SH_IRQ_COMPASS_DATA_READY, ret); goto unregister_accel_irq; } - ret = m4sensorhub_irq_register(mpu9150_client_data->m4sensorhub, - M4SH_IRQ_FUSION_DATA_READY, - m4_handle_mpu9150_fusion_irq, - mpu9150_client_data); - if (ret < 0) { - KDEBUG(M4SH_ERROR, "Error registering int %d (%d)\n", - M4SH_IRQ_FUSION_DATA_READY, ret); - goto unregister_compass_irq; - } return ret; -unregister_compass_irq: - m4sensorhub_irq_unregister(mpu9150_client_data->m4sensorhub, - M4SH_IRQ_COMPASS_DATA_READY); unregister_accel_irq: m4sensorhub_irq_unregister(mpu9150_client_data->m4sensorhub, M4SH_IRQ_ACCEL_DATA_READY); @@ -864,8 +569,6 @@ unregister_gyro_irq: static void mpu9150_irq_deinit(struct mpu9150_client *mpu9150_client_data) { m4sensorhub_irq_unregister(mpu9150_client_data->m4sensorhub, - M4SH_IRQ_FUSION_DATA_READY); - m4sensorhub_irq_unregister(mpu9150_client_data->m4sensorhub, M4SH_IRQ_COMPASS_DATA_READY); m4sensorhub_irq_unregister(mpu9150_client_data->m4sensorhub, M4SH_IRQ_ACCEL_DATA_READY); @@ -934,24 +637,6 @@ static int mpu9150_irq_enable_disable(struct mpu9150_client *mpu9150_client_data mpu9150_client_data->m4sensorhub, M4SH_IRQ_COMPASS_DATA_READY); break; - case TYPE_FUSION: - irq_status = m4sensorhub_irq_enable_get( - mpu9150_client_data->m4sensorhub, - M4SH_IRQ_FUSION_DATA_READY); - if (flag && (!irq_status)) { - ret = m4sensorhub_irq_enable( - mpu9150_client_data->m4sensorhub, - M4SH_IRQ_FUSION_DATA_READY); - if (ret < 0) { - KDEBUG(M4SH_ERROR, "Error enabling int %d (%d)\n", - M4SH_IRQ_FUSION_DATA_READY, ret); - return ret; - } - } else if ((!flag) && irq_status) - m4sensorhub_irq_disable( - mpu9150_client_data->m4sensorhub, - M4SH_IRQ_FUSION_DATA_READY); - break; default: ret = -EINVAL; break; @@ -1007,23 +692,9 @@ static int mpu9150_client_probe(struct platform_device *pdev) set_bit(REL_X, mpu9150_client_data->input_dev->relbit); set_bit(REL_Y, mpu9150_client_data->input_dev->relbit); set_bit(REL_Z, mpu9150_client_data->input_dev->relbit); - set_bit(REL_GX, mpu9150_client_data->input_dev->relbit); - set_bit(REL_GY, mpu9150_client_data->input_dev->relbit); - set_bit(REL_GZ, mpu9150_client_data->input_dev->relbit); - set_bit(REL_LX, mpu9150_client_data->input_dev->relbit); - set_bit(REL_LY, mpu9150_client_data->input_dev->relbit); - set_bit(REL_LZ, mpu9150_client_data->input_dev->relbit); - set_bit(REL_WX, mpu9150_client_data->input_dev->relbit); - set_bit(REL_WY, mpu9150_client_data->input_dev->relbit); - set_bit(REL_WZ, mpu9150_client_data->input_dev->relbit); - set_bit(REL_ROLL, mpu9150_client_data->input_dev->relbit); - set_bit(REL_PITCH, mpu9150_client_data->input_dev->relbit); - set_bit(REL_YAW, mpu9150_client_data->input_dev->relbit); set_bit(REL_RX, mpu9150_client_data->input_dev->relbit); set_bit(REL_RY, mpu9150_client_data->input_dev->relbit); set_bit(REL_RZ, mpu9150_client_data->input_dev->relbit); - set_bit(REL_HEADING, mpu9150_client_data->input_dev->relbit); - set_bit(REL_HEADING_ACCURACY, mpu9150_client_data->input_dev->relbit); if (input_register_device(mpu9150_client_data->input_dev)) { KDEBUG(M4SH_ERROR, "%s: input device register failed\n", @@ -1096,26 +767,6 @@ static int __exit mpu9150_client_remove(struct platform_device *pdev) return 0; } -static void mpu9150_client_shutdown(struct platform_device *pdev) -{ - return; -} -#ifdef CONFIG_PM -static int mpu9150_client_suspend(struct platform_device *pdev, - pm_message_t message) -{ - return 0; -} - -static int mpu9150_client_resume(struct platform_device *pdev) -{ - return 0; -} -#else -#define mpu9150_client_suspend NULL -#define mpu9150_client_resume NULL -#endif - static struct of_device_id m4mpu9150_match_tbl[] = { { .compatible = "mot,m4mpu9150" }, {}, @@ -1124,9 +775,9 @@ static struct of_device_id m4mpu9150_match_tbl[] = { static struct platform_driver mpu9150_client_driver = { .probe = mpu9150_client_probe, .remove = __exit_p(mpu9150_client_remove), - .shutdown = mpu9150_client_shutdown, - .suspend = mpu9150_client_suspend, - .resume = mpu9150_client_resume, + .shutdown = NULL, + .suspend = NULL, + .resume = NULL, .driver = { .name = MPU9150_CLIENT_DRIVER_NAME, .owner = THIS_MODULE, diff --git a/drivers/misc/m4sensorhub_passive.c b/drivers/misc/m4sensorhub_passive.c index 6e40b5c4c1d..555a6d007d3 100644 --- a/drivers/misc/m4sensorhub_passive.c +++ b/drivers/misc/m4sensorhub_passive.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Motorola, Inc. + * Copyright (C) 2012-2014 Motorola, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,320 +23,462 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/miscdevice.h> #include <linux/platform_device.h> -#include <linux/proc_fs.h> -#include <linux/input.h> +#include <linux/fs.h> #include <linux/m4sensorhub.h> -#include <linux/m4sensorhub/MemMapPassive.h> -#include <linux/m4sensorhub_client_ioctl.h> -#include <linux/uaccess.h> #include <linux/slab.h> +#include <linux/iio/iio.h> +#include <linux/iio/types.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/events.h> +#include <linux/iio/buffer.h> +#include <linux/iio/kfifo_buf.h> +#include <linux/iio/m4sensorhub/m4sensorhub_passive.h> -#define PASSIVE_CLIENT_DRIVER_NAME "m4sensorhub_passive" +#define m4pas_err(format, args...) KDEBUG(M4SH_ERROR, format, ## args) -struct m4_passive_data { - u32 mets; - u32 steps; - u32 floorsClimbed; - u32 timestamp; -}; +#define M4PAS_IRQ_ENABLED_BIT 0 + +struct m4pas_driver_data { + struct platform_device *pdev; + struct m4sensorhub_data *m4; + struct mutex mutex; /* controls driver entry points */ -struct passive_client { - struct m4sensorhub_data *m4sensorhub; - struct input_dev *input_dev; + struct m4sensorhub_passive_iio_data iiodat[M4PAS_NUM_PASSIVE_BUFFERS]; + int16_t samplerate; + uint16_t status; }; -static struct passive_client *misc_passive_data; -static struct m4_passive_data pdata_buffer[MAX_PASSIVE_BUFFERS] = {}; -static int passive_client_open(struct inode *inode, struct file *file) +static void m4pas_isr(enum m4sensorhub_irqs int_event, void *handle) { int err = 0; + struct iio_dev *iio = handle; + struct m4pas_driver_data *dd = iio_priv(iio); + int size = 0; + uint32_t passive_timestamp[M4PAS_NUM_PASSIVE_BUFFERS]; + uint32_t steps[M4PAS_NUM_PASSIVE_BUFFERS]; + uint32_t mets[M4PAS_NUM_PASSIVE_BUFFERS]; + uint32_t floors_climbed[M4PAS_NUM_PASSIVE_BUFFERS]; + int i = 0; + + mutex_lock(&(dd->mutex)); - err = nonseekable_open(inode, file); + size = m4sensorhub_reg_getsize(dd->m4, M4SH_REG_PASSIVE_TIMESTAMP); + err = m4sensorhub_reg_read(dd->m4, M4SH_REG_PASSIVE_TIMESTAMP, + (char *)&(passive_timestamp)); if (err < 0) { - KDEBUG(M4SH_ERROR, "%s failed\n", __func__); - return err; + m4pas_err("%s: Failed to read passive_timestamp data.\n", + __func__); + goto m4pas_isr_fail; + } else if (err != size) { + m4pas_err("%s: Read %d bytes instead of %d for %s.\n", + __func__, err, size, "passive_timestamp"); + err = -EBADE; + goto m4pas_isr_fail; } - file->private_data = misc_passive_data; - return 0; -} + size = m4sensorhub_reg_getsize(dd->m4, M4SH_REG_PASSIVE_STEPS); + err = m4sensorhub_reg_read(dd->m4, M4SH_REG_PASSIVE_STEPS, + (char *)&(steps)); + if (err < 0) { + m4pas_err("%s: Failed to read steps data.\n", __func__); + goto m4pas_isr_fail; + } else if (err != size) { + m4pas_err("%s: Read %d bytes instead of %d for %s.\n", + __func__, err, size, "steps"); + err = -EBADE; + goto m4pas_isr_fail; + } -static int passive_client_close(struct inode *inode, struct file *file) -{ - KDEBUG(M4SH_DEBUG, "passive_client in %s\n", __func__); - return 0; + size = m4sensorhub_reg_getsize(dd->m4, M4SH_REG_PASSIVE_METS); + err = m4sensorhub_reg_read(dd->m4, M4SH_REG_PASSIVE_METS, + (char *)&(mets)); + if (err < 0) { + m4pas_err("%s: Failed to read mets data.\n", __func__); + goto m4pas_isr_fail; + } else if (err != size) { + m4pas_err("%s: Read %d bytes instead of %d for %s.\n", + __func__, err, size, "mets"); + err = -EBADE; + goto m4pas_isr_fail; + } + + size = m4sensorhub_reg_getsize(dd->m4, M4SH_REG_PASSIVE_FLOORSCLIMBED); + err = m4sensorhub_reg_read(dd->m4, M4SH_REG_PASSIVE_FLOORSCLIMBED, + (char *)&(floors_climbed)); + if (err < 0) { + m4pas_err("%s: Failed to read floors_climbed data.\n", + __func__); + goto m4pas_isr_fail; + } else if (err != size) { + m4pas_err("%s: Read %d bytes instead of %d for %s.\n", + __func__, err, size, "floors_climbed"); + err = -EBADE; + goto m4pas_isr_fail; + } + + for (i = 0; i < M4PAS_NUM_PASSIVE_BUFFERS; i++) { + dd->iiodat[i].passive_timestamp = passive_timestamp[i]; + dd->iiodat[i].steps = steps[i]; + dd->iiodat[i].mets = mets[i]; + dd->iiodat[i].floors_climbed = floors_climbed[i]; + dd->iiodat[i].timestamp = iio_get_time_ns(); + iio_push_to_buffers(iio, (unsigned char *)&(dd->iiodat[i])); + } + +m4pas_isr_fail: + if (err < 0) + m4pas_err("%s: Failed with error code %d.\n", __func__, err); + + mutex_unlock(&(dd->mutex)); + + return; } -static void m4_report_passive_inputevent( - struct passive_client *passive_client_data) +static int m4pas_set_samplerate(struct iio_dev *iio, int16_t rate) { - int i; - for (i = 0; i < MAX_PASSIVE_BUFFERS; i++) { - input_event(passive_client_data->input_dev, EV_MSC, - MSC_PASSIVE_STEPS, - pdata_buffer[i].steps); - input_event(passive_client_data->input_dev, EV_MSC, - MSC_PASSIVE_METS, - pdata_buffer[i].mets); - input_event(passive_client_data->input_dev, EV_MSC, - MSC_PASSIVE_TIMESTAMP, - pdata_buffer[i].timestamp); - input_event(passive_client_data->input_dev, EV_MSC, - MSC_PASSIVE_FLOORSCLIMBED, - pdata_buffer[i].floorsClimbed); - input_sync(passive_client_data->input_dev); + int err = 0; + struct m4pas_driver_data *dd = iio_priv(iio); + + /* + * Currently, there is no concept of setting a sample rate for this + * sensor, so this function only enables/disables interrupt reporting. + */ + dd->samplerate = rate; + + if (rate >= 0) { + /* Enable the IRQ if necessary */ + if (!(dd->status & (1 << M4PAS_IRQ_ENABLED_BIT))) { + err = m4sensorhub_irq_enable(dd->m4, + M4SH_IRQ_PASSIVE_BUFFER_FULL); + if (err < 0) { + m4pas_err("%s: Failed to enable irq.\n", + __func__); + goto m4pas_set_samplerate_fail; + } + dd->status = dd->status | (1 << M4PAS_IRQ_ENABLED_BIT); + } + } else { + /* Disable the IRQ if necessary */ + if (dd->status & (1 << M4PAS_IRQ_ENABLED_BIT)) { + err = m4sensorhub_irq_disable(dd->m4, + M4SH_IRQ_PASSIVE_BUFFER_FULL); + if (err < 0) { + m4pas_err("%s: Failed to disable irq.\n", + __func__); + goto m4pas_set_samplerate_fail; + } + dd->status = dd->status & ~(1 << M4PAS_IRQ_ENABLED_BIT); + } } + +m4pas_set_samplerate_fail: + return err; } +static ssize_t m4pas_setrate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iio_dev *iio = platform_get_drvdata(pdev); + struct m4pas_driver_data *dd = iio_priv(iio); + ssize_t size = 0; -static void m4_read_passive_data(struct passive_client *passive_client_data) + mutex_lock(&(dd->mutex)); + size = snprintf(buf, PAGE_SIZE, "Current rate: %hd\n", dd->samplerate); + mutex_unlock(&(dd->mutex)); + return size; +} +static ssize_t m4pas_setrate_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) { - int i; - u32 steps[MAX_PASSIVE_BUFFERS] = {0}; - u32 mets[MAX_PASSIVE_BUFFERS] = {0}; - u32 timestamp[12] = {0}; - u32 floorsClimbed[MAX_PASSIVE_BUFFERS] = {0}; + int err = 0; + struct platform_device *pdev = to_platform_device(dev); + struct iio_dev *iio = platform_get_drvdata(pdev); + struct m4pas_driver_data *dd = iio_priv(iio); + int value = 0; - /*read all buffers of steps*/ - m4sensorhub_reg_read(passive_client_data->m4sensorhub, - M4SH_REG_PASSIVE_STEPS, - (char *)&steps); - m4sensorhub_reg_read(passive_client_data->m4sensorhub, - M4SH_REG_PASSIVE_METS, - (char *)&mets); - m4sensorhub_reg_read(passive_client_data->m4sensorhub, - M4SH_REG_PASSIVE_TIMESTAMP, - (char *)×tamp); - m4sensorhub_reg_read(passive_client_data->m4sensorhub, - M4SH_REG_PASSIVE_FLOORSCLIMBED, - (char *)&floorsClimbed); - for (i = 0; i < MAX_PASSIVE_BUFFERS; i++) { - pdata_buffer[i].steps = steps[i]; - pdata_buffer[i].mets = mets[i]; - pdata_buffer[i].timestamp = timestamp[i]; - pdata_buffer[i].floorsClimbed = floorsClimbed[i]; - KDEBUG(M4SH_DEBUG, "steps = %u, mets = %u, timestamp = %u,\ - floorsClimbed = %u", pdata_buffer[i].steps, - pdata_buffer[i].mets, pdata_buffer[i].timestamp, - pdata_buffer[i].floorsClimbed); + mutex_lock(&(dd->mutex)); + + err = kstrtoint(buf, 10, &value); + if (err < 0) { + m4pas_err("%s: Failed to convert value.\n", __func__); + goto m4pas_enable_store_exit; } -} -static void m4_handle_passive_irq(enum m4sensorhub_irqs int_event, - void *passive_data) -{ - struct passive_client *passive_client_data = passive_data; + if ((value < -1) || (value > 32767)) { + m4pas_err("%s: Invalid samplerate %d passed.\n", + __func__, value); + err = -EINVAL; + goto m4pas_enable_store_exit; + } - m4_read_passive_data(passive_client_data); - m4_report_passive_inputevent(passive_client_data); + err = m4pas_set_samplerate(iio, value); + if (err < 0) { + m4pas_err("%s: Failed to set sample rate.\n", __func__); + goto m4pas_enable_store_exit; + } + +m4pas_enable_store_exit: + if (err < 0) { + m4pas_err("%s: Failed with error code %d.\n", __func__, err); + size = err; + } + + mutex_unlock(&(dd->mutex)); + + return size; } +static IIO_DEVICE_ATTR(setrate, S_IRUSR | S_IWUSR, + m4pas_setrate_show, m4pas_setrate_store, 0); -/* - * Handle commands from user-space. - */ -static long passive_client_ioctl(struct file *filp, - unsigned int cmd, unsigned long arg) +static ssize_t m4pas_iiodata_show(struct device *dev, + struct device_attribute *attr, char *buf) { - int ret = 0; - struct passive_client *passive_client_data = filp->private_data; + struct platform_device *pdev = to_platform_device(dev); + struct iio_dev *iio = platform_get_drvdata(pdev); + struct m4pas_driver_data *dd = iio_priv(iio); + ssize_t size = 0; + int i = 0; - switch (cmd) { - case M4_SENSOR_IOCTL_GET_PASSIVE_DATA: - m4_read_passive_data(passive_client_data); - m4_report_passive_inputevent(passive_client_data); - break; - default: - KDEBUG(M4SH_ERROR, "Invalid IOCTL Command in %s\n", __func__); - ret = -EINVAL; + mutex_lock(&(dd->mutex)); + buf[0] = '\0'; /* Start with NULL terminator for concatenation */; + for (i = 0; i < M4PAS_NUM_PASSIVE_BUFFERS; i++) { + size = snprintf(buf, PAGE_SIZE, + "%s%s%d\n%s%u\n%s%u\n%s%u\n%s%u\n", + buf, "Buffer ", i, + "passive_timestamp: ", dd->iiodat[i].passive_timestamp, + "steps: ", dd->iiodat[i].steps, + "mets: ", dd->iiodat[i].mets, + "floors_climbed: ", dd->iiodat[i].floors_climbed); } - return ret; + mutex_unlock(&(dd->mutex)); + return size; } +static IIO_DEVICE_ATTR(iiodata, S_IRUGO, m4pas_iiodata_show, NULL, 0); -static const struct file_operations passive_client_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = passive_client_ioctl, - .open = passive_client_open, - .release = passive_client_close, +static struct attribute *m4pas_iio_attributes[] = { + &iio_dev_attr_setrate.dev_attr.attr, + &iio_dev_attr_iiodata.dev_attr.attr, + NULL, }; -static struct miscdevice passive_client_miscdrv = { - .minor = MISC_DYNAMIC_MINOR, - .name = PASSIVE_CLIENT_DRIVER_NAME, - .fops = &passive_client_fops, +static const struct attribute_group m4pas_iio_attr_group = { + .attrs = m4pas_iio_attributes, }; -static int passive_driver_init(struct init_calldata *p_arg) -{ - int ret; - struct m4sensorhub_data *m4sensorhub = p_arg->p_m4sensorhub_data; - ret = m4sensorhub_irq_register(m4sensorhub, - M4SH_IRQ_PASSIVE_BUFFER_FULL, - m4_handle_passive_irq, - misc_passive_data); - if (ret < 0) { - KDEBUG(M4SH_ERROR, "Error registering int %d (%d)\n", - M4SH_IRQ_PASSIVE_BUFFER_FULL, ret); - return ret; - } - ret = m4sensorhub_irq_enable(m4sensorhub, - M4SH_IRQ_PASSIVE_BUFFER_FULL); - if (ret < 0) { - KDEBUG(M4SH_ERROR, "Error enabling int %d (%d)\n", - M4SH_IRQ_PASSIVE_BUFFER_FULL, ret); - goto exit; - } +static const struct iio_info m4pas_iio_info = { + .driver_module = THIS_MODULE, + .attrs = &m4pas_iio_attr_group, +}; - return ret; -exit: - m4sensorhub_irq_unregister(m4sensorhub, M4SH_IRQ_PASSIVE_BUFFER_FULL); - return ret; -} +static const struct iio_chan_spec m4pas_iio_channels[] = { + { + .type = IIO_PASSIVE, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = M4PAS_DATA_STRUCT_SIZE_BITS, + .storagebits = M4PAS_DATA_STRUCT_SIZE_BITS, + .shift = 0, + }, + }, +}; -static int passive_client_probe(struct platform_device *pdev) +static void m4pas_remove_iiodev(struct iio_dev *iio) { - int ret = -1; - struct passive_client *passive_client_data; - struct m4sensorhub_data *m4sensorhub = m4sensorhub_client_get_drvdata(); + struct m4pas_driver_data *dd = iio_priv(iio); - if (!m4sensorhub) - return -EFAULT; + /* Remember, only call when dd->mutex is locked */ + iio_kfifo_free(iio->buffer); + iio_buffer_unregister(iio); + iio_device_unregister(iio); + mutex_destroy(&(dd->mutex)); + iio_device_free(iio); /* dd is freed here */ + return; +} - passive_client_data = kzalloc(sizeof(*passive_client_data), - GFP_KERNEL); - if (!passive_client_data) - return -ENOMEM; +static int m4pas_create_iiodev(struct iio_dev *iio) +{ + int err = 0; + struct m4pas_driver_data *dd = iio_priv(iio); - passive_client_data->m4sensorhub = m4sensorhub; - platform_set_drvdata(pdev, passive_client_data); + iio->name = M4PAS_DRIVER_NAME; + iio->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_HARDWARE; + iio->num_channels = 1; + iio->info = &m4pas_iio_info; + iio->channels = m4pas_iio_channels; - passive_client_data->input_dev = input_allocate_device(); - if (!passive_client_data->input_dev) { - ret = -ENOMEM; - KDEBUG(M4SH_ERROR, "%s: input device allocate failed: %d\n", - __func__, ret); - goto free_mem; + iio->buffer = iio_kfifo_allocate(iio); + if (iio->buffer == NULL) { + m4pas_err("%s: Failed to allocate IIO buffer.\n", __func__); + err = -ENOMEM; + goto m4pas_create_iiodev_kfifo_fail; } - passive_client_data->input_dev->name = PASSIVE_CLIENT_DRIVER_NAME; - set_bit(EV_MSC, passive_client_data->input_dev->evbit); - set_bit(MSC_PASSIVE_STEPS, passive_client_data->input_dev->mscbit); - set_bit(MSC_PASSIVE_METS, passive_client_data->input_dev->mscbit); - set_bit(MSC_PASSIVE_TIMESTAMP, passive_client_data->input_dev->mscbit); - set_bit(MSC_PASSIVE_FLOORSCLIMBED, - passive_client_data->input_dev->mscbit); - if (input_register_device(passive_client_data->input_dev)) { - KDEBUG(M4SH_ERROR, "%s: input device register failed\n", - __func__); - input_free_device(passive_client_data->input_dev); - goto free_mem; + iio->buffer->scan_timestamp = true; + iio->buffer->access->set_bytes_per_datum(iio->buffer, + sizeof(dd->iiodat)); + err = iio_buffer_register(iio, iio->channels, iio->num_channels); + if (err < 0) { + m4pas_err("%s: Failed to register IIO buffer.\n", __func__); + goto m4pas_create_iiodev_buffer_fail; } - ret = misc_register(&passive_client_miscdrv); - if (ret < 0) { - KDEBUG(M4SH_ERROR, "Error registering %s driver\n", __func__); - goto unregister_input_device; - } - misc_passive_data = passive_client_data; - ret = m4sensorhub_register_initcall(passive_driver_init, - passive_client_data); - if (ret < 0) { - KDEBUG(M4SH_ERROR, "Unable to register init function" - "for passive client = %d\n", ret); - goto unregister_misc_device; + err = iio_device_register(iio); + if (err < 0) { + m4pas_err("%s: Failed to register IIO device.\n", __func__); + goto m4pas_create_iiodev_iioreg_fail; } - KDEBUG(M4SH_INFO, "Initialized %s driver\n", __func__); - return 0; -unregister_misc_device: - misc_passive_data = NULL; - misc_deregister(&passive_client_miscdrv); -unregister_input_device: - input_unregister_device(passive_client_data->input_dev); -free_mem: - platform_set_drvdata(pdev, NULL); - passive_client_data->m4sensorhub = NULL; - kfree(passive_client_data); - passive_client_data = NULL; - return ret; + goto m4pas_create_iiodev_exit; + +m4pas_create_iiodev_iioreg_fail: + iio_buffer_unregister(iio); +m4pas_create_iiodev_buffer_fail: + iio_kfifo_free(iio->buffer); +m4pas_create_iiodev_kfifo_fail: + iio_device_free(iio); /* dd is freed here */ +m4pas_create_iiodev_exit: + return err; } -static int __exit passive_client_remove(struct platform_device *pdev) +static int m4pas_driver_init(struct init_calldata *p_arg) { - struct passive_client *passive_client_data = - platform_get_drvdata(pdev); + struct iio_dev *iio = p_arg->p_data; + struct m4pas_driver_data *dd = iio_priv(iio); + int err = 0; - m4sensorhub_irq_disable(passive_client_data->m4sensorhub, - M4SH_IRQ_PASSIVE_BUFFER_FULL); - m4sensorhub_irq_unregister(passive_client_data->m4sensorhub, - M4SH_IRQ_PASSIVE_BUFFER_FULL); - m4sensorhub_unregister_initcall(passive_driver_init); + mutex_lock(&(dd->mutex)); - misc_passive_data = NULL; - misc_deregister(&passive_client_miscdrv); - input_unregister_device(passive_client_data->input_dev); - platform_set_drvdata(pdev, NULL); - passive_client_data->m4sensorhub = NULL; - kfree(passive_client_data); - passive_client_data = NULL; - return 0; -} + dd->m4 = p_arg->p_m4sensorhub_data; + if (dd->m4 == NULL) { + m4pas_err("%s: M4 sensor data is NULL.\n", __func__); + err = -ENODATA; + goto m4pas_driver_init_fail; + } -static void passive_client_shutdown(struct platform_device *pdev) -{ - return; + err = m4sensorhub_irq_register(dd->m4, + M4SH_IRQ_PASSIVE_BUFFER_FULL, m4pas_isr, iio); + if (err < 0) { + m4pas_err("%s: Failed to register M4 IRQ.\n", __func__); + goto m4pas_driver_init_fail; + } + + goto m4pas_driver_init_exit; + +m4pas_driver_init_fail: + m4pas_err("%s: Init failed with error code %d.\n", __func__, err); +m4pas_driver_init_exit: + mutex_unlock(&(dd->mutex)); + return err; } -#ifdef CONFIG_PM -static int passive_client_suspend(struct platform_device *pdev, - pm_message_t message) + +static int m4pas_probe(struct platform_device *pdev) { + struct m4pas_driver_data *dd = NULL; + struct iio_dev *iio = NULL; + int err = 0; + + iio = iio_device_alloc(sizeof(dd)); + if (iio == NULL) { + m4pas_err("%s: Failed to allocate IIO data.\n", __func__); + err = -ENOMEM; + goto m4pas_probe_fail_noiio; + } + + dd = iio_priv(iio); + dd->pdev = pdev; + mutex_init(&(dd->mutex)); + platform_set_drvdata(pdev, iio); + dd->samplerate = -1; /* We always start disabled */ + + err = m4pas_create_iiodev(iio); /* iio and dd are freed on fail */ + if (err < 0) { + m4pas_err("%s: Failed to create IIO device.\n", __func__); + goto m4pas_probe_fail_noiio; + } + + err = m4sensorhub_register_initcall(m4pas_driver_init, iio); + if (err < 0) { + m4pas_err("%s: Failed to register initcall.\n", __func__); + goto m4pas_probe_fail; + } + return 0; + +m4pas_probe_fail: + mutex_destroy(&(dd->mutex)); + m4pas_remove_iiodev(iio); /* iio and dd are freed here */ +m4pas_probe_fail_noiio: + m4pas_err("%s: Probe failed with error code %d.\n", __func__, err); + return err; } -static int passive_client_resume(struct platform_device *pdev) +static int __exit m4pas_remove(struct platform_device *pdev) { + struct iio_dev *iio = platform_get_drvdata(pdev); + struct m4pas_driver_data *dd = NULL; + + if (iio == NULL) + goto m4pas_remove_exit; + + dd = iio_priv(iio); + if (dd == NULL) + goto m4pas_remove_exit; + + mutex_lock(&(dd->mutex)); + if (dd->status & (1 << M4PAS_IRQ_ENABLED_BIT)) { + m4sensorhub_irq_disable(dd->m4, + M4SH_IRQ_PASSIVE_BUFFER_FULL); + dd->status = dd->status & ~(1 << M4PAS_IRQ_ENABLED_BIT); + } + m4sensorhub_irq_unregister(dd->m4, + M4SH_IRQ_PASSIVE_BUFFER_FULL); + m4sensorhub_unregister_initcall(m4pas_driver_init); + mutex_destroy(&(dd->mutex)); + m4pas_remove_iiodev(iio); /* dd is freed here */ + +m4pas_remove_exit: return 0; } -#else -#define passive_client_suspend NULL -#define passive_client_resume NULL -#endif static struct of_device_id m4passive_match_tbl[] = { { .compatible = "mot,m4passive" }, {}, }; -static struct platform_driver passive_client_driver = { - .probe = passive_client_probe, - .remove = __exit_p(passive_client_remove), - .shutdown = passive_client_shutdown, - .suspend = passive_client_suspend, - .resume = passive_client_resume, +static struct platform_driver m4pas_driver = { + .probe = m4pas_probe, + .remove = __exit_p(m4pas_remove), + .shutdown = NULL, + .suspend = NULL, + .resume = NULL, .driver = { - .name = PASSIVE_CLIENT_DRIVER_NAME, + .name = M4PAS_DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = of_match_ptr(m4passive_match_tbl), }, }; -static int __init passive_client_init(void) +static int __init m4pas_init(void) { - return platform_driver_register(&passive_client_driver); + return platform_driver_register(&m4pas_driver); } -static void __exit passive_client_exit(void) +static void __exit m4pas_exit(void) { - platform_driver_unregister(&passive_client_driver); + platform_driver_unregister(&m4pas_driver); } -module_init(passive_client_init); -module_exit(passive_client_exit); +module_init(m4pas_init); +module_exit(m4pas_exit); -MODULE_ALIAS("platform:passive_client"); -MODULE_DESCRIPTION("M4 Sensor Hub Passive mode client driver"); +MODULE_ALIAS("platform:m4pas"); +MODULE_DESCRIPTION("M4 Sensor Hub Passive client driver"); MODULE_AUTHOR("Motorola"); MODULE_LICENSE("GPL"); - diff --git a/drivers/misc/m4sensorhub_pedometer.c b/drivers/misc/m4sensorhub_pedometer.c index 15e8850bf91..ce4d161c4d8 100644 --- a/drivers/misc/m4sensorhub_pedometer.c +++ b/drivers/misc/m4sensorhub_pedometer.c @@ -395,17 +395,11 @@ static int m4ped_driver_init(struct init_calldata *p_arg) goto m4ped_driver_init_fail; } - err = m4ped_create_iiodev(iio); - if (err < 0) { - m4ped_err("%s: Failed to create IIO device.\n", __func__); - goto m4ped_driver_init_fail; - } - err = m4sensorhub_irq_register(dd->m4, M4SH_IRQ_PEDOMETER_DATA_READY, m4ped_isr, iio); if (err < 0) { m4ped_err("%s: Failed to register M4 PED IRQ.\n", __func__); - goto m4ped_driver_init_irq_ped_fail; + goto m4ped_driver_init_fail; } err = m4sensorhub_irq_register(dd->m4, @@ -415,24 +409,14 @@ static int m4ped_driver_init(struct init_calldata *p_arg) goto m4ped_driver_init_irq_act_fail; } - /* - * NOTE: We're intentionally unlocking here instead of - * at function end (after error cases). The reason - * is that the mutex ceases to exist because IIO is - * freed, so we would cause a panic putting the unlock - * after m4ped_driver_init_exit. - */ - mutex_unlock(&(dd->mutex)); - goto m4ped_driver_init_exit; m4ped_driver_init_irq_act_fail: m4sensorhub_irq_unregister(dd->m4, M4SH_IRQ_PEDOMETER_DATA_READY); -m4ped_driver_init_irq_ped_fail: - m4ped_remove_iiodev(iio); /* dd is freed here */ m4ped_driver_init_fail: m4ped_err("%s: Init failed with error code %d.\n", __func__, err); m4ped_driver_init_exit: + mutex_unlock(&(dd->mutex)); return err; } @@ -455,6 +439,12 @@ static int m4ped_probe(struct platform_device *pdev) platform_set_drvdata(pdev, iio); dd->samplerate = -1; /* We always start disabled */ + err = m4ped_create_iiodev(iio); /* iio and dd are freed on fail */ + if (err < 0) { + m4ped_err("%s: Failed to create IIO device.\n", __func__); + goto m4ped_probe_fail_noiio; + } + err = m4sensorhub_register_initcall(m4ped_driver_init, iio); if (err < 0) { m4ped_err("%s: Failed to register initcall.\n", __func__); @@ -465,7 +455,7 @@ static int m4ped_probe(struct platform_device *pdev) m4ped_probe_fail: mutex_destroy(&(dd->mutex)); - iio_device_free(iio); /* dd is freed here */ + m4ped_remove_iiodev(iio); /* iio and dd are freed here */ m4ped_probe_fail_noiio: m4ped_err("%s: Probe failed with error code %d.\n", __func__, err); return err; diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c index 787f71b6705..8e7c13fd161 100644 --- a/drivers/staging/iio/Documentation/iio_event_monitor.c +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -50,6 +50,8 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_PRESSURE] = "pressure", [IIO_HEARTRATE] = "heartrate", [IIO_PEDOMETER] = "pedometer", + [IIO_PASSIVE] = "passive", + [IIO_GESTURE] = "gesture", }; static const char * const iio_ev_type_text[] = { diff --git a/include/linux/iio/m4sensorhub/m4sensorhub_gesture.h b/include/linux/iio/m4sensorhub/m4sensorhub_gesture.h new file mode 100644 index 00000000000..232d5e602ee --- /dev/null +++ b/include/linux/iio/m4sensorhub/m4sensorhub_gesture.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Adds ability to program periodic interrupts from user space that + * can wake the phone out of low power modes. + * + */ + +#ifndef _M4SENSORHUB_GESTURE_IIO_H +#define _M4SENSORHUB_GESTURE_IIO_H + +struct m4sensorhub_gesture_iio_data { + uint8_t gesture_type; + uint8_t gesture_confidence; + int8_t gesture_value; + long long timestamp; +} __packed; + +#define M4GES_DRIVER_NAME "m4sensorhub_gesture" +#define M4GES_DATA_STRUCT_SIZE_BITS \ + (sizeof(struct m4sensorhub_gesture_iio_data) * 8) + +#endif /* _M4SENSORHUB_GESTURE_IIO_H */ diff --git a/include/linux/iio/m4sensorhub/m4sensorhub_passive.h b/include/linux/iio/m4sensorhub/m4sensorhub_passive.h new file mode 100644 index 00000000000..52b3fce375a --- /dev/null +++ b/include/linux/iio/m4sensorhub/m4sensorhub_passive.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2014 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Adds ability to program periodic interrupts from user space that + * can wake the phone out of low power modes. + * + */ + +#ifndef _M4SENSORHUB_PASSIVE_IIO_H +#define _M4SENSORHUB_PASSIVE_IIO_H + +struct m4sensorhub_passive_iio_data { + uint32_t passive_timestamp; + uint32_t steps; + uint32_t mets; + uint32_t floors_climbed; + long long timestamp; +} __packed; + +#define M4PAS_DRIVER_NAME "m4sensorhub_passive" +#define M4PAS_DATA_STRUCT_SIZE_BITS \ + (sizeof(struct m4sensorhub_passive_iio_data) * 8) + +#define M4PAS_NUM_PASSIVE_BUFFERS 12 + +#endif /* _M4SENSORHUB_PASSIVE_IIO_H */ diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 0c301484f2f..1b7ddde46ae 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -31,6 +31,8 @@ enum iio_chan_type { IIO_PRESSURE, IIO_HEARTRATE, IIO_PEDOMETER, + IIO_PASSIVE, + IIO_GESTURE, }; enum iio_modifier { diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 0fcaac18208..b508016fb76 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -276,10 +276,9 @@ struct pcmcia_device_id { #define INPUT_DEVICE_ID_EV_MAX 0x1f #define INPUT_DEVICE_ID_KEY_MIN_INTERESTING 0x71 #define INPUT_DEVICE_ID_KEY_MAX 0x2ff -#define INPUT_DEVICE_ID_REL_MAX 0x1f -/* TEMP!!! TODO : Check IKXCLOCK-100*/ +#define INPUT_DEVICE_ID_REL_MAX 0x0f #define INPUT_DEVICE_ID_ABS_MAX 0x3f -#define INPUT_DEVICE_ID_MSC_MAX 0x1f +#define INPUT_DEVICE_ID_MSC_MAX 0x07 #define INPUT_DEVICE_ID_LED_MAX 0x0f #define INPUT_DEVICE_ID_SND_MAX 0x07 #define INPUT_DEVICE_ID_FF_MAX 0x7f diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h index b3618eb001e..8fef2bcd7d8 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -773,22 +773,7 @@ struct input_keymap_entry { #define REL_DIAL 0x07 #define REL_WHEEL 0x08 #define REL_MISC 0x09 -#define REL_ROLL 0x0a -#define REL_PITCH 0x0b -#define REL_YAW 0x0c -#define REL_LX 0x0d -#define REL_LY 0x0e -#define REL_LZ 0x0f -#define REL_WX 0x10 -#define REL_WY 0x11 -#define REL_WZ 0x12 -#define REL_GX 0x13 -#define REL_GY 0x14 -#define REL_GZ 0x15 -#define REL_HEADING 0x16 -#define REL_HEADING_ACCURACY 0x17 -#define REL_ACTIVITY_LEVEL 0x18 -#define REL_MAX 0x1f +#define REL_MAX 0x0f #define REL_CNT (REL_MAX+1) /* @@ -841,10 +826,6 @@ struct input_keymap_entry { #define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */ -/* MSP (sensor) related events */ -#define ABS_TILTSCROLL 0x3e - -/* TODO TEMP !!! CHeck IKXCLOCK-100 */ #define ABS_MAX 0x3f #define ABS_CNT (ABS_MAX+1) @@ -882,21 +863,7 @@ struct input_keymap_entry { #define MSC_RAW 0x03 #define MSC_SCAN 0x04 #define MSC_TIMESTAMP 0x05 -#define MSC_GESTURE1 0x06 -#define MSC_GESTURE2 0x07 -#define MSC_GESTURE3 0x08 -#define MSC_GESTURE_CONFIDENCE1 0x09 -#define MSC_GESTURE_CONFIDENCE2 0x0a -#define MSC_GESTURE_CONFIDENCE3 0x0b -#define MSC_GESTURE_VALUE1 0x0c -#define MSC_GESTURE_VALUE2 0x0d -#define MSC_GESTURE_VALUE3 0x0e -#define MSC_PASSIVE_STEPS 0x0f -#define MSC_PASSIVE_METS 0x10 -#define MSC_PASSIVE_TIMESTAMP 0x11 -#define MSC_PASSIVE_FLOORSCLIMBED 0x12 - -#define MSC_MAX 0x1f +#define MSC_MAX 0x07 #define MSC_CNT (MSC_MAX+1) /* |