Loading drivers/media/platform/msm/camera_v2/camera/camera.c +86 −1 Original line number Diff line number Diff line Loading @@ -453,6 +453,38 @@ static int camera_v4l2_unsubscribe_event(struct v4l2_fh *fh, return rc; } static long camera_v4l2_vidioc_private_ioctl(struct file *filep, void *fh, bool valid_prio, unsigned int cmd, void *arg) { struct camera_v4l2_private *sp = fh_to_private(fh); struct msm_video_device *pvdev = video_drvdata(filep); struct msm_camera_private_ioctl_arg *k_ioctl = arg; long rc = -EINVAL; if (WARN_ON(!k_ioctl || !pvdev)) return -EIO; switch (k_ioctl->id) { case MSM_CAMERA_PRIV_IOCTL_ID_RETURN_BUF: { struct msm_camera_return_buf ptr, *tmp = NULL; MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl->ioctl_ptr, sizeof(tmp)); if (copy_from_user(&ptr, tmp, sizeof(struct msm_camera_return_buf))) { return -EFAULT; } rc = msm_vb2_return_buf_by_idx(pvdev->vdev->num, sp->stream_id, ptr.index); } break; default: pr_debug("unimplemented id %d", k_ioctl->id); return -EINVAL; } return rc; } static const struct v4l2_ioctl_ops camera_v4l2_ioctl_ops = { .vidioc_querycap = camera_v4l2_querycap, .vidioc_s_crop = camera_v4l2_s_crop, Loading @@ -477,6 +509,7 @@ static const struct v4l2_ioctl_ops camera_v4l2_ioctl_ops = { /* event subscribe/unsubscribe */ .vidioc_subscribe_event = camera_v4l2_subscribe_event, .vidioc_unsubscribe_event = camera_v4l2_unsubscribe_event, .vidioc_default = camera_v4l2_vidioc_private_ioctl, }; static int camera_v4l2_fh_open(struct file *filep) Loading Loading @@ -724,10 +757,62 @@ static int camera_v4l2_close(struct file *filep) } #ifdef CONFIG_COMPAT static long camera_handle_internal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long rc = 0; struct msm_camera_private_ioctl_arg k_ioctl; void __user *tmp_compat_ioctl_ptr = NULL; rc = msm_copy_camera_private_ioctl_args(arg, &k_ioctl, &tmp_compat_ioctl_ptr); if (rc < 0) { pr_err("Subdev cmd %d failed\n", cmd); return rc; } switch (k_ioctl.id) { case MSM_CAMERA_PRIV_IOCTL_ID_RETURN_BUF: { if (k_ioctl.size != sizeof(struct msm_camera_return_buf)) { pr_debug("Invalid size for id %d with size %d", k_ioctl.id, k_ioctl.size); return -EINVAL; } k_ioctl.ioctl_ptr = (__u64)tmp_compat_ioctl_ptr; if (!k_ioctl.ioctl_ptr) { pr_debug("Invalid ptr for id %d", k_ioctl.id); return -EINVAL; } rc = camera_v4l2_vidioc_private_ioctl(file, file->private_data, 0, cmd, (void *)&k_ioctl); } break; default: pr_debug("unimplemented id %d", k_ioctl.id); return -EINVAL; } return rc; } long camera_v4l2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return -ENOIOCTLCMD; long ret = 0; switch (cmd) { case VIDIOC_MSM_CAMERA_PRIVATE_IOCTL_CMD: { ret = camera_handle_internal_compat_ioctl(file, cmd, arg); if (ret < 0) { pr_debug("Subdev cmd %d fail\n", cmd); return ret; } } break; default: ret = -ENOIOCTLCMD; break; } return ret; } #endif static struct v4l2_file_operations camera_v4l2_fops = { Loading drivers/media/platform/msm/camera_v2/fd/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -3,5 +3,6 @@ ccflags-y += -Idrivers/media/video/msm ccflags-y += -Idrivers/media/platform/msm/camera_v2/common ccflags-y += -Idrivers/media/platform/msm/camera_v2 ccflags-y += -Idrivers/media/platform/msm/camera_v2/pproc/cpp ccflags-y += -Idrivers/media/platform/msm/camera_v2/msm_buf_mgr/ obj-$(CONFIG_MSM_FD) += msm_fd_dev.o msm_fd_hw.o drivers/media/platform/msm/camera_v2/msm.c +22 −0 Original line number Diff line number Diff line Loading @@ -1088,6 +1088,28 @@ struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q) } EXPORT_SYMBOL(msm_get_stream_from_vb2q); #ifdef CONFIG_COMPAT long msm_copy_camera_private_ioctl_args(unsigned long arg, struct msm_camera_private_ioctl_arg *k_ioctl, void __user **tmp_compat_ioctl_ptr) { struct msm_camera_private_ioctl_arg *up_ioctl_ptr = (struct msm_camera_private_ioctl_arg *)arg; if (WARN_ON(!arg || !k_ioctl || !tmp_compat_ioctl_ptr)) return -EIO; k_ioctl->id = up_ioctl_ptr->id; k_ioctl->size = up_ioctl_ptr->size; k_ioctl->result = up_ioctl_ptr->result; k_ioctl->reserved = up_ioctl_ptr->reserved; *tmp_compat_ioctl_ptr = compat_ptr(up_ioctl_ptr->ioctl_ptr); return 0; } EXPORT_SYMBOL(msm_copy_camera_private_ioctl_args); #endif static void msm_sd_notify(struct v4l2_subdev *sd, unsigned int notification, void *arg) { Loading drivers/media/platform/msm/camera_v2/msm.h +6 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2016, The Linux Foundation. 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 Loading Loading @@ -127,4 +127,9 @@ struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id, unsigned int stream_id); struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q); struct msm_session *msm_session_find(unsigned int session_id); #ifdef CONFIG_COMPAT long msm_copy_camera_private_ioctl_args(unsigned long arg, struct msm_camera_private_ioctl_arg *k_ioctl, void __user **tmp_compat_ioctl_ptr); #endif #endif /*_MSM_H */ drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c +268 −48 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ static int32_t msm_buf_mngr_hdl_cont_get_buf(struct msm_buf_mngr_device *dev, } return 0; } static int32_t msm_buf_mngr_get_buf(struct msm_buf_mngr_device *dev, void __user *argp) { Loading Loading @@ -91,6 +92,51 @@ static int32_t msm_buf_mngr_get_buf(struct msm_buf_mngr_device *dev, return rc; } static int32_t msm_buf_mngr_get_buf_by_idx(struct msm_buf_mngr_device *dev, void *argp) { unsigned long flags; int32_t rc = 0; struct msm_buf_mngr_info *buf_info = (struct msm_buf_mngr_info *)argp; struct msm_get_bufs *new_entry = kzalloc(sizeof(struct msm_get_bufs), GFP_KERNEL); if (!new_entry) { pr_err("%s:No mem\n", __func__); return -ENOMEM; } if (WARN_ON(!buf_info)) return -EIO; INIT_LIST_HEAD(&new_entry->entry); new_entry->vb2_buf = dev->vb2_ops.get_buf_by_idx(buf_info->session_id, buf_info->stream_id, buf_info->index); if (!new_entry->vb2_buf) { pr_debug("%s:Get buf is null\n", __func__); kfree(new_entry); return -EINVAL; } new_entry->session_id = buf_info->session_id; new_entry->stream_id = buf_info->stream_id; new_entry->index = new_entry->vb2_buf->v4l2_buf.index; spin_lock_irqsave(&dev->buf_q_spinlock, flags); list_add_tail(&new_entry->entry, &dev->buf_qhead); spin_unlock_irqrestore(&dev->buf_q_spinlock, flags); if (buf_info->type == MSM_CAMERA_BUF_MNGR_BUF_USER) { mutex_lock(&dev->cont_mutex); if (!list_empty(&dev->cont_qhead)) { rc = msm_buf_mngr_hdl_cont_get_buf(dev, buf_info); } else { pr_err("Nothing mapped in user buf for %d,%d\n", buf_info->session_id, buf_info->stream_id); rc = -EINVAL; } mutex_unlock(&dev->cont_mutex); } return rc; } static int32_t msm_buf_mngr_buf_done(struct msm_buf_mngr_device *buf_mngr_dev, struct msm_buf_mngr_info *buf_info) { Loading Loading @@ -410,6 +456,67 @@ static int msm_generic_buf_mngr_close(struct v4l2_subdev *sd, return rc; } int msm_cam_buf_mgr_ops(unsigned int cmd, void *argp) { int rc = 0; if (!msm_buf_mngr_dev) return -ENODEV; if (!argp) return -EINVAL; switch (cmd) { case VIDIOC_MSM_BUF_MNGR_GET_BUF: rc = msm_buf_mngr_get_buf(msm_buf_mngr_dev, argp); break; case VIDIOC_MSM_BUF_MNGR_BUF_DONE: rc = msm_buf_mngr_buf_done(msm_buf_mngr_dev, argp); break; case VIDIOC_MSM_BUF_MNGR_PUT_BUF: rc = msm_buf_mngr_put_buf(msm_buf_mngr_dev, argp); break; case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD: { struct msm_camera_private_ioctl_arg *k_ioctl = argp; switch (k_ioctl->id) { case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: { struct msm_buf_mngr_info *tmp = NULL; if (!k_ioctl->ioctl_ptr) return -EINVAL; if (k_ioctl->size != sizeof(struct msm_buf_mngr_info)) return -EINVAL; MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl->ioctl_ptr, sizeof(tmp)); rc = msm_buf_mngr_get_buf_by_idx(msm_buf_mngr_dev, tmp); } break; default: pr_debug("unimplemented id %d", k_ioctl->id); return -EINVAL; } break; } default: return -ENOIOCTLCMD; } return rc; } int msm_cam_buf_mgr_register_ops(struct msm_cam_buf_mgr_req_ops *cb_struct) { if (!msm_buf_mngr_dev) return -ENODEV; if (!cb_struct) return -EINVAL; cb_struct->msm_cam_buf_mgr_ops = msm_cam_buf_mgr_ops; return 0; } static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { Loading @@ -422,16 +529,45 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd, rc = -ENOMEM; return rc; } switch (cmd) { case VIDIOC_MSM_BUF_MNGR_GET_BUF: rc = msm_buf_mngr_get_buf(buf_mngr_dev, argp); case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD: { struct msm_camera_private_ioctl_arg k_ioctl, *ptr; if (!arg) return -EINVAL; ptr = arg; k_ioctl = *ptr; switch (k_ioctl.id) { case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: { struct msm_buf_mngr_info buf_info, *tmp = NULL; if (k_ioctl.size != sizeof(struct msm_buf_mngr_info)) return -EINVAL; if (!k_ioctl.ioctl_ptr) return -EINVAL; MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl.ioctl_ptr, sizeof(tmp)); if (copy_from_user(&buf_info, tmp, sizeof(struct msm_buf_mngr_info))) { return -EFAULT; } MSM_CAM_GET_IOCTL_ARG_PTR(&k_ioctl.ioctl_ptr, &buf_info, sizeof(void *)); argp = &k_ioctl; rc = msm_cam_buf_mgr_ops(cmd, argp); } break; case VIDIOC_MSM_BUF_MNGR_BUF_DONE: rc = msm_buf_mngr_buf_done(buf_mngr_dev, argp); default: pr_debug("unimplemented id %d", k_ioctl.id); return -EINVAL; } } break; case VIDIOC_MSM_BUF_MNGR_GET_BUF: case VIDIOC_MSM_BUF_MNGR_BUF_DONE: case VIDIOC_MSM_BUF_MNGR_PUT_BUF: rc = msm_buf_mngr_put_buf(buf_mngr_dev, argp); rc = msm_cam_buf_mgr_ops(cmd, argp); break; case VIDIOC_MSM_BUF_MNGR_INIT: rc = msm_generic_buf_mngr_open(sd, NULL); Loading Loading @@ -459,6 +595,105 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd, } #ifdef CONFIG_COMPAT static long msm_camera_buf_mgr_fetch_buf_info( struct msm_buf_mngr_info32_t *buf_info32, struct msm_buf_mngr_info *buf_info, unsigned long arg) { WARN_ON(!arg || !buf_info32 || !buf_info); if (copy_from_user(buf_info32, (void __user *)arg, sizeof(struct msm_buf_mngr_info32_t))) return -EFAULT; buf_info->session_id = buf_info32->session_id; buf_info->stream_id = buf_info32->stream_id; buf_info->frame_id = buf_info32->frame_id; buf_info->index = buf_info32->index; buf_info->timestamp.tv_sec = (long) buf_info32->timestamp.tv_sec; buf_info->timestamp.tv_usec = (long) buf_info32-> timestamp.tv_usec; buf_info->reserved = buf_info32->reserved; buf_info->type = buf_info32->type; return 0; } static long msm_camera_buf_mgr_update_buf_info( struct msm_buf_mngr_info32_t *buf_info32, struct msm_buf_mngr_info *buf_info, unsigned long arg) { WARN_ON(!arg || !buf_info32 || !buf_info); buf_info32->session_id = buf_info->session_id; buf_info32->stream_id = buf_info->stream_id; buf_info32->index = buf_info->index; buf_info32->timestamp.tv_sec = (int32_t) buf_info-> timestamp.tv_sec; buf_info32->timestamp.tv_usec = (int32_t) buf_info->timestamp. tv_usec; buf_info32->reserved = buf_info->reserved; buf_info32->type = buf_info->type; buf_info32->user_buf.buf_cnt = buf_info->user_buf.buf_cnt; memcpy(&buf_info32->user_buf.buf_idx, &buf_info->user_buf.buf_idx, sizeof(buf_info->user_buf.buf_idx)); if (copy_to_user((void __user *)arg, buf_info32, sizeof(struct msm_buf_mngr_info32_t))) return -EFAULT; return 0; } static long msm_camera_buf_mgr_internal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); long rc = 0; struct msm_camera_private_ioctl_arg k_ioctl; void __user *tmp_compat_ioctl_ptr = NULL; rc = msm_copy_camera_private_ioctl_args(arg, &k_ioctl, &tmp_compat_ioctl_ptr); if (rc < 0) { pr_err("Subdev cmd %d failed\n", cmd); return rc; } switch (k_ioctl.id) { case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: { struct msm_buf_mngr_info32_t buf_info32; struct msm_buf_mngr_info buf_info; if (k_ioctl.size != sizeof(struct msm_buf_mngr_info32_t)) { pr_err("Invalid size for id %d with size %d", k_ioctl.id, k_ioctl.size); return -EINVAL; } if (!tmp_compat_ioctl_ptr) { pr_err("Invalid ptr for id %d", k_ioctl.id); return -EINVAL; } k_ioctl.ioctl_ptr = (__u64)&buf_info; rc = msm_camera_buf_mgr_fetch_buf_info(&buf_info32, &buf_info, (unsigned long)tmp_compat_ioctl_ptr); if (rc < 0) { pr_err("Fetch buf info failed for cmd=%d", cmd); return rc; } rc = v4l2_subdev_call(sd, core, ioctl, cmd, &k_ioctl); if (rc < 0) { pr_err("Subdev cmd %d failed for id %d", cmd, k_ioctl.id); return rc; } } break; default: pr_debug("unimplemented id %d", k_ioctl.id); return -EINVAL; } return 0; } static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { Loading @@ -466,8 +701,6 @@ static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file, struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); int32_t rc = 0; void __user *up = (void __user *)arg; /* Convert 32 bit IOCTL ID's to 64 bit IOCTL ID's * except VIDIOC_MSM_CPP_CFG32, which needs special * processing Loading @@ -483,13 +716,14 @@ static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file, cmd = VIDIOC_MSM_BUF_MNGR_PUT_BUF; break; case VIDIOC_MSM_BUF_MNGR_CONT_CMD: cmd = VIDIOC_MSM_BUF_MNGR_CONT_CMD; break; case VIDIOC_MSM_BUF_MNGR_FLUSH32: cmd = VIDIOC_MSM_BUF_MNGR_FLUSH; break; case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD: break; default: pr_debug("%s : unsupported compat type", __func__); pr_debug("unsupported compat type\n"); return -ENOIOCTLCMD; } Loading @@ -501,65 +735,51 @@ static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file, struct msm_buf_mngr_info32_t buf_info32; struct msm_buf_mngr_info buf_info; if (copy_from_user(&buf_info32, (void __user *)up, sizeof(struct msm_buf_mngr_info32_t))) return -EFAULT; buf_info.session_id = buf_info32.session_id; buf_info.stream_id = buf_info32.stream_id; buf_info.frame_id = buf_info32.frame_id; buf_info.index = buf_info32.index; buf_info.timestamp.tv_sec = (long) buf_info32.timestamp.tv_sec; buf_info.timestamp.tv_usec = (long) buf_info32. timestamp.tv_usec; buf_info.reserved = buf_info32.reserved; buf_info.type = buf_info32.type; rc = msm_camera_buf_mgr_fetch_buf_info(&buf_info32, &buf_info, arg); if (rc < 0) { pr_err("Fetch buf info failed for cmd=%d\n", cmd); return rc; } rc = v4l2_subdev_call(sd, core, ioctl, cmd, &buf_info); if (rc < 0) { pr_debug("%s : Subdev cmd %d fail", __func__, cmd); pr_debug("Subdev cmd %d fail\n", cmd); return rc; } rc = msm_camera_buf_mgr_update_buf_info(&buf_info32, &buf_info, arg); if (rc < 0) { pr_err("Update buf info failed for cmd=%d\n", cmd); return rc; } } break; case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD: { rc = msm_camera_buf_mgr_internal_compat_ioctl(file, cmd, arg); if (rc < 0) { pr_debug("Subdev cmd %d fail\n", cmd); return rc; } buf_info32.session_id = buf_info.session_id; buf_info32.stream_id = buf_info.stream_id; buf_info32.index = buf_info.index; buf_info32.timestamp.tv_sec = (int32_t) buf_info. timestamp.tv_sec; buf_info32.timestamp.tv_usec = (int32_t) buf_info.timestamp. tv_usec; buf_info32.reserved = buf_info.reserved; buf_info32.type = buf_info.type; buf_info32.user_buf.buf_cnt = buf_info.user_buf.buf_cnt; memcpy(&buf_info32.user_buf.buf_idx, &buf_info.user_buf.buf_idx, sizeof(buf_info.user_buf.buf_idx)); if (copy_to_user((void __user *)up, &buf_info32, sizeof(struct msm_buf_mngr_info32_t))) return -EFAULT; } break; case VIDIOC_MSM_BUF_MNGR_CONT_CMD: { struct msm_buf_mngr_main_cont_info cont_cmd; if (copy_from_user(&cont_cmd, (void __user *)up, if (copy_from_user(&cont_cmd, (void __user *)arg, sizeof(struct msm_buf_mngr_main_cont_info))) return -EFAULT; rc = v4l2_subdev_call(sd, core, ioctl, cmd, &cont_cmd); if (rc < 0) { pr_debug("%s : Subdev cmd %d fail", __func__, cmd); pr_debug("Subdev cmd %d fail\n", cmd); return rc; } } break; default: pr_debug("%s : unsupported compat type", __func__); pr_debug("unsupported compat type\n"); return -ENOIOCTLCMD; break; } return 0; } #endif Loading Loading
drivers/media/platform/msm/camera_v2/camera/camera.c +86 −1 Original line number Diff line number Diff line Loading @@ -453,6 +453,38 @@ static int camera_v4l2_unsubscribe_event(struct v4l2_fh *fh, return rc; } static long camera_v4l2_vidioc_private_ioctl(struct file *filep, void *fh, bool valid_prio, unsigned int cmd, void *arg) { struct camera_v4l2_private *sp = fh_to_private(fh); struct msm_video_device *pvdev = video_drvdata(filep); struct msm_camera_private_ioctl_arg *k_ioctl = arg; long rc = -EINVAL; if (WARN_ON(!k_ioctl || !pvdev)) return -EIO; switch (k_ioctl->id) { case MSM_CAMERA_PRIV_IOCTL_ID_RETURN_BUF: { struct msm_camera_return_buf ptr, *tmp = NULL; MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl->ioctl_ptr, sizeof(tmp)); if (copy_from_user(&ptr, tmp, sizeof(struct msm_camera_return_buf))) { return -EFAULT; } rc = msm_vb2_return_buf_by_idx(pvdev->vdev->num, sp->stream_id, ptr.index); } break; default: pr_debug("unimplemented id %d", k_ioctl->id); return -EINVAL; } return rc; } static const struct v4l2_ioctl_ops camera_v4l2_ioctl_ops = { .vidioc_querycap = camera_v4l2_querycap, .vidioc_s_crop = camera_v4l2_s_crop, Loading @@ -477,6 +509,7 @@ static const struct v4l2_ioctl_ops camera_v4l2_ioctl_ops = { /* event subscribe/unsubscribe */ .vidioc_subscribe_event = camera_v4l2_subscribe_event, .vidioc_unsubscribe_event = camera_v4l2_unsubscribe_event, .vidioc_default = camera_v4l2_vidioc_private_ioctl, }; static int camera_v4l2_fh_open(struct file *filep) Loading Loading @@ -724,10 +757,62 @@ static int camera_v4l2_close(struct file *filep) } #ifdef CONFIG_COMPAT static long camera_handle_internal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long rc = 0; struct msm_camera_private_ioctl_arg k_ioctl; void __user *tmp_compat_ioctl_ptr = NULL; rc = msm_copy_camera_private_ioctl_args(arg, &k_ioctl, &tmp_compat_ioctl_ptr); if (rc < 0) { pr_err("Subdev cmd %d failed\n", cmd); return rc; } switch (k_ioctl.id) { case MSM_CAMERA_PRIV_IOCTL_ID_RETURN_BUF: { if (k_ioctl.size != sizeof(struct msm_camera_return_buf)) { pr_debug("Invalid size for id %d with size %d", k_ioctl.id, k_ioctl.size); return -EINVAL; } k_ioctl.ioctl_ptr = (__u64)tmp_compat_ioctl_ptr; if (!k_ioctl.ioctl_ptr) { pr_debug("Invalid ptr for id %d", k_ioctl.id); return -EINVAL; } rc = camera_v4l2_vidioc_private_ioctl(file, file->private_data, 0, cmd, (void *)&k_ioctl); } break; default: pr_debug("unimplemented id %d", k_ioctl.id); return -EINVAL; } return rc; } long camera_v4l2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return -ENOIOCTLCMD; long ret = 0; switch (cmd) { case VIDIOC_MSM_CAMERA_PRIVATE_IOCTL_CMD: { ret = camera_handle_internal_compat_ioctl(file, cmd, arg); if (ret < 0) { pr_debug("Subdev cmd %d fail\n", cmd); return ret; } } break; default: ret = -ENOIOCTLCMD; break; } return ret; } #endif static struct v4l2_file_operations camera_v4l2_fops = { Loading
drivers/media/platform/msm/camera_v2/fd/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -3,5 +3,6 @@ ccflags-y += -Idrivers/media/video/msm ccflags-y += -Idrivers/media/platform/msm/camera_v2/common ccflags-y += -Idrivers/media/platform/msm/camera_v2 ccflags-y += -Idrivers/media/platform/msm/camera_v2/pproc/cpp ccflags-y += -Idrivers/media/platform/msm/camera_v2/msm_buf_mgr/ obj-$(CONFIG_MSM_FD) += msm_fd_dev.o msm_fd_hw.o
drivers/media/platform/msm/camera_v2/msm.c +22 −0 Original line number Diff line number Diff line Loading @@ -1088,6 +1088,28 @@ struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q) } EXPORT_SYMBOL(msm_get_stream_from_vb2q); #ifdef CONFIG_COMPAT long msm_copy_camera_private_ioctl_args(unsigned long arg, struct msm_camera_private_ioctl_arg *k_ioctl, void __user **tmp_compat_ioctl_ptr) { struct msm_camera_private_ioctl_arg *up_ioctl_ptr = (struct msm_camera_private_ioctl_arg *)arg; if (WARN_ON(!arg || !k_ioctl || !tmp_compat_ioctl_ptr)) return -EIO; k_ioctl->id = up_ioctl_ptr->id; k_ioctl->size = up_ioctl_ptr->size; k_ioctl->result = up_ioctl_ptr->result; k_ioctl->reserved = up_ioctl_ptr->reserved; *tmp_compat_ioctl_ptr = compat_ptr(up_ioctl_ptr->ioctl_ptr); return 0; } EXPORT_SYMBOL(msm_copy_camera_private_ioctl_args); #endif static void msm_sd_notify(struct v4l2_subdev *sd, unsigned int notification, void *arg) { Loading
drivers/media/platform/msm/camera_v2/msm.h +6 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2016, The Linux Foundation. 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 Loading Loading @@ -127,4 +127,9 @@ struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id, unsigned int stream_id); struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q); struct msm_session *msm_session_find(unsigned int session_id); #ifdef CONFIG_COMPAT long msm_copy_camera_private_ioctl_args(unsigned long arg, struct msm_camera_private_ioctl_arg *k_ioctl, void __user **tmp_compat_ioctl_ptr); #endif #endif /*_MSM_H */
drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c +268 −48 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ static int32_t msm_buf_mngr_hdl_cont_get_buf(struct msm_buf_mngr_device *dev, } return 0; } static int32_t msm_buf_mngr_get_buf(struct msm_buf_mngr_device *dev, void __user *argp) { Loading Loading @@ -91,6 +92,51 @@ static int32_t msm_buf_mngr_get_buf(struct msm_buf_mngr_device *dev, return rc; } static int32_t msm_buf_mngr_get_buf_by_idx(struct msm_buf_mngr_device *dev, void *argp) { unsigned long flags; int32_t rc = 0; struct msm_buf_mngr_info *buf_info = (struct msm_buf_mngr_info *)argp; struct msm_get_bufs *new_entry = kzalloc(sizeof(struct msm_get_bufs), GFP_KERNEL); if (!new_entry) { pr_err("%s:No mem\n", __func__); return -ENOMEM; } if (WARN_ON(!buf_info)) return -EIO; INIT_LIST_HEAD(&new_entry->entry); new_entry->vb2_buf = dev->vb2_ops.get_buf_by_idx(buf_info->session_id, buf_info->stream_id, buf_info->index); if (!new_entry->vb2_buf) { pr_debug("%s:Get buf is null\n", __func__); kfree(new_entry); return -EINVAL; } new_entry->session_id = buf_info->session_id; new_entry->stream_id = buf_info->stream_id; new_entry->index = new_entry->vb2_buf->v4l2_buf.index; spin_lock_irqsave(&dev->buf_q_spinlock, flags); list_add_tail(&new_entry->entry, &dev->buf_qhead); spin_unlock_irqrestore(&dev->buf_q_spinlock, flags); if (buf_info->type == MSM_CAMERA_BUF_MNGR_BUF_USER) { mutex_lock(&dev->cont_mutex); if (!list_empty(&dev->cont_qhead)) { rc = msm_buf_mngr_hdl_cont_get_buf(dev, buf_info); } else { pr_err("Nothing mapped in user buf for %d,%d\n", buf_info->session_id, buf_info->stream_id); rc = -EINVAL; } mutex_unlock(&dev->cont_mutex); } return rc; } static int32_t msm_buf_mngr_buf_done(struct msm_buf_mngr_device *buf_mngr_dev, struct msm_buf_mngr_info *buf_info) { Loading Loading @@ -410,6 +456,67 @@ static int msm_generic_buf_mngr_close(struct v4l2_subdev *sd, return rc; } int msm_cam_buf_mgr_ops(unsigned int cmd, void *argp) { int rc = 0; if (!msm_buf_mngr_dev) return -ENODEV; if (!argp) return -EINVAL; switch (cmd) { case VIDIOC_MSM_BUF_MNGR_GET_BUF: rc = msm_buf_mngr_get_buf(msm_buf_mngr_dev, argp); break; case VIDIOC_MSM_BUF_MNGR_BUF_DONE: rc = msm_buf_mngr_buf_done(msm_buf_mngr_dev, argp); break; case VIDIOC_MSM_BUF_MNGR_PUT_BUF: rc = msm_buf_mngr_put_buf(msm_buf_mngr_dev, argp); break; case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD: { struct msm_camera_private_ioctl_arg *k_ioctl = argp; switch (k_ioctl->id) { case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: { struct msm_buf_mngr_info *tmp = NULL; if (!k_ioctl->ioctl_ptr) return -EINVAL; if (k_ioctl->size != sizeof(struct msm_buf_mngr_info)) return -EINVAL; MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl->ioctl_ptr, sizeof(tmp)); rc = msm_buf_mngr_get_buf_by_idx(msm_buf_mngr_dev, tmp); } break; default: pr_debug("unimplemented id %d", k_ioctl->id); return -EINVAL; } break; } default: return -ENOIOCTLCMD; } return rc; } int msm_cam_buf_mgr_register_ops(struct msm_cam_buf_mgr_req_ops *cb_struct) { if (!msm_buf_mngr_dev) return -ENODEV; if (!cb_struct) return -EINVAL; cb_struct->msm_cam_buf_mgr_ops = msm_cam_buf_mgr_ops; return 0; } static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { Loading @@ -422,16 +529,45 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd, rc = -ENOMEM; return rc; } switch (cmd) { case VIDIOC_MSM_BUF_MNGR_GET_BUF: rc = msm_buf_mngr_get_buf(buf_mngr_dev, argp); case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD: { struct msm_camera_private_ioctl_arg k_ioctl, *ptr; if (!arg) return -EINVAL; ptr = arg; k_ioctl = *ptr; switch (k_ioctl.id) { case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: { struct msm_buf_mngr_info buf_info, *tmp = NULL; if (k_ioctl.size != sizeof(struct msm_buf_mngr_info)) return -EINVAL; if (!k_ioctl.ioctl_ptr) return -EINVAL; MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl.ioctl_ptr, sizeof(tmp)); if (copy_from_user(&buf_info, tmp, sizeof(struct msm_buf_mngr_info))) { return -EFAULT; } MSM_CAM_GET_IOCTL_ARG_PTR(&k_ioctl.ioctl_ptr, &buf_info, sizeof(void *)); argp = &k_ioctl; rc = msm_cam_buf_mgr_ops(cmd, argp); } break; case VIDIOC_MSM_BUF_MNGR_BUF_DONE: rc = msm_buf_mngr_buf_done(buf_mngr_dev, argp); default: pr_debug("unimplemented id %d", k_ioctl.id); return -EINVAL; } } break; case VIDIOC_MSM_BUF_MNGR_GET_BUF: case VIDIOC_MSM_BUF_MNGR_BUF_DONE: case VIDIOC_MSM_BUF_MNGR_PUT_BUF: rc = msm_buf_mngr_put_buf(buf_mngr_dev, argp); rc = msm_cam_buf_mgr_ops(cmd, argp); break; case VIDIOC_MSM_BUF_MNGR_INIT: rc = msm_generic_buf_mngr_open(sd, NULL); Loading Loading @@ -459,6 +595,105 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd, } #ifdef CONFIG_COMPAT static long msm_camera_buf_mgr_fetch_buf_info( struct msm_buf_mngr_info32_t *buf_info32, struct msm_buf_mngr_info *buf_info, unsigned long arg) { WARN_ON(!arg || !buf_info32 || !buf_info); if (copy_from_user(buf_info32, (void __user *)arg, sizeof(struct msm_buf_mngr_info32_t))) return -EFAULT; buf_info->session_id = buf_info32->session_id; buf_info->stream_id = buf_info32->stream_id; buf_info->frame_id = buf_info32->frame_id; buf_info->index = buf_info32->index; buf_info->timestamp.tv_sec = (long) buf_info32->timestamp.tv_sec; buf_info->timestamp.tv_usec = (long) buf_info32-> timestamp.tv_usec; buf_info->reserved = buf_info32->reserved; buf_info->type = buf_info32->type; return 0; } static long msm_camera_buf_mgr_update_buf_info( struct msm_buf_mngr_info32_t *buf_info32, struct msm_buf_mngr_info *buf_info, unsigned long arg) { WARN_ON(!arg || !buf_info32 || !buf_info); buf_info32->session_id = buf_info->session_id; buf_info32->stream_id = buf_info->stream_id; buf_info32->index = buf_info->index; buf_info32->timestamp.tv_sec = (int32_t) buf_info-> timestamp.tv_sec; buf_info32->timestamp.tv_usec = (int32_t) buf_info->timestamp. tv_usec; buf_info32->reserved = buf_info->reserved; buf_info32->type = buf_info->type; buf_info32->user_buf.buf_cnt = buf_info->user_buf.buf_cnt; memcpy(&buf_info32->user_buf.buf_idx, &buf_info->user_buf.buf_idx, sizeof(buf_info->user_buf.buf_idx)); if (copy_to_user((void __user *)arg, buf_info32, sizeof(struct msm_buf_mngr_info32_t))) return -EFAULT; return 0; } static long msm_camera_buf_mgr_internal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); long rc = 0; struct msm_camera_private_ioctl_arg k_ioctl; void __user *tmp_compat_ioctl_ptr = NULL; rc = msm_copy_camera_private_ioctl_args(arg, &k_ioctl, &tmp_compat_ioctl_ptr); if (rc < 0) { pr_err("Subdev cmd %d failed\n", cmd); return rc; } switch (k_ioctl.id) { case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: { struct msm_buf_mngr_info32_t buf_info32; struct msm_buf_mngr_info buf_info; if (k_ioctl.size != sizeof(struct msm_buf_mngr_info32_t)) { pr_err("Invalid size for id %d with size %d", k_ioctl.id, k_ioctl.size); return -EINVAL; } if (!tmp_compat_ioctl_ptr) { pr_err("Invalid ptr for id %d", k_ioctl.id); return -EINVAL; } k_ioctl.ioctl_ptr = (__u64)&buf_info; rc = msm_camera_buf_mgr_fetch_buf_info(&buf_info32, &buf_info, (unsigned long)tmp_compat_ioctl_ptr); if (rc < 0) { pr_err("Fetch buf info failed for cmd=%d", cmd); return rc; } rc = v4l2_subdev_call(sd, core, ioctl, cmd, &k_ioctl); if (rc < 0) { pr_err("Subdev cmd %d failed for id %d", cmd, k_ioctl.id); return rc; } } break; default: pr_debug("unimplemented id %d", k_ioctl.id); return -EINVAL; } return 0; } static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { Loading @@ -466,8 +701,6 @@ static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file, struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); int32_t rc = 0; void __user *up = (void __user *)arg; /* Convert 32 bit IOCTL ID's to 64 bit IOCTL ID's * except VIDIOC_MSM_CPP_CFG32, which needs special * processing Loading @@ -483,13 +716,14 @@ static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file, cmd = VIDIOC_MSM_BUF_MNGR_PUT_BUF; break; case VIDIOC_MSM_BUF_MNGR_CONT_CMD: cmd = VIDIOC_MSM_BUF_MNGR_CONT_CMD; break; case VIDIOC_MSM_BUF_MNGR_FLUSH32: cmd = VIDIOC_MSM_BUF_MNGR_FLUSH; break; case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD: break; default: pr_debug("%s : unsupported compat type", __func__); pr_debug("unsupported compat type\n"); return -ENOIOCTLCMD; } Loading @@ -501,65 +735,51 @@ static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file, struct msm_buf_mngr_info32_t buf_info32; struct msm_buf_mngr_info buf_info; if (copy_from_user(&buf_info32, (void __user *)up, sizeof(struct msm_buf_mngr_info32_t))) return -EFAULT; buf_info.session_id = buf_info32.session_id; buf_info.stream_id = buf_info32.stream_id; buf_info.frame_id = buf_info32.frame_id; buf_info.index = buf_info32.index; buf_info.timestamp.tv_sec = (long) buf_info32.timestamp.tv_sec; buf_info.timestamp.tv_usec = (long) buf_info32. timestamp.tv_usec; buf_info.reserved = buf_info32.reserved; buf_info.type = buf_info32.type; rc = msm_camera_buf_mgr_fetch_buf_info(&buf_info32, &buf_info, arg); if (rc < 0) { pr_err("Fetch buf info failed for cmd=%d\n", cmd); return rc; } rc = v4l2_subdev_call(sd, core, ioctl, cmd, &buf_info); if (rc < 0) { pr_debug("%s : Subdev cmd %d fail", __func__, cmd); pr_debug("Subdev cmd %d fail\n", cmd); return rc; } rc = msm_camera_buf_mgr_update_buf_info(&buf_info32, &buf_info, arg); if (rc < 0) { pr_err("Update buf info failed for cmd=%d\n", cmd); return rc; } } break; case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD: { rc = msm_camera_buf_mgr_internal_compat_ioctl(file, cmd, arg); if (rc < 0) { pr_debug("Subdev cmd %d fail\n", cmd); return rc; } buf_info32.session_id = buf_info.session_id; buf_info32.stream_id = buf_info.stream_id; buf_info32.index = buf_info.index; buf_info32.timestamp.tv_sec = (int32_t) buf_info. timestamp.tv_sec; buf_info32.timestamp.tv_usec = (int32_t) buf_info.timestamp. tv_usec; buf_info32.reserved = buf_info.reserved; buf_info32.type = buf_info.type; buf_info32.user_buf.buf_cnt = buf_info.user_buf.buf_cnt; memcpy(&buf_info32.user_buf.buf_idx, &buf_info.user_buf.buf_idx, sizeof(buf_info.user_buf.buf_idx)); if (copy_to_user((void __user *)up, &buf_info32, sizeof(struct msm_buf_mngr_info32_t))) return -EFAULT; } break; case VIDIOC_MSM_BUF_MNGR_CONT_CMD: { struct msm_buf_mngr_main_cont_info cont_cmd; if (copy_from_user(&cont_cmd, (void __user *)up, if (copy_from_user(&cont_cmd, (void __user *)arg, sizeof(struct msm_buf_mngr_main_cont_info))) return -EFAULT; rc = v4l2_subdev_call(sd, core, ioctl, cmd, &cont_cmd); if (rc < 0) { pr_debug("%s : Subdev cmd %d fail", __func__, cmd); pr_debug("Subdev cmd %d fail\n", cmd); return rc; } } break; default: pr_debug("%s : unsupported compat type", __func__); pr_debug("unsupported compat type\n"); return -ENOIOCTLCMD; break; } return 0; } #endif Loading