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 /drivers/misc/m4sensorhub_gesture.c | |
| 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>
Diffstat (limited to 'drivers/misc/m4sensorhub_gesture.c')
| -rw-r--r-- | drivers/misc/m4sensorhub_gesture.c | 649 |
1 files changed, 333 insertions, 316 deletions
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"); - |