summaryrefslogtreecommitdiff
path: root/drivers/misc/m4sensorhub_gesture.c
diff options
context:
space:
mode:
authorDoug Zobel <dzobel1@motorola.com>2013-11-15 14:29:07 -0600
committerJames Wylder <jwylder@motorola.com>2014-03-05 17:46:52 -0600
commitd2a782003a6047da120a33e6f8ee6fd33bb825d6 (patch)
tree8d20bd4ecda62a06e98993c4108456bc1acb0d0b /drivers/misc/m4sensorhub_gesture.c
parent32fd2d36d2464056d4522a9c02797b7c2b2e884f (diff)
downloadolio-linux-3.10-d2a782003a6047da120a33e6f8ee6fd33bb825d6.tar.xz
olio-linux-3.10-d2a782003a6047da120a33e6f8ee6fd33bb825d6.zip
CW integration and minnow bringup
* create minnow machine type * create Android makefile * add pre-commit syntax check * enable -Werror * Add drivers: CPCAP, TPS65xxx, m4sensorhub, atmxt, lm3535, usb gadget, minnow display, TI 12xx wireless Change-Id: I7962f5e1256715f2452aed5a62a4f2f2383d5046
Diffstat (limited to 'drivers/misc/m4sensorhub_gesture.c')
-rw-r--r--drivers/misc/m4sensorhub_gesture.c415
1 files changed, 415 insertions, 0 deletions
diff --git a/drivers/misc/m4sensorhub_gesture.c b/drivers/misc/m4sensorhub_gesture.c
new file mode 100644
index 00000000000..b067be71d24
--- /dev/null
+++ b/drivers/misc/m4sensorhub_gesture.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2012 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.
+ *
+ */
+
+#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/m4sensorhub.h>
+#include <linux/m4sensorhub_client_ioctl.h>
+#include <linux/uaccess.h>
+#include <linux/m4sensorhub/MemMapGesture.h>
+#include <linux/slab.h>
+
+#define GESTURE_CLIENT_DRIVER_NAME "m4sensorhub_gesture"
+
+struct gesture_client {
+ struct m4sensorhub_data *m4sensorhub;
+ struct input_dev *input_dev;
+ struct memMapGesture gesture_data;
+};
+
+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;
+ }
+}
+
+static struct gesture_client *misc_gesture_data;
+
+static int gesture_client_open(struct inode *inode, struct file *file)
+{
+ int err = 0;
+
+ err = nonseekable_open(inode, file);
+ if (err < 0) {
+ KDEBUG(M4SH_ERROR, "%s failed\n", __func__);
+ return err;
+ }
+ file->private_data = misc_gesture_data;
+
+ return 0;
+}
+
+static int gesture_client_close(struct inode *inode, struct file *file)
+{
+ KDEBUG(M4SH_DEBUG, "gesture_client in %s\n", __func__);
+ return 0;
+}
+
+static char m4_read_gesture_data(struct gesture_client *gesture_client_data)
+{
+ int ret;
+ struct memMapGesture *gdata = &(gesture_client_data->gesture_data);
+
+ ret = m4sensorhub_reg_read_n(gesture_client_data->m4sensorhub,
+ M4SH_REG_GESTURE_VERSION,
+ (char *)gdata,
+ sizeof(gesture_client_data->gesture_data));
+
+ if (ret != sizeof(gesture_client_data->gesture_data))
+ goto ERR;
+
+ 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;
+}
+
+static void m4_handle_gesture_irq(enum m4sensorhub_irqs int_event,
+ void *gesture_data)
+{
+ 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);
+
+ if (m4_read_gesture_data(gesture_client_data) < 0) {
+ KDEBUG(M4SH_ERROR, "m4_read_gesture_data returned \
+ error %s\n", __func__);
+ return;
+ }
+
+ if (read_gesture_value(gesture_client_data, &value, GESTURE_TILT_SCROLL)) {
+ input_event(gesture_client_data->input_dev, EV_ABS,
+ ABS_TILTSCROLL, value);
+ } 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);
+ }
+ }
+
+ 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);
+
+ input_sync(gesture_client_data->input_dev);
+
+}
+
+/*
+ * Handle commands from user-space.
+ */
+static long gesture_client_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+ void __user *argp = (void __user *)arg;
+ struct gesture_client *gesture_client_data = filp->private_data;
+ unsigned char byte;
+
+ 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;
+ }
+ return ret;
+}
+
+static ssize_t m4_gesture_status(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);
+
+ 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);
+}
+
+static DEVICE_ATTR(gesture_status, 0444, m4_gesture_status, NULL);
+
+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 struct miscdevice gesture_client_miscdrv = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = GESTURE_CLIENT_DRIVER_NAME,
+ .fops = &gesture_client_fops,
+};
+
+static int gesture_client_probe(struct platform_device *pdev)
+{
+ int ret = -1;
+ struct gesture_client *gesture_client_data;
+ struct m4sensorhub_data *m4sensorhub = m4sensorhub_client_get_drvdata();
+
+ if (!m4sensorhub)
+ return -EFAULT;
+
+ gesture_client_data = kzalloc(sizeof(*gesture_client_data),
+ GFP_KERNEL);
+ if (!gesture_client_data)
+ return -ENOMEM;
+
+ gesture_client_data->m4sensorhub = m4sensorhub;
+ platform_set_drvdata(pdev, gesture_client_data);
+
+ 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;
+ }
+
+ 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);
+
+ set_bit(EV_ABS, gesture_client_data->input_dev->evbit);
+ set_bit(ABS_TILTSCROLL, gesture_client_data->input_dev->absbit);
+
+ 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;
+ }
+
+ 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_irq_register(m4sensorhub, M4SH_IRQ_GESTURE_DETECTED,
+ m4_handle_gesture_irq,
+ gesture_client_data);
+ if (ret < 0) {
+ KDEBUG(M4SH_ERROR, "Error registering int %d (%d)\n",
+ M4SH_IRQ_GESTURE_DETECTED, ret);
+ goto unregister_misc_device;
+ }
+ 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 unregister_display_gesture_irq;
+ }
+ if (device_create_file(&pdev->dev, &dev_attr_gesture_status)) {
+ KDEBUG(M4SH_ERROR, "Error creating %s sys entry\n", __func__);
+ ret = -1;
+ goto disable_display_gesture_irq;
+ }
+ KDEBUG(M4SH_INFO, "Initialized %s driver\n", __func__);
+ return 0;
+
+disable_display_gesture_irq:
+ m4sensorhub_irq_disable(m4sensorhub, M4SH_IRQ_GESTURE_DETECTED);
+unregister_display_gesture_irq:
+ m4sensorhub_irq_unregister(m4sensorhub, M4SH_IRQ_GESTURE_DETECTED);
+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;
+}
+
+static int __exit gesture_client_remove(struct platform_device *pdev)
+{
+ struct gesture_client *gesture_client_data =
+ platform_get_drvdata(pdev);
+
+ 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);
+ 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;
+}
+
+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;
+}
+
+static int gesture_client_resume(struct platform_device *pdev)
+{
+ 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,
+ .driver = {
+ .name = GESTURE_CLIENT_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(m4gesture_match_tbl),
+ },
+};
+
+static int __init gesture_client_init(void)
+{
+ return platform_driver_register(&gesture_client_driver);
+}
+
+static void __exit gesture_client_exit(void)
+{
+ platform_driver_unregister(&gesture_client_driver);
+}
+
+module_init(gesture_client_init);
+module_exit(gesture_client_exit);
+
+MODULE_ALIAS("platform:gesture_client");
+MODULE_DESCRIPTION("M4 Sensor Hub Gesture client driver");
+MODULE_AUTHOR("Motorola");
+MODULE_LICENSE("GPL");
+