| /* |
| * Copyright (C) 2013 Paul Kocialkowski |
| * |
| * Based on crespo libcamera and exynos4 hal libcamera: |
| * Copyright 2008, The Android Open Source Project |
| * Copyright 2010, Samsung Electronics Co. LTD |
| * |
| * 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 3 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, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include <malloc.h> |
| #include <poll.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #include <sys/time.h> |
| #include <sys/mman.h> |
| #include <sys/ioctl.h> |
| |
| #include <asm/types.h> |
| |
| #define LOG_TAG "exynos_v4l2" |
| #include <utils/Log.h> |
| |
| #include "exynos_camera.h" |
| |
| int exynos_v4l2_init(struct exynos_camera *exynos_camera) |
| { |
| int i; |
| |
| for (i = 0; i < EXYNOS_CAMERA_MAX_V4L2_NODES_COUNT; i++) |
| exynos_camera->v4l2_fds[i] = -1; |
| |
| return 0; |
| } |
| |
| int exynos_v4l2_index(struct exynos_camera *exynos_camera, int exynos_v4l2_id) |
| { |
| int index; |
| int i; |
| |
| if (exynos_camera == NULL || exynos_camera->config == NULL || |
| exynos_camera->config->v4l2_nodes == NULL) |
| return -EINVAL; |
| |
| if (exynos_v4l2_id > exynos_camera->config->v4l2_nodes_count) |
| return -1; |
| |
| index = -1; |
| for (i = 0; i < exynos_camera->config->v4l2_nodes_count; i++) { |
| if (exynos_camera->config->v4l2_nodes[i].id == exynos_v4l2_id && |
| exynos_camera->config->v4l2_nodes[i].node != NULL) { |
| index = i; |
| } |
| } |
| |
| return index; |
| } |
| |
| int exynos_v4l2_fd(struct exynos_camera *exynos_camera, int exynos_v4l2_id) |
| { |
| int index; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| index = exynos_v4l2_index(exynos_camera, exynos_v4l2_id); |
| if (index < 0) { |
| ALOGE("%s: Unable to get v4l2 index for id %d", __func__, exynos_v4l2_id); |
| return -1; |
| } |
| |
| return exynos_camera->v4l2_fds[index]; |
| } |
| |
| int exynos_v4l2_open(struct exynos_camera *exynos_camera, int exynos_v4l2_id) |
| { |
| char *node; |
| int index; |
| int fd; |
| |
| if (exynos_camera == NULL || exynos_camera->config == NULL || |
| exynos_camera->config->v4l2_nodes == NULL) |
| return -EINVAL; |
| |
| index = exynos_v4l2_index(exynos_camera, exynos_v4l2_id); |
| if (index < 0) { |
| ALOGE("%s: Unable to get v4l2 node for id %d", __func__, exynos_v4l2_id); |
| return -1; |
| } |
| |
| node = exynos_camera->config->v4l2_nodes[index].node; |
| fd = open(node, O_RDWR); |
| if (fd < 0) { |
| ALOGE("%s: Unable to open v4l2 node for id %d", __func__, exynos_v4l2_id); |
| return -1; |
| } |
| |
| exynos_camera->v4l2_fds[index] = fd; |
| |
| return 0; |
| } |
| |
| void exynos_v4l2_close(struct exynos_camera *exynos_camera, int exynos_v4l2_id) |
| { |
| int index; |
| |
| if (exynos_camera == NULL || exynos_camera->config == NULL || |
| exynos_camera->config->v4l2_nodes == NULL) |
| return; |
| |
| index = exynos_v4l2_index(exynos_camera, exynos_v4l2_id); |
| if (index < 0) { |
| ALOGE("%s: Unable to get v4l2 node for id %d", __func__, exynos_v4l2_id); |
| return; |
| } |
| |
| if (exynos_camera->v4l2_fds[index] >= 0) |
| close(exynos_camera->v4l2_fds[index]); |
| |
| exynos_camera->v4l2_fds[index] = -1; |
| } |
| |
| int exynos_v4l2_ioctl(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| int request, void *data) |
| { |
| int fd; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| fd = exynos_v4l2_fd(exynos_camera, exynos_v4l2_id); |
| if (fd < 0) { |
| ALOGE("%s: Unable to get v4l2 fd for id %d", __func__, exynos_v4l2_id); |
| return -1; |
| } |
| |
| return ioctl(fd, request, data); |
| } |
| |
| int exynos_v4l2_poll(struct exynos_camera *exynos_camera, int exynos_v4l2_id) |
| { |
| struct pollfd events; |
| int fd; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| fd = exynos_v4l2_fd(exynos_camera, exynos_v4l2_id); |
| if (fd < 0) { |
| ALOGE("%s: Unable to get v4l2 fd for id %d", __func__, exynos_v4l2_id); |
| return -1; |
| } |
| |
| memset(&events, 0, sizeof(events)); |
| events.fd = fd; |
| events.events = POLLIN | POLLERR; |
| |
| rc = poll(&events, 1, 1000); |
| if (rc < 0 || events.revents & POLLERR) |
| return -1; |
| |
| return rc; |
| } |
| |
| int exynos_v4l2_qbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| int type, int memory, int index, unsigned long userptr) |
| { |
| struct v4l2_buffer buffer; |
| int rc; |
| |
| if (exynos_camera == NULL || index < 0) |
| return -EINVAL; |
| |
| memset(&buffer, 0, sizeof(buffer)); |
| buffer.type = type; |
| buffer.memory = memory; |
| buffer.index = index; |
| |
| if (userptr) |
| buffer.m.userptr = userptr; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_QBUF, &buffer); |
| return rc; |
| } |
| |
| int exynos_v4l2_qbuf_cap(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| int index) |
| { |
| return exynos_v4l2_qbuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
| V4L2_MEMORY_MMAP, index, 0); |
| } |
| |
| int exynos_v4l2_qbuf_out(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| int index, unsigned long userptr) |
| { |
| return exynos_v4l2_qbuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
| V4L2_MEMORY_USERPTR, index, userptr); |
| } |
| |
| int exynos_v4l2_dqbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| int type, int memory) |
| { |
| struct v4l2_buffer buffer; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| memset(&buffer, 0, sizeof(buffer)); |
| buffer.type = type; |
| buffer.memory = memory; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_DQBUF, &buffer); |
| if (rc < 0) |
| return rc; |
| |
| return buffer.index; |
| } |
| |
| int exynos_v4l2_s_ext_ctrl_face_detection(struct exynos_camera *exynos_camera, |
| int id, void *value) |
| { |
| struct v4l2_ext_control ext_ctrl_fd[111]; |
| struct v4l2_ext_controls ext_ctrls_fd; |
| struct v4l2_ext_controls *ctrls; |
| camera_frame_metadata_t *facedata = (camera_frame_metadata_t *)value; |
| int i, ret; |
| |
| ext_ctrl_fd[0].id = V4L2_CID_IS_FD_GET_FACE_COUNT; |
| for (i = 0; i < exynos_camera->max_detected_faces; i++) { |
| ext_ctrl_fd[22*i+1].id = V4L2_CID_IS_FD_GET_FACE_FRAME_NUMBER; |
| ext_ctrl_fd[22*i+2].id = V4L2_CID_IS_FD_GET_FACE_CONFIDENCE; |
| ext_ctrl_fd[22*i+3].id = V4L2_CID_IS_FD_GET_FACE_SMILE_LEVEL; |
| ext_ctrl_fd[22*i+4].id = V4L2_CID_IS_FD_GET_FACE_BLINK_LEVEL; |
| ext_ctrl_fd[22*i+5].id = V4L2_CID_IS_FD_GET_FACE_TOPLEFT_X; |
| ext_ctrl_fd[22*i+6].id = V4L2_CID_IS_FD_GET_FACE_TOPLEFT_Y; |
| ext_ctrl_fd[22*i+7].id = V4L2_CID_IS_FD_GET_FACE_BOTTOMRIGHT_X; |
| ext_ctrl_fd[22*i+8].id = V4L2_CID_IS_FD_GET_FACE_BOTTOMRIGHT_Y; |
| ext_ctrl_fd[22*i+9].id = V4L2_CID_IS_FD_GET_LEFT_EYE_TOPLEFT_X; |
| ext_ctrl_fd[22*i+10].id = V4L2_CID_IS_FD_GET_LEFT_EYE_TOPLEFT_Y; |
| ext_ctrl_fd[22*i+11].id = V4L2_CID_IS_FD_GET_LEFT_EYE_BOTTOMRIGHT_X; |
| ext_ctrl_fd[22*i+12].id = V4L2_CID_IS_FD_GET_LEFT_EYE_BOTTOMRIGHT_Y; |
| ext_ctrl_fd[22*i+13].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_TOPLEFT_X; |
| ext_ctrl_fd[22*i+14].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_TOPLEFT_Y; |
| ext_ctrl_fd[22*i+15].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_BOTTOMRIGHT_X; |
| ext_ctrl_fd[22*i+16].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_BOTTOMRIGHT_Y; |
| ext_ctrl_fd[22*i+17].id = V4L2_CID_IS_FD_GET_MOUTH_TOPLEFT_X; |
| ext_ctrl_fd[22*i+18].id = V4L2_CID_IS_FD_GET_MOUTH_TOPLEFT_Y; |
| ext_ctrl_fd[22*i+19].id = V4L2_CID_IS_FD_GET_MOUTH_BOTTOMRIGHT_X; |
| ext_ctrl_fd[22*i+20].id = V4L2_CID_IS_FD_GET_MOUTH_BOTTOMRIGHT_Y; |
| ext_ctrl_fd[22*i+21].id = V4L2_CID_IS_FD_GET_ANGLE; |
| ext_ctrl_fd[22*i+22].id = V4L2_CID_IS_FD_GET_NEXT; |
| } |
| |
| ext_ctrls_fd.ctrl_class = V4L2_CTRL_CLASS_CAMERA; |
| ext_ctrls_fd.count = 111; |
| ext_ctrls_fd.controls = ext_ctrl_fd; |
| ctrls = &ext_ctrls_fd; |
| |
| ret = exynos_v4l2_ioctl(exynos_camera, id, VIDIOC_G_EXT_CTRLS, &ext_ctrls_fd); |
| |
| facedata->number_of_faces = ext_ctrls_fd.controls[0].value; |
| |
| for(i = 0; i < facedata->number_of_faces; i++) { |
| facedata->faces[i].rect[0] = ext_ctrl_fd[22*i+5].value; |
| facedata->faces[i].rect[1] = ext_ctrl_fd[22*i+6].value; |
| facedata->faces[i].rect[2] = ext_ctrl_fd[22*i+7].value; |
| facedata->faces[i].rect[3] = ext_ctrl_fd[22*i+8].value; |
| facedata->faces[i].score = ext_ctrl_fd[22*i+2].value; |
| /* TODO : id is unique value for each face. We need to suppot this. */ |
| facedata->faces[i].id = 0; |
| facedata->faces[i].left_eye[0] = (ext_ctrl_fd[22*i+9].value + ext_ctrl_fd[22*i+11].value) / 2; |
| facedata->faces[i].left_eye[1] = (ext_ctrl_fd[22*i+10].value + ext_ctrl_fd[22*i+12].value) / 2; |
| facedata->faces[i].right_eye[0] = (ext_ctrl_fd[22*i+13].value + ext_ctrl_fd[22*i+15].value) / 2; |
| facedata->faces[i].right_eye[1] = (ext_ctrl_fd[22*i+14].value + ext_ctrl_fd[22*i+16].value) / 2; |
| facedata->faces[i].mouth[0] = (ext_ctrl_fd[22*i+17].value + ext_ctrl_fd[22*i+19].value) / 2; |
| facedata->faces[i].mouth[1] = (ext_ctrl_fd[22*i+18].value + ext_ctrl_fd[22*i+20].value) / 2; |
| } |
| |
| return ret; |
| } |
| |
| int exynos_v4l2_dqbuf_cap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id) |
| { |
| return exynos_v4l2_dqbuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
| V4L2_MEMORY_MMAP); |
| } |
| |
| int exynos_v4l2_dqbuf_out(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id) |
| { |
| return exynos_v4l2_dqbuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
| V4L2_MEMORY_USERPTR); |
| } |
| |
| int exynos_v4l2_reqbufs(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int type, int memory, int count) |
| { |
| struct v4l2_requestbuffers requestbuffers; |
| int rc; |
| |
| if (exynos_camera == NULL || count < 0) |
| return -EINVAL; |
| |
| requestbuffers.type = type; |
| requestbuffers.count = count; |
| requestbuffers.memory = memory; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_REQBUFS, &requestbuffers); |
| if (rc < 0) |
| return rc; |
| |
| return requestbuffers.count; |
| } |
| |
| int exynos_v4l2_reqbufs_cap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int count) |
| { |
| return exynos_v4l2_reqbufs(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
| V4L2_MEMORY_MMAP, count); |
| } |
| |
| int exynos_v4l2_reqbufs_out(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int count) |
| { |
| return exynos_v4l2_reqbufs(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
| V4L2_MEMORY_USERPTR, count); |
| } |
| |
| int exynos_v4l2_querybuf(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int type, int memory, int index) |
| { |
| struct v4l2_buffer buffer; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| memset(&buffer, 0, sizeof(buffer)); |
| buffer.type = type; |
| buffer.memory = memory; |
| buffer.index = index; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_QUERYBUF, &buffer); |
| if (rc < 0) |
| return rc; |
| |
| return buffer.length; |
| } |
| |
| int exynos_v4l2_querybuf_cap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int index) |
| { |
| return exynos_v4l2_querybuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
| V4L2_MEMORY_MMAP, index); |
| } |
| |
| int exynos_v4l2_querybuf_out(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int index) |
| { |
| return exynos_v4l2_querybuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
| V4L2_MEMORY_USERPTR, index); |
| } |
| |
| int exynos_v4l2_querycap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int flags) |
| { |
| struct v4l2_capability cap; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_QUERYCAP, &cap); |
| if (rc < 0) |
| return rc; |
| |
| if (!(cap.capabilities & flags)) |
| return -1; |
| |
| return 0; |
| } |
| |
| int exynos_v4l2_querycap_cap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id) |
| { |
| return exynos_v4l2_querycap(exynos_camera, exynos_v4l2_id, V4L2_CAP_VIDEO_CAPTURE); |
| } |
| |
| int exynos_v4l2_querycap_out(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id) |
| { |
| return exynos_v4l2_querycap(exynos_camera, exynos_v4l2_id, V4L2_CAP_VIDEO_OUTPUT); |
| } |
| |
| int exynos_v4l2_streamon(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int type) |
| { |
| enum v4l2_buf_type buf_type; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| buf_type = type; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_STREAMON, &buf_type); |
| return rc; |
| } |
| |
| int exynos_v4l2_streamon_cap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id) |
| { |
| return exynos_v4l2_streamon(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
| } |
| |
| int exynos_v4l2_streamon_out(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id) |
| { |
| return exynos_v4l2_streamon(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
| } |
| |
| int exynos_v4l2_streamoff(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int type) |
| { |
| enum v4l2_buf_type buf_type; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| buf_type = type; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_STREAMOFF, &buf_type); |
| return rc; |
| } |
| |
| int exynos_v4l2_streamoff_cap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id) |
| { |
| return exynos_v4l2_streamoff(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
| } |
| |
| int exynos_v4l2_streamoff_out(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id) |
| { |
| return exynos_v4l2_streamoff(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
| } |
| |
| int exynos_v4l2_g_fmt(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| int type, int *width, int *height, int *fmt) |
| { |
| struct v4l2_format format; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| format.type = type; |
| format.fmt.pix.field = V4L2_FIELD_NONE; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_G_FMT, &format); |
| if (rc < 0) |
| return rc; |
| |
| if (width != NULL) |
| *width = format.fmt.pix.width; |
| if (height != NULL) |
| *height = format.fmt.pix.height; |
| if (fmt != NULL) |
| *fmt = format.fmt.pix.pixelformat; |
| |
| return 0; |
| } |
| |
| int exynos_v4l2_g_fmt_cap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int *width, int *height, int *fmt) |
| { |
| return exynos_v4l2_g_fmt(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
| width, height, fmt); |
| } |
| |
| int exynos_v4l2_g_fmt_out(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int *width, int *height, int *fmt) |
| { |
| return exynos_v4l2_g_fmt(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
| width, height, fmt); |
| } |
| |
| int exynos_v4l2_s_fmt_pix(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int type, int width, int height, int fmt, int field, |
| int priv) |
| { |
| struct v4l2_format format; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| memset(&format, 0, sizeof(format)); |
| format.type = type; |
| format.fmt.pix.width = width; |
| format.fmt.pix.height = height; |
| format.fmt.pix.pixelformat = fmt; |
| format.fmt.pix.field = field; |
| format.fmt.pix.priv = priv; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_FMT, &format); |
| return rc; |
| |
| return 0; |
| } |
| |
| int exynos_v4l2_s_fmt_pix_cap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int width, int height, int fmt, int priv) |
| { |
| return exynos_v4l2_s_fmt_pix(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
| width, height, fmt, V4L2_FIELD_NONE, priv); |
| } |
| |
| int exynos_v4l2_s_fmt_pix_out(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int width, int height, int fmt, int priv) |
| { |
| return exynos_v4l2_s_fmt_pix(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
| width, height, fmt, V4L2_FIELD_NONE, priv); |
| } |
| |
| int exynos_v4l2_s_fmt_win(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int left, int top, int width, int height) |
| { |
| struct v4l2_format format; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| memset(&format, 0, sizeof(format)); |
| format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; |
| format.fmt.win.w.left = left; |
| format.fmt.win.w.top = top; |
| format.fmt.win.w.width = width; |
| format.fmt.win.w.height = height; |
| |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_FMT, &format); |
| return rc; |
| } |
| |
| int exynos_v4l2_enum_fmt(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int type, int fmt) |
| { |
| struct v4l2_fmtdesc fmtdesc; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| fmtdesc.type = type; |
| fmtdesc.index = 0; |
| |
| do { |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_ENUM_FMT, &fmtdesc); |
| if (rc < 0) |
| return rc; |
| |
| if (fmtdesc.pixelformat == (unsigned int) fmt) |
| return 0; |
| |
| fmtdesc.index++; |
| } while (rc >= 0); |
| |
| return -1; |
| } |
| |
| int exynos_v4l2_enum_fmt_cap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int fmt) |
| { |
| return exynos_v4l2_enum_fmt(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
| fmt); |
| } |
| |
| int exynos_v4l2_enum_fmt_out(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int fmt) |
| { |
| return exynos_v4l2_enum_fmt(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
| fmt); |
| } |
| |
| int exynos_v4l2_enum_input(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int id) |
| { |
| struct v4l2_input input; |
| int rc; |
| |
| if (exynos_camera == NULL || id < 0) |
| return -EINVAL; |
| |
| input.index = id; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_ENUMINPUT, &input); |
| if (rc < 0) |
| return rc; |
| |
| if (input.name[0] == '\0') |
| return -1; |
| |
| return 0; |
| } |
| |
| int exynos_v4l2_s_input(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| int id) |
| { |
| struct v4l2_input input; |
| int rc; |
| |
| if (exynos_camera == NULL || id < 0) |
| return -EINVAL; |
| |
| input.index = id; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_INPUT, &input); |
| return rc; |
| } |
| |
| int exynos_v4l2_g_ext_ctrls(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, struct v4l2_ext_control *control, int count) |
| { |
| struct v4l2_ext_controls controls; |
| int rc; |
| |
| if (exynos_camera == NULL || control == NULL) |
| return -EINVAL; |
| |
| memset(&controls, 0, sizeof(controls)); |
| controls.ctrl_class = V4L2_CTRL_CLASS_CAMERA; |
| controls.count = count; |
| controls.controls = control; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_G_EXT_CTRLS, &controls); |
| return rc; |
| } |
| |
| int exynos_v4l2_g_ctrl(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| int id, int *value) |
| { |
| struct v4l2_control control; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| control.id = id; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_G_CTRL, &control); |
| if (rc < 0) |
| return rc; |
| |
| if (value != NULL) |
| *value = control.value; |
| |
| return 0; |
| } |
| |
| int exynos_v4l2_s_ctrl(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| int id, int value) |
| { |
| struct v4l2_control control; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| control.id = id; |
| control.value = value; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_CTRL, &control); |
| if (rc < 0) |
| return rc; |
| |
| return control.value; |
| } |
| |
| int exynos_v4l2_s_parm(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| int type, struct v4l2_streamparm *streamparm) |
| { |
| int rc; |
| |
| if (exynos_camera == NULL || streamparm == NULL) |
| return -EINVAL; |
| |
| streamparm->type = type; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_PARM, streamparm); |
| return rc; |
| } |
| |
| int exynos_v4l2_s_parm_cap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, struct v4l2_streamparm *streamparm) |
| { |
| return exynos_v4l2_s_parm(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
| streamparm); |
| } |
| |
| int exynos_v4l2_s_parm_out(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, struct v4l2_streamparm *streamparm) |
| { |
| return exynos_v4l2_s_parm(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
| streamparm); |
| } |
| |
| int exynos_v4l2_s_crop(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| int type, int left, int top, int width, int height) |
| { |
| struct v4l2_crop crop; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| crop.type = type; |
| crop.c.left = left; |
| crop.c.top = top; |
| crop.c.width = width; |
| crop.c.height = height; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_CROP, &crop); |
| return rc; |
| } |
| |
| int exynos_v4l2_s_crop_cap(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int left, int top, int width, int height) |
| { |
| return exynos_v4l2_s_crop(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
| left, top, width, height); |
| } |
| |
| int exynos_v4l2_s_crop_out(struct exynos_camera *exynos_camera, |
| int exynos_v4l2_id, int left, int top, int width, int height) |
| { |
| return exynos_v4l2_s_crop(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
| left, top, width, height); |
| } |
| |
| int exynos_v4l2_g_fbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| void **base, int *width, int *height, int *fmt) |
| { |
| struct v4l2_framebuffer framebuffer; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_G_FBUF, &framebuffer); |
| if (rc < 0) |
| return rc; |
| |
| if (base != NULL) |
| *base = framebuffer.base; |
| if (width != NULL) |
| *width = framebuffer.fmt.width; |
| if (height != NULL) |
| *height = framebuffer.fmt.height; |
| if (fmt != NULL) |
| *fmt = framebuffer.fmt.pixelformat; |
| |
| return 0; |
| } |
| |
| int exynos_v4l2_s_fbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, |
| void *base, int width, int height, int fmt) |
| { |
| struct v4l2_framebuffer framebuffer; |
| int rc; |
| |
| if (exynos_camera == NULL) |
| return -EINVAL; |
| |
| memset(&framebuffer, 0, sizeof(framebuffer)); |
| framebuffer.base = base; |
| framebuffer.fmt.width = width; |
| framebuffer.fmt.height = height; |
| framebuffer.fmt.pixelformat = fmt; |
| |
| rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_FBUF, &framebuffer); |
| return rc; |
| } |