msm: camera: Add support for gesture driver
Added gesture driver code. Gesture node is a subdevice to
server node.
Change-Id: I488da3dbdb502a2f78b0cd5269dd113c472ee377
Signed-off-by: Sunid Wilson <sunidw@codeaurora.org>
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index ebfed6c..b60f99f 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -13,6 +13,7 @@
EXTRA_CFLAGS += -Idrivers/media/video/msm/actuators
obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o msm_mctl_pp.o
obj-$(CONFIG_MSM_CAMERA) += io/ eeprom/ sensors/ actuators/ csi/
+ obj-$(CONFIG_MSM_CAMERA) += msm_gesture.o
else
obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
endif
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 1220b6e..034cbc5 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -45,6 +45,10 @@
module_param(msm_camera_v4l2_nr, uint, 0644);
MODULE_PARM_DESC(msm_camera_v4l2_nr, "videoX start number, -1 is autodetect");
+static long msm_server_send_v4l2_evt(void *evt);
+static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd,
+ unsigned int notification, void *arg);
+
static void msm_queue_init(struct msm_device_queue *queue, const char *name)
{
D("%s\n", __func__);
@@ -178,10 +182,16 @@
return -EINVAL;
}
+ D("%s qid %d evtid %d %d\n", __func__, command->queue_idx,
+ command->evt_id,
+ g_server_dev.server_queue[command->queue_idx].evt_id);
g_server_dev.server_queue[command->queue_idx].ctrl = command;
if (command->evt_id !=
g_server_dev.server_queue[command->queue_idx].evt_id) {
- pr_err("Invalid event id from userspace\n");
+ pr_err("%s Invalid event id from userspace cmd id %d %d qid %d\n",
+ __func__, command->evt_id,
+ g_server_dev.server_queue[command->queue_idx].evt_id,
+ command->queue_idx);
return -EINVAL;
}
@@ -241,6 +251,8 @@
mutex_lock(&server_dev->server_queue_lock);
if (++server_dev->server_evt_id == 0)
server_dev->server_evt_id++;
+ D("%s qid %d evtid %d\n", __func__, out->queue_idx,
+ server_dev->server_evt_id);
server_dev->server_queue[out->queue_idx].evt_id =
server_dev->server_evt_id;
@@ -317,7 +329,7 @@
{
int rc = 0;
struct msm_ctrl_cmd ctrlcmd;
- D("%s\n", __func__);
+ D("%s qid %d\n", __func__, pcam->server_queue_idx);
ctrlcmd.type = MSM_V4L2_OPEN;
ctrlcmd.timeout_ms = 10000;
ctrlcmd.length = strnlen(g_server_dev.config_info.config_dev_name[0],
@@ -337,7 +349,7 @@
{
int rc = 0;
struct msm_ctrl_cmd ctrlcmd;
- D("%s\n", __func__);
+ D("%s qid %d\n", __func__, pcam->server_queue_idx);
ctrlcmd.type = MSM_V4L2_CLOSE;
ctrlcmd.timeout_ms = 10000;
ctrlcmd.length = strnlen(g_server_dev.config_info.config_dev_name[0],
@@ -1432,7 +1444,7 @@
sub->type++;
D("sub->type while = 0x%x\n", sub->type);
} while (sub->type !=
- V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_MAX);
+ V4L2_EVENT_PRIVATE_START + MSM_SVR_RESP_MAX);
} else {
D("sub->type not V4L2_EVENT_ALL = 0x%x\n", sub->type);
rc = v4l2_event_subscribe(fh, sub);
@@ -1555,6 +1567,150 @@
msm_mctl_free(pcam);
return rc;
}
+
+int msm_server_open_client(int *p_qidx)
+{
+ int rc = 0;
+ int server_q_idx = 0;
+ struct msm_cam_server_queue *queue = NULL;
+
+ mutex_lock(&g_server_dev.server_lock);
+ server_q_idx = msm_find_free_queue();
+ if (server_q_idx < 0) {
+ mutex_unlock(&g_server_dev.server_lock);
+ return server_q_idx;
+ }
+
+ *p_qidx = server_q_idx;
+ queue = &g_server_dev.server_queue[server_q_idx];
+ queue->ctrl = NULL;
+ queue->ctrl_data = kzalloc(sizeof(uint8_t) *
+ max_control_command_size, GFP_KERNEL);
+ msm_queue_init(&queue->ctrl_q, "control");
+ msm_queue_init(&queue->eventData_q, "eventdata");
+ queue->queue_active = 1;
+ mutex_unlock(&g_server_dev.server_lock);
+ return rc;
+}
+
+int msm_server_send_ctrl(struct msm_ctrl_cmd *out,
+ int ctrl_id)
+{
+ int rc = 0;
+ void *value;
+ struct msm_queue_cmd *rcmd;
+ struct msm_queue_cmd *event_qcmd;
+ struct msm_ctrl_cmd *ctrlcmd;
+ struct msm_cam_server_dev *server_dev = &g_server_dev;
+ struct msm_device_queue *queue =
+ &server_dev->server_queue[out->queue_idx].ctrl_q;
+
+ struct v4l2_event v4l2_evt;
+ struct msm_isp_event_ctrl *isp_event;
+ isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_KERNEL);
+ if (!isp_event) {
+ pr_err("%s Insufficient memory. return", __func__);
+ return -ENOMEM;
+ }
+ event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
+ if (!event_qcmd) {
+ pr_err("%s Insufficient memory. return", __func__);
+ kfree(isp_event);
+ return -ENOMEM;
+ }
+
+ D("%s\n", __func__);
+ mutex_lock(&server_dev->server_queue_lock);
+ if (++server_dev->server_evt_id == 0)
+ server_dev->server_evt_id++;
+
+ D("%s qid %d evtid %d\n", __func__, out->queue_idx,
+ server_dev->server_evt_id);
+ server_dev->server_queue[out->queue_idx].evt_id =
+ server_dev->server_evt_id;
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START + ctrl_id;
+ v4l2_evt.u.data[0] = out->queue_idx;
+ /* setup event object to transfer the command; */
+ isp_event->resptype = MSM_CAM_RESP_V4L2;
+ isp_event->isp_data.ctrl = *out;
+ isp_event->isp_data.ctrl.evt_id = server_dev->server_evt_id;
+
+ atomic_set(&event_qcmd->on_heap, 1);
+ event_qcmd->command = isp_event;
+
+ msm_enqueue(&server_dev->server_queue[out->queue_idx].eventData_q,
+ &event_qcmd->list_eventdata);
+
+ /* now send command to config thread in userspace,
+ * and wait for results */
+ v4l2_event_queue(server_dev->server_command_queue.pvdev,
+ &v4l2_evt);
+ D("%s v4l2_event_queue: type = 0x%x\n", __func__, v4l2_evt.type);
+ mutex_unlock(&server_dev->server_queue_lock);
+
+ /* wait for config return status */
+ D("Waiting for config status\n");
+ rc = wait_event_interruptible_timeout(queue->wait,
+ !list_empty_careful(&queue->list),
+ msecs_to_jiffies(out->timeout_ms));
+ D("Waiting is over for config status\n");
+ if (list_empty_careful(&queue->list)) {
+ if (!rc)
+ rc = -ETIMEDOUT;
+ if (rc < 0) {
+ kfree(isp_event);
+ pr_err("%s: wait_event error %d\n", __func__, rc);
+ return rc;
+ }
+ }
+
+ rcmd = msm_dequeue(queue, list_control);
+ BUG_ON(!rcmd);
+ D("%s Finished servicing ioctl\n", __func__);
+
+ ctrlcmd = (struct msm_ctrl_cmd *)(rcmd->command);
+ value = out->value;
+ if (ctrlcmd->length > 0)
+ memcpy(value, ctrlcmd->value, ctrlcmd->length);
+
+ memcpy(out, ctrlcmd, sizeof(struct msm_ctrl_cmd));
+ out->value = value;
+
+ kfree(ctrlcmd);
+ server_dev->server_queue[out->queue_idx].ctrl = NULL;
+
+ free_qcmd(rcmd);
+ kfree(isp_event);
+ D("%s: rc %d\n", __func__, rc);
+ /* rc is the time elapsed. */
+ if (rc >= 0) {
+ /* TODO: Refactor msm_ctrl_cmd::status field */
+ if (out->status == 0)
+ rc = -1;
+ else if (out->status == 1 || out->status == 4)
+ rc = 0;
+ else
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+int msm_server_close_client(int idx)
+{
+ int rc = 0;
+ struct msm_cam_server_queue *queue = NULL;
+ mutex_lock(&g_server_dev.server_lock);
+ queue = &g_server_dev.server_queue[idx];
+ queue->queue_active = 0;
+ kfree(queue->ctrl);
+ queue->ctrl = NULL;
+ kfree(queue->ctrl_data);
+ queue->ctrl_data = NULL;
+ msm_queue_drain(&queue->ctrl_q, list_control);
+ msm_drain_eventq(&queue->eventData_q);
+ mutex_unlock(&g_server_dev.server_lock);
+ return rc;
+}
/* v4l2_file_operations */
static int msm_open(struct file *f)
{
@@ -1610,7 +1766,10 @@
pcam_inst->my_index,
pcam->vnode_id, pcam->use_count);
pcam->use_count++;
+ D("%s use_count %d\n", __func__, pcam->use_count);
if (pcam->use_count == 1) {
+ struct msm_cam_server_queue *queue;
+ int ges_evt = MSM_V4L2_GES_CAM_OPEN;
pcam->server_queue_idx = server_q_idx;
queue = &g_server_dev.server_queue[server_q_idx];
queue->ctrl = NULL;
@@ -1620,6 +1779,10 @@
msm_queue_init(&queue->eventData_q, "eventdata");
queue->queue_active = 1;
+ pr_err("%s send gesture evt\n", __func__);
+ msm_cam_server_subdev_notify(g_server_dev.gesture_device,
+ NOTIFY_GESTURE_CAM_EVT, &ges_evt);
+
rc = msm_cam_server_open_session(&g_server_dev, pcam);
if (rc < 0) {
pr_err("%s: cam_server_open_session failed %d\n",
@@ -1713,6 +1876,74 @@
}
mutex_unlock(&pcam->vid_lock);
kfree(pcam_inst);
+ pr_err("%s: error end", __func__);
+ return rc;
+}
+
+int msm_cam_server_close_mctl_session(struct msm_cam_v4l2_device *pcam)
+{
+ int rc = 0;
+ struct msm_cam_media_controller *pmctl = NULL;
+
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ if (!pmctl) {
+ D("%s: invalid handle\n", __func__);
+ return -ENODEV;
+ }
+
+ if (pmctl->mctl_release) {
+ rc = pmctl->mctl_release(pmctl);
+ if (rc < 0)
+ pr_err("mctl_release fails %d\n", rc);
+ }
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ kref_put(&pmctl->refcount, msm_release_ion_client);
+#endif
+
+ rc = msm_cam_server_close_session(&g_server_dev, pcam);
+ if (rc < 0)
+ pr_err("msm_cam_server_close_session fails %d\n", rc);
+
+ return rc;
+}
+
+int msm_cam_server_open_mctl_session(struct msm_cam_v4l2_device *pcam,
+ int *p_active)
+{
+ int rc = 0;
+ struct msm_cam_media_controller *pmctl = NULL;
+ D("%s: %p", __func__, g_server_dev.pcam_active);
+ *p_active = 0;
+ if (g_server_dev.pcam_active) {
+ D("%s: Active camera present return", __func__);
+ return 0;
+ }
+ rc = msm_cam_server_open_session(&g_server_dev, pcam);
+ if (rc < 0) {
+ pr_err("%s: cam_server_open_session failed %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ /* Should be set to sensor ops if any but right now its OK!! */
+ if (!pmctl->mctl_open) {
+ D("%s: media contoller is not inited\n",
+ __func__);
+ rc = -ENODEV;
+ return rc;
+ }
+
+ D("%s: call mctl_open\n", __func__);
+ rc = pmctl->mctl_open(pmctl, MSM_APPS_ID_V4L2);
+
+ if (rc < 0) {
+ pr_err("%s: HW open failed rc = 0x%x\n", __func__, rc);
+ return rc;
+ }
+ pmctl->pcam_ptr = pcam;
+ *p_active = 1;
return rc;
}
@@ -1839,6 +2070,7 @@
f->private_data = NULL;
if (pcam->use_count == 0) {
+ int ges_evt = MSM_V4L2_GES_CAM_CLOSE;
if (g_server_dev.use_count > 0) {
rc = msm_send_close_server(pcam);
if (rc < 0)
@@ -1866,6 +2098,9 @@
if (g_server_dev.use_count == 0)
mutex_unlock(&g_server_dev.server_lock);
+
+ msm_cam_server_subdev_notify(g_server_dev.gesture_device,
+ NOTIFY_GESTURE_CAM_EVT, &ges_evt);
}
mutex_unlock(&pcam->vid_lock);
return rc;
@@ -2080,6 +2315,11 @@
rc = 0;
break;
}
+
+ case MSM_CAM_IOCTL_SEND_EVENT:
+ rc = msm_server_send_v4l2_evt(arg);
+ break;
+
default:
pr_err("%s: Invalid IOCTL = %d", __func__, cmd);
break;
@@ -2143,6 +2383,29 @@
return 0;
}
+static long msm_server_send_v4l2_evt(void *evt)
+{
+ struct v4l2_event *v4l2_ev = (struct v4l2_event *)evt;
+ int rc = 0;
+
+ if (NULL == evt) {
+ pr_err("%s: evt is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ D("%s: evt type 0x%x\n", __func__, v4l2_ev->type);
+ if ((v4l2_ev->type >= MSM_GES_APP_EVT_MIN) &&
+ (v4l2_ev->type < MSM_GES_APP_EVT_MAX)) {
+ msm_cam_server_subdev_notify(g_server_dev.gesture_device,
+ NOTIFY_GESTURE_EVT, v4l2_ev);
+ } else {
+ pr_err("%s: Invalid evt %d\n", __func__, v4l2_ev->type);
+ rc = -EINVAL;
+ }
+ D("%s: end\n", __func__);
+
+ return rc;
+}
static long msm_v4l2_evt_notify(struct msm_cam_media_controller *mctl,
unsigned int cmd, unsigned long evt)
@@ -2635,6 +2898,14 @@
rc = v4l2_subdev_call(g_server_dev.csic_device[csid_core],
core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
break;
+ case NOTIFY_GESTURE_EVT:
+ rc = v4l2_subdev_call(g_server_dev.gesture_device,
+ core, ioctl, VIDIOC_MSM_GESTURE_EVT, arg);
+ break;
+ case NOTIFY_GESTURE_CAM_EVT:
+ rc = v4l2_subdev_call(g_server_dev.gesture_device,
+ core, ioctl, VIDIOC_MSM_GESTURE_CAM_EVT, arg);
+ break;
default:
break;
}
@@ -2674,6 +2945,8 @@
if (index >= MAX_NUM_AXI_DEV)
return -EINVAL;
g_server_dev.axi_device[index] = sd;
+ } else if (sdev_type == GESTURE_DEV) {
+ g_server_dev.gesture_device = sd;
}
err = v4l2_device_register_subdev(&g_server_dev.v4l2_dev, sd);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 04e224c..6798cbb 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -32,6 +32,7 @@
#include <mach/camera.h>
#include <media/msm_isp.h>
#include <linux/ion.h>
+#include <media/msm_gestures.h>
#define MSM_V4L2_DIMENSION_SIZE 96
#define MAX_DEV_NAME_LEN 50
@@ -69,6 +70,7 @@
SENSOR_DEV,
ACTUATOR_DEV,
EEPROM_DEV,
+ GESTURE_DEV,
};
/* msm queue management APIs*/
@@ -150,6 +152,8 @@
NOTIFY_VFE_BUF_FREE_EVT, /* arg = msm_camera_csic_params */
NOTIFY_VFE_IRQ,
NOTIFY_AXI_IRQ,
+ NOTIFY_GESTURE_EVT, /* arg = v4l2_event */
+ NOTIFY_GESTURE_CAM_EVT, /* arg = int */
NOTIFY_INVALID
};
@@ -330,6 +334,8 @@
struct msm_cam_v4l2_dev_inst *dev_inst[MSM_DEV_INST_MAX];
struct msm_cam_v4l2_dev_inst *dev_inst_map[MSM_MAX_IMG_MODE];
struct mutex dev_lock;
+ int active;
+ int use_count;
};
/* abstract camera device for each sensor successfully probed*/
@@ -384,7 +390,8 @@
struct msm_mem_map_info mem_map;
};
-#define MAX_NUM_ACTIVE_CAMERA 2
+/* 2 for camera, 1 for gesture */
+#define MAX_NUM_ACTIVE_CAMERA 3
struct msm_cam_server_queue {
uint32_t queue_active;
@@ -444,6 +451,7 @@
struct v4l2_subdev *vfe_device[MAX_NUM_VFE_DEV];
struct v4l2_subdev *axi_device[MAX_NUM_AXI_DEV];
struct v4l2_subdev *vpe_device[MAX_NUM_VPE_DEV];
+ struct v4l2_subdev *gesture_device;
};
/* camera server related functions */
@@ -566,6 +574,12 @@
uint32_t msm_camera_get_mctl_handle(void);
struct msm_cam_media_controller *msm_camera_get_mctl(uint32_t handle);
void msm_camera_free_mctl(uint32_t handle);
+int msm_server_open_client(int *p_qidx);
+int msm_server_send_ctrl(struct msm_ctrl_cmd *out, int ctrl_id);
+int msm_server_close_client(int idx);
+int msm_cam_server_open_mctl_session(struct msm_cam_v4l2_device *pcam,
+ int *p_active);
+int msm_cam_server_close_mctl_session(struct msm_cam_v4l2_device *pcam);
#endif /* __KERNEL__ */
#endif /* _MSM_H */
diff --git a/drivers/media/video/msm/msm_gesture.c b/drivers/media/video/msm/msm_gesture.c
new file mode 100644
index 0000000..654594d
--- /dev/null
+++ b/drivers/media/video/msm/msm_gesture.c
@@ -0,0 +1,497 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <mach/camera.h>
+#include <media/v4l2-subdev.h>
+#include "msm.h"
+#include <media/msm_camera.h>
+#include <media/msm_gestures.h>
+#include <media/v4l2-ctrls.h>
+
+#ifdef CONFIG_MSM_CAMERA_DEBUG
+#define D(fmt, args...) pr_debug("msm_gesture: " fmt, ##args)
+#else
+#define D(fmt, args...) do {} while (0)
+#endif
+
+struct msm_gesture_ctrl {
+ int queue_id;
+ atomic_t active;
+ struct v4l2_ctrl_handler ctrl_handler;
+ int num_ctrls;
+ struct v4l2_fh *p_eventHandle;
+ struct v4l2_subdev *sd;
+ struct msm_ges_evt event;
+ int camera_opened;
+};
+
+static struct msm_gesture_ctrl g_gesture_ctrl;
+
+int msm_gesture_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ D("%s\n", __func__);
+ if (sub->type == V4L2_EVENT_ALL)
+ sub->type = MSM_GES_APP_NOTIFY_EVENT;
+ return v4l2_event_subscribe(fh, sub);
+}
+
+static int msm_gesture_send_ctrl(struct msm_gesture_ctrl *p_gesture_ctrl,
+ int type, void *value, int length, uint32_t timeout)
+{
+ int rc = 0;
+ struct msm_ctrl_cmd ctrlcmd;
+ D("%s qid %d\n", __func__, p_gesture_ctrl->queue_id);
+ ctrlcmd.type = type;
+ ctrlcmd.timeout_ms = timeout;
+ ctrlcmd.length = length;
+ ctrlcmd.value = value;
+ ctrlcmd.vnode_id = 0;
+ ctrlcmd.queue_idx = p_gesture_ctrl->queue_id;
+ ctrlcmd.config_ident = 0;
+
+ rc = msm_server_send_ctrl(&ctrlcmd, MSM_GES_RESP_V4L2);
+ return rc;
+}
+
+static int msm_gesture_proc_ctrl_cmd(struct msm_gesture_ctrl *p_gesture_ctrl,
+ struct v4l2_control *ctrl)
+{
+ int rc = 0;
+ struct msm_ctrl_cmd *tmp_cmd = NULL;
+ uint8_t *ctrl_data = NULL;
+ void __user *uptr_cmd;
+ void __user *uptr_value;
+ uint32_t cmd_len = sizeof(struct msm_ctrl_cmd);
+ uint32_t value_len;
+
+ tmp_cmd = (struct msm_ctrl_cmd *)ctrl->value;
+ uptr_cmd = (void __user *)ctrl->value;
+ uptr_value = (void __user *)tmp_cmd->value;
+ value_len = tmp_cmd->length;
+
+ D("%s: cmd type = %d, up1=0x%x, ulen1=%d, up2=0x%x, ulen2=%d\n",
+ __func__, tmp_cmd->type, (uint32_t)uptr_cmd, cmd_len,
+ (uint32_t)uptr_value, tmp_cmd->length);
+
+ ctrl_data = kzalloc(value_len + cmd_len, GFP_KERNEL);
+ if (ctrl_data == 0) {
+ pr_err("%s could not allocate memory\n", __func__);
+ rc = -ENOMEM;
+ goto end;
+ }
+ tmp_cmd = (struct msm_ctrl_cmd *)ctrl_data;
+ if (copy_from_user((void *)ctrl_data, uptr_cmd,
+ cmd_len)) {
+ pr_err("%s: copy_from_user failed.\n", __func__);
+ rc = -EINVAL;
+ goto end;
+ }
+ tmp_cmd->value = (void *)(ctrl_data + cmd_len);
+ if (uptr_value && tmp_cmd->length > 0) {
+ if (copy_from_user((void *)tmp_cmd->value, uptr_value,
+ value_len)) {
+ pr_err("%s: copy_from_user failed, size=%d\n",
+ __func__, value_len);
+ rc = -EINVAL;
+ goto end;
+ }
+ } else
+ tmp_cmd->value = NULL;
+
+ /* send command to config thread in usersspace, and get return value */
+ rc = msm_server_send_ctrl((struct msm_ctrl_cmd *)ctrl_data,
+ MSM_GES_RESP_V4L2);
+ D("%s: msm_server_control rc=%d\n", __func__, rc);
+ if (rc == 0) {
+ if (uptr_value && tmp_cmd->length > 0 &&
+ copy_to_user((void __user *)uptr_value,
+ (void *)(ctrl_data + cmd_len),
+ tmp_cmd->length)) {
+ pr_err("%s: copy_to_user failed, size=%d\n",
+ __func__, tmp_cmd->length);
+ rc = -EINVAL;
+ goto end;
+ }
+ tmp_cmd->value = uptr_value;
+ if (copy_to_user((void __user *)uptr_cmd,
+ (void *)tmp_cmd, cmd_len)) {
+ pr_err("%s: copy_to_user failed in cpy, size=%d\n",
+ __func__, cmd_len);
+ rc = -EINVAL;
+ goto end;
+ }
+ }
+end:
+ D("%s: END, type = %d, vaddr = 0x%x, vlen = %d, status = %d, rc = %d\n",
+ __func__, tmp_cmd->type, (uint32_t)tmp_cmd->value,
+ tmp_cmd->length, tmp_cmd->status, rc);
+ kfree(ctrl_data);
+ return rc;
+}
+
+static int msm_gesture_s_ctrl(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int rc = 0;
+ struct msm_gesture_ctrl *p_gesture_ctrl = &g_gesture_ctrl;
+ D("%s ctrl->id %d\n", __func__, ctrl->id);
+ rc = msm_gesture_proc_ctrl_cmd(p_gesture_ctrl, ctrl);
+ if (rc != 0) {
+ pr_err("%s set ctrl failed %d\n", __func__, rc);
+ return -EINVAL;
+ }
+ return rc;
+}
+
+static int msm_gesture_s_ctrl_ops(struct v4l2_ctrl *ctrl)
+{
+ int rc = 0;
+ struct v4l2_control control;
+ struct msm_gesture_ctrl *p_gesture_ctrl = &g_gesture_ctrl;
+ control.id = ctrl->id;
+ control.value = ctrl->val;
+ D("%s ctrl->id 0x%x\n", __func__, ctrl->id);
+ rc = msm_gesture_proc_ctrl_cmd(p_gesture_ctrl, &control);
+ if (rc != 0) {
+ pr_err("%s proc ctrl failed %d\n", __func__, rc);
+ return -EINVAL;
+ }
+ return rc;
+}
+
+static int msm_gesture_s_ctrl_ext(struct v4l2_subdev *sd,
+ struct v4l2_ext_controls *ctrls)
+{
+ int rc = 0;
+ struct v4l2_control control;
+ struct msm_gesture_ctrl *p_gesture_ctrl = &g_gesture_ctrl;
+ if ((ctrls->count < 1) || (NULL == ctrls->controls)) {
+ pr_err("%s invalid ctrl failed\n", __func__);
+ return -EINVAL;
+ }
+ control.id = ctrls->controls->id;
+ control.value = ctrls->controls->value;
+ D("%s ctrl->id %d\n", __func__, control.id);
+ rc = msm_gesture_proc_ctrl_cmd(p_gesture_ctrl, &control);
+ if (rc != 0) {
+ pr_err("%s proc ctrl failed %d\n", __func__, rc);
+ return -EINVAL;
+ }
+ return rc;
+}
+
+static int msm_gesture_handle_event(struct v4l2_subdev *sd,
+ struct msm_gesture_ctrl *p_gesture_ctrl, void* arg)
+{
+ int rc = 0;
+ struct v4l2_event *evt = (struct v4l2_event *)arg;
+ struct msm_ges_evt *p_ges_evt = NULL;
+ D("%s: Received gesture evt 0x%x ", __func__, evt->type);
+ p_gesture_ctrl->event.evt_len = 0;
+ p_gesture_ctrl->event.evt_data = NULL;
+ if (0 != evt->u.data[0]) {
+ p_ges_evt = (struct msm_ges_evt *)evt->u.data;
+ D("%s: event data %p len %d", __func__,
+ p_ges_evt->evt_data,
+ p_ges_evt->evt_len);
+
+ if (p_ges_evt->evt_len > 0) {
+ p_gesture_ctrl->event.evt_data =
+ kzalloc(p_ges_evt->evt_len, GFP_KERNEL);
+
+ if (NULL == p_gesture_ctrl->event.evt_data) {
+ pr_err("%s: cannot allocate event", __func__);
+ rc = -ENOMEM;
+ } else {
+ if (copy_from_user(
+ (void *)p_gesture_ctrl->event.evt_data,
+ (void __user *)p_ges_evt->evt_data,
+ p_ges_evt->evt_len)) {
+ pr_err("%s: copy_from_user failed",
+ __func__);
+ rc = -EFAULT;
+ } else {
+ D("%s: copied the event", __func__);
+ p_gesture_ctrl->event.evt_len =
+ p_ges_evt->evt_len;
+ }
+ }
+ }
+ }
+
+ if (rc == 0) {
+ ktime_get_ts(&evt->timestamp);
+ v4l2_event_queue(&sd->devnode, evt);
+ }
+ D("%s: exit rc %d ", __func__, rc);
+ return rc;
+}
+
+static int msm_gesture_get_evt_payload(struct v4l2_subdev *sd,
+ struct msm_gesture_ctrl *p_gesture_ctrl, void* arg)
+{
+ int rc = 0;
+ struct msm_ges_evt *p_ges_evt = (struct msm_ges_evt *)arg;
+ D("%s: enter ", __func__);
+ if (NULL != p_gesture_ctrl->event.evt_data) {
+ D("%s: event data %p len %d", __func__,
+ p_gesture_ctrl->event.evt_data,
+ p_gesture_ctrl->event.evt_len);
+
+ if (copy_to_user((void __user *)p_ges_evt->evt_data,
+ p_gesture_ctrl->event.evt_data,
+ p_gesture_ctrl->event.evt_len)) {
+ pr_err("%s: copy_to_user failed.\n", __func__);
+ rc = -EFAULT;
+ } else {
+ D("%s: copied the event", __func__);
+ p_ges_evt->evt_len = p_gesture_ctrl->event.evt_len;
+ }
+ }
+ D("%s: exit rc %d ", __func__, rc);
+ return rc;
+}
+
+static int msm_gesture_handle_cam_event(struct v4l2_subdev *sd,
+ struct msm_gesture_ctrl *p_gesture_ctrl, int cam_evt)
+{
+ int rc = 0;
+ D("%s: cam_evt %d ", __func__, cam_evt);
+
+ if ((cam_evt != MSM_V4L2_GES_CAM_OPEN)
+ && (cam_evt != MSM_V4L2_GES_CAM_CLOSE)) {
+ pr_err("%s: error invalid event %d ", __func__, cam_evt);
+ return -EINVAL;
+ }
+
+ p_gesture_ctrl->camera_opened =
+ (cam_evt == MSM_V4L2_GES_CAM_OPEN);
+
+ if (atomic_read(&p_gesture_ctrl->active) == 0) {
+ D("%s gesture not active\n", __func__);
+ return 0;
+ }
+
+ rc = msm_gesture_send_ctrl(p_gesture_ctrl, cam_evt, NULL,
+ 0, 2000);
+ if (rc != 0) {
+ pr_err("%s gesture ctrl failed %d\n", __func__, rc);
+ rc = -EINVAL;
+ }
+ D("%s exit rc %d\n", __func__, rc);
+ return rc;
+}
+
+long msm_gesture_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ int rc = 0;
+ struct msm_gesture_ctrl *p_gesture_ctrl = &g_gesture_ctrl;
+ D("%s\n", __func__);
+ switch (cmd) {
+ case MSM_GES_IOCTL_CTRL_COMMAND: {
+ struct v4l2_control *ctrl = (struct v4l2_control *)arg;
+ D("%s MSM_GES_IOCTL_CTRL_COMMAND arg %p size %d\n", __func__,
+ arg, sizeof(ctrl));
+ rc = msm_gesture_s_ctrl(sd, ctrl);
+ break;
+ }
+ case VIDIOC_MSM_GESTURE_EVT: {
+ rc = msm_gesture_handle_event(sd, p_gesture_ctrl, arg);
+ break;
+ }
+ case VIDIOC_MSM_GESTURE_CAM_EVT: {
+ int cam_evt = *((int *)arg);
+ rc = msm_gesture_handle_cam_event(sd, p_gesture_ctrl, cam_evt);
+ break;
+ }
+ case MSM_GES_GET_EVT_PAYLOAD: {
+ rc = msm_gesture_get_evt_payload(sd, p_gesture_ctrl, arg);
+ break;
+ }
+ default:
+ pr_err("%s: Invalid ioctl %d", __func__, cmd);
+ break;
+ }
+ D("%s exit rc %d\n", __func__, rc);
+ return rc;
+}
+
+static const struct v4l2_ctrl_ops msm_gesture_ctrl_ops = {
+ .s_ctrl = msm_gesture_s_ctrl_ops,
+};
+
+static const struct v4l2_ctrl_config msm_gesture_ctrl_filter = {
+ .ops = &msm_gesture_ctrl_ops,
+ .id = MSM_GESTURE_CID_CTRL_CMD,
+ .name = "Gesture ctrl",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .flags = V4L2_CTRL_FLAG_SLIDER,
+ .max = 0x7fffffff,
+ .step = 1,
+ .min = 0x80000000,
+};
+
+static int msm_gesture_init_ctrl(struct v4l2_subdev *sd,
+ struct msm_gesture_ctrl *p_gesture_ctrl)
+{
+ int rc = 0;
+ p_gesture_ctrl->num_ctrls = 1;
+ p_gesture_ctrl->ctrl_handler.error = 0;
+ v4l2_ctrl_handler_init(&p_gesture_ctrl->ctrl_handler,
+ p_gesture_ctrl->num_ctrls);
+ v4l2_ctrl_new_custom(&p_gesture_ctrl->ctrl_handler,
+ &msm_gesture_ctrl_filter, p_gesture_ctrl);
+ if (p_gesture_ctrl->ctrl_handler.error) {
+ int err = p_gesture_ctrl->ctrl_handler.error;
+ D("%s: error adding control %d", __func__, err);
+ p_gesture_ctrl->ctrl_handler.error = 0;
+ }
+ sd->ctrl_handler = &p_gesture_ctrl->ctrl_handler;
+ return rc;
+}
+
+static int msm_gesture_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ int rc = 0, rc_err = 0;
+ struct msm_gesture_ctrl *p_gesture_ctrl = &g_gesture_ctrl;
+ D("%s\n", __func__);
+ if (atomic_read(&p_gesture_ctrl->active) != 0) {
+ pr_err("%s already opened\n", __func__);
+ return -EINVAL;
+ }
+ memset(&p_gesture_ctrl->event, 0x0, sizeof(struct msm_ges_evt));
+ rc = msm_server_open_client(&p_gesture_ctrl->queue_id);
+ if (rc != 0) {
+ pr_err("%s open failed %d\n", __func__, rc);
+ rc = -EINVAL;
+ goto err;
+ }
+
+ rc = msm_gesture_init_ctrl(sd, p_gesture_ctrl);
+ if (rc != 0) {
+ pr_err("%s init ctrl failed %d\n", __func__, rc);
+ rc = -EINVAL;
+ goto err;
+ }
+
+ rc = msm_gesture_send_ctrl(p_gesture_ctrl, MSM_V4L2_GES_OPEN, NULL,
+ 0, 10000);
+ if (rc != 0) {
+ pr_err("%s gesture ctrl failed %d\n", __func__, rc);
+ rc = -EINVAL;
+ goto err;
+ }
+
+ atomic_inc(&p_gesture_ctrl->active);
+
+ return rc;
+
+err:
+ rc_err = msm_server_close_client(p_gesture_ctrl->queue_id);
+ if (rc_err != 0)
+ pr_err("%s failed %d\n", __func__, rc);
+ return rc;
+}
+
+static int msm_gesture_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ int rc = 0;
+ struct msm_gesture_ctrl *p_gesture_ctrl = &g_gesture_ctrl;
+ D("%s\n", __func__);
+ if (atomic_read(&p_gesture_ctrl->active) == 0) {
+ pr_err("%s already closed\n", __func__);
+ return -EINVAL;
+ }
+
+ rc = msm_gesture_send_ctrl(p_gesture_ctrl, MSM_V4L2_GES_CLOSE, NULL,
+ 0, 10000);
+ if (rc != 0)
+ pr_err("%s gesture ctrl failed %d\n", __func__, rc);
+
+ rc = msm_server_close_client(p_gesture_ctrl->queue_id);
+ if (rc != 0)
+ pr_err("%s failed %d\n", __func__, rc);
+
+ v4l2_ctrl_handler_free(&p_gesture_ctrl->ctrl_handler);
+ kfree(p_gesture_ctrl->event.evt_data);
+
+ atomic_dec(&p_gesture_ctrl->active);
+ g_gesture_ctrl.queue_id = -1;
+ return 0;
+}
+
+static struct v4l2_subdev_core_ops msm_gesture_core_ops = {
+ .s_ctrl = msm_gesture_s_ctrl,
+ .s_ext_ctrls = msm_gesture_s_ctrl_ext,
+ .ioctl = msm_gesture_ioctl,
+ .subscribe_event = msm_gesture_subscribe_event,
+};
+
+static struct v4l2_subdev_video_ops msm_gesture_video_ops;
+
+static struct v4l2_subdev_ops msm_gesture_subdev_ops = {
+ .core = &msm_gesture_core_ops,
+ .video = &msm_gesture_video_ops,
+};
+
+static const struct v4l2_subdev_internal_ops msm_gesture_internal_ops = {
+ .open = msm_gesture_open,
+ .close = msm_gesture_close,
+};
+
+static int msm_gesture_node_register(void)
+{
+ struct msm_gesture_ctrl *p_gesture_ctrl = &g_gesture_ctrl;
+ struct v4l2_subdev *gesture_subdev =
+ kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+ D("%s\n", __func__);
+ if (!gesture_subdev) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ };
+
+ v4l2_subdev_init(gesture_subdev, &msm_gesture_subdev_ops);
+ gesture_subdev->internal_ops = &msm_gesture_internal_ops;
+ gesture_subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(gesture_subdev->name,
+ sizeof(gesture_subdev->name), "gesture");
+
+ media_entity_init(&gesture_subdev->entity, 0, NULL, 0);
+ gesture_subdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+ gesture_subdev->entity.group_id = GESTURE_DEV;
+ gesture_subdev->entity.name = gesture_subdev->name;
+
+ /* events */
+ gesture_subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
+ gesture_subdev->nevents = MAX_GES_EVENTS;
+
+ msm_cam_register_subdev_node(gesture_subdev, GESTURE_DEV, 0);
+
+ gesture_subdev->entity.revision = gesture_subdev->devnode.num;
+
+ atomic_set(&p_gesture_ctrl->active, 0);
+ p_gesture_ctrl->queue_id = -1;
+ p_gesture_ctrl->event.evt_data = NULL;
+ p_gesture_ctrl->event.evt_len = 0;
+ return 0;
+}
+
+static int __init msm_gesture_init_module(void)
+{
+ return msm_gesture_node_register();
+}
+
+module_init(msm_gesture_init_module);
+MODULE_DESCRIPTION("MSM Gesture driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index e878063..e9eb68f 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -923,7 +923,6 @@
struct msm_cam_v4l2_device *pcam = NULL;
struct msm_cam_v4l2_dev_inst *pcam_inst;
struct msm_cam_media_controller *pmctl;
- D("%s : E ", __func__);
if (f == NULL) {
pr_err("%s :: cannot open video driver data", __func__);
@@ -935,8 +934,8 @@
pr_err("%s NULL pointer passed in!\n", __func__);
return rc;
}
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ D("%s : E use_count %d", __func__, pcam->mctl_node.use_count);
mutex_lock(&pcam->mctl_node.dev_lock);
for (i = 0; i < MSM_DEV_INST_MAX; i++) {
if (pcam->mctl_node.dev_inst[i] == NULL)
@@ -960,6 +959,21 @@
D("%s pcam_inst %p my_index = %d\n", __func__,
pcam_inst, pcam_inst->my_index);
+ rc = msm_cam_server_open_mctl_session(pcam,
+ &pcam->mctl_node.active);
+ if (rc < 0) {
+ pr_err("%s: mctl session open failed %d", __func__, rc);
+ mutex_unlock(&pcam->mctl_node.dev_lock);
+ return rc;
+ }
+
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ if (!pmctl) {
+ pr_err("%s mctl NULL!\n", __func__);
+ return rc;
+ }
+
+ D("%s active %d\n", __func__, pcam->mctl_node.active);
rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
pcam->mctl_node.pvdev);
if (rc < 0) {
@@ -973,6 +987,7 @@
D("f->private_data = 0x%x, pcam = 0x%x\n",
(u32)f->private_data, (u32)pcam_inst);
+ pcam->mctl_node.use_count++;
mutex_unlock(&pcam->mctl_node.dev_lock);
D("%s : X ", __func__);
return rc;
@@ -1030,6 +1045,17 @@
pmctl = msm_camera_get_mctl(pcam->mctl_handle);
mutex_lock(&pcam->mctl_node.dev_lock);
+ D("%s : active %d ", __func__, pcam->mctl_node.active);
+ if (pcam->mctl_node.active == 1) {
+ rc = msm_cam_server_close_mctl_session(pcam);
+ if (rc < 0) {
+ pr_err("%s: mctl session close failed %d",
+ __func__, rc);
+ mutex_unlock(&pcam->mctl_node.dev_lock);
+ return rc;
+ }
+ pmctl = NULL;
+ }
pcam_inst->streamon = 0;
pcam->mctl_node.dev_inst_map[pcam_inst->image_mode] = NULL;
if (pcam_inst->vbqueue_initialized)
@@ -1040,10 +1066,14 @@
v4l2_fh_exit(&pcam_inst->eventHandle);
kfree(pcam_inst);
- kref_put(&pmctl->refcount, msm_release_ion_client);
+ if (NULL != pmctl) {
+ D("%s : release ion client", __func__);
+ kref_put(&pmctl->refcount, msm_release_ion_client);
+ }
f->private_data = NULL;
mutex_unlock(&pcam->mctl_node.dev_lock);
- D("%s : X ", __func__);
+ pcam->mctl_node.use_count--;
+ D("%s : use_count %d X ", __func__, pcam->mctl_node.use_count);
return rc;
}
@@ -1246,6 +1276,11 @@
pb->m.planes[i].data_offset;
pcam_inst->buf_offset[pb->index][i].addr_offset =
pb->m.planes[i].reserved[0];
+ pcam_inst->plane_info.plane[i].offset = 0;
+ D("%s, len %d user[%d] %p buf_len %d\n",
+ __func__, pb->length, i,
+ (void *)pb->m.planes[i].m.userptr,
+ pb->m.planes[i].length);
}
} else {
D("%s stored reserved info %d", __func__, pb->reserved);
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 5bc81a7..42d13a1 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -431,8 +431,8 @@
int pp_divert_type = 0, pp_type = 0;
msm_mctl_check_pp(p_mctl, image_mode, &pp_divert_type, &pp_type);
- D("%s: pp_type=%d, pp_divert_type = %d, frame_id = 0x%x",
- __func__, pp_type, pp_divert_type, frame_id);
+ D("%s: pp_type=%d, pp_divert_type = %d, frame_id = 0x%x image_mode %d",
+ __func__, pp_type, pp_divert_type, frame_id, image_mode);
if (pp_type || pp_divert_type)
rc = msm_mctl_do_pp_divert(p_mctl,
image_mode, fbuf, frame_id, pp_type);
@@ -440,9 +440,26 @@
idx = msm_mctl_img_mode_to_inst_index(
p_mctl, image_mode, 0);
if (idx < 0) {
- pr_err("%s Invalid instance, dropping buffer\n",
- __func__);
- return idx;
+ /* check mctl node */
+ if ((image_mode >= 0) &&
+ p_mctl->pcam_ptr->mctl_node.
+ dev_inst_map[image_mode]) {
+ int index = p_mctl->pcam_ptr->mctl_node.
+ dev_inst_map[image_mode]->my_index;
+ pcam_inst = p_mctl->pcam_ptr->mctl_node.
+ dev_inst[index];
+ D("%s: Mctl node index %d inst %p",
+ __func__, index, pcam_inst);
+ rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
+ image_mode, fbuf,
+ &frame_id, 1);
+ D("%s mctl node buf done %d\n", __func__, 0);
+ return -EINVAL;
+ } else {
+ pr_err("%s Invalid instance, dropping buffer\n",
+ __func__);
+ return idx;
+ }
}
pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
@@ -573,6 +590,10 @@
plane_offset =
mem->offset.sp_off.cbcr_off;
+ D("%s: data off %d plane off %d",
+ __func__,
+ pcam_inst->buf_offset[buf_idx][i].
+ data_offset, plane_offset);
free_buf->ch_paddr[i] = (uint32_t)
videobuf2_to_pmem_contig(&buf->vidbuf, i) +
pcam_inst->buf_offset[buf_idx][i].data_offset +
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index becdd95..3e8d3be 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -3056,7 +3056,7 @@
ch2_paddr = vfe32_get_ch_addr(ping_pong,
vfe32_ctrl->outpath.out1.ch2);
- pr_debug("%s ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
+ CDBG("%s ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
__func__, ch0_paddr, ch1_paddr, ch2_paddr);
if (free_buf) {
/* Y channel */
diff --git a/include/media/Kbuild b/include/media/Kbuild
index 8dfb0fc..03951ce 100644
--- a/include/media/Kbuild
+++ b/include/media/Kbuild
@@ -4,4 +4,4 @@
header-y += vcap_fmt.h
header-y += msm_isp.h
header-y += msm_gemini.h
-header-y += msm_v4l2_overlay.h
+header-y += msm_gestures.h
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 3f647dc..d4cf1d2 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1433,6 +1433,9 @@
#define MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD \
_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct msm_camera_v4l2_ioctl_t *)
+#define MSM_CAM_IOCTL_SEND_EVENT \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_event)
+
struct msm_camera_v4l2_ioctl_t {
void __user *ioctl_ptr;
};
diff --git a/include/media/msm_gestures.h b/include/media/msm_gestures.h
new file mode 100644
index 0000000..c9af034
--- /dev/null
+++ b/include/media/msm_gestures.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+#ifndef __LINUX_MSM_GESTURES_H
+#define __LINUX_MSM_GESTURES_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <media/msm_camera.h>
+
+#define MSM_GES_IOCTL_CTRL_COMMAND \
+ _IOW('V', BASE_VIDIOC_PRIVATE + 20, struct v4l2_control)
+
+#define VIDIOC_MSM_GESTURE_EVT \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 21, struct v4l2_event)
+
+#define MSM_GES_GET_EVT_PAYLOAD \
+ _IOW('V', BASE_VIDIOC_PRIVATE + 22, struct msm_ges_evt)
+
+#define VIDIOC_MSM_GESTURE_CAM_EVT \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 23, int)
+
+#define MSM_GES_RESP_V4L2 MSM_CAM_RESP_MAX
+#define MSM_GES_RESP_MAX (MSM_GES_RESP_V4L2 + 1)
+
+#define MSM_SVR_RESP_MAX MSM_GES_RESP_MAX
+
+
+#define MSM_V4L2_GES_BASE 100
+#define MSM_V4L2_GES_OPEN (MSM_V4L2_GES_BASE + 0)
+#define MSM_V4L2_GES_CLOSE (MSM_V4L2_GES_BASE + 1)
+#define MSM_V4L2_GES_CAM_OPEN (MSM_V4L2_GES_BASE + 2)
+#define MSM_V4L2_GES_CAM_CLOSE (MSM_V4L2_GES_BASE + 3)
+
+#define MSM_GES_APP_EVT_MIN (V4L2_EVENT_PRIVATE_START + 0x14)
+#define MSM_GES_APP_NOTIFY_EVENT (MSM_GES_APP_EVT_MIN + 0)
+#define MSM_GES_APP_NOTIFY_ERROR_EVENT (MSM_GES_APP_EVT_MIN + 1)
+#define MSM_GES_APP_EVT_MAX (MSM_GES_APP_EVT_MIN + 2)
+
+#define MSM_GESTURE_CID_CTRL_CMD V4L2_CID_BRIGHTNESS
+
+#define MAX_GES_EVENTS 25
+
+struct msm_ges_ctrl_cmd {
+ int type;
+ void *value;
+ int len;
+ int fd;
+ uint32_t cookie;
+};
+
+struct msm_ges_evt {
+ void *evt_data;
+ int evt_len;
+};
+
+#endif /*__LINUX_MSM_GESTURES_H*/