diff options
| -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)  /*  |