diff options
Diffstat (limited to 'camerasrc/src/camerasrc-internal.c')
-rw-r--r-- | camerasrc/src/camerasrc-internal.c | 1463 |
1 files changed, 1463 insertions, 0 deletions
diff --git a/camerasrc/src/camerasrc-internal.c b/camerasrc/src/camerasrc-internal.c new file mode 100644 index 0000000..e820bd9 --- /dev/null +++ b/camerasrc/src/camerasrc-internal.c @@ -0,0 +1,1463 @@ +/* + * camerasrc + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang <jm80.yang@samsung.com> + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <math.h> +#include "camerasrc-internal.h" + +/*#define USE_IOCTL_DEBUG*/ +#if defined (USE_IOCTL_DEBUG) +static char* get_request_name(int request, char* res_str) { + switch (request) { + case VIDIOC_QBUF: + sprintf(res_str, "[VIDIOC_QBUF]"); + break; + case VIDIOC_DQBUF: + sprintf(res_str, "[VIDIOC_DQBUF]"); + break; + case VIDIOC_S_INPUT: + sprintf(res_str, "[VIDIOC_S_INPUT]"); + break; + case VIDIOC_G_INPUT: + sprintf(res_str, "[VIDIOC_G_INPUT]"); + break; + case VIDIOC_S_PARM: + sprintf(res_str, "[VIDIOC_S_PARM]"); + break; + case VIDIOC_G_PARM: + sprintf(res_str, "[VIDIOC_G_PARM]"); + break; + case VIDIOC_S_FMT: + sprintf(res_str, "[VIDIOC_S_FMT]"); + break; + case VIDIOC_G_FMT: + sprintf(res_str, "[VIDIOC_G_FMT]"); + break; + case VIDIOC_REQBUFS: + sprintf(res_str, "[VIDIOC_REQBUFS]"); + break; + case VIDIOC_QUERYBUF: + sprintf(res_str, "[VIDIOC_QUERYBUF]"); + break; + case VIDIOC_STREAMON: + sprintf(res_str, "[VIDIOC_STREAMON]"); + break; + case VIDIOC_STREAMOFF: + sprintf(res_str, "[VIDIOC_STREAMOFF]"); + break; + case VIDIOC_S_CTRL: + sprintf(res_str, "[VIDIOC_S_CTRL] "); + break; + case VIDIOC_G_CTRL: + sprintf(res_str, "[VIDIOC_G_CTRL]"); + break; + case VIDIOC_ENUMINPUT: + sprintf(res_str, "[VIDIOC_ENUMINPUT]"); + break; + case VIDIOC_S_JPEGCOMP: + sprintf(res_str, "[VIDIOC_S_JPEGCOMP]"); + break; + case VIDIOC_G_JPEGCOMP: + sprintf(res_str, "[VIDIOC_G_JPEGCOMP]"); + break; + /* Extension */ + case VIDIOC_S_STROBE: + sprintf(res_str, "[VIDIOC_S_STROBE]"); + break; + case VIDIOC_G_STROBE: + sprintf(res_str, "[VIDIOC_G_STROBE]"); + break; + case VIDIOC_S_RECOGNITION: + sprintf(res_str, "[VIDIOC_S_RECOGNITION]"); + break; + case VIDIOC_G_RECOGNITION: + sprintf(res_str, "[VIDIOC_G_RECOGNITION]"); + break; + case VIDIOC_G_EXIF: + sprintf(res_str, "[VIDIOC_G_EXIF]"); + break; + default: + sprintf(res_str, "[UNKNOWN IOCTL(%x)]", request); + break; + } + + return 0; +} + +#define PRINT_IOCTL_INFO(request, arg) {\ + char res_str[255];\ + get_request_name(request, res_str);\ + camsrc_info("[request : %s, argument address : %x]", res_str, arg);\ +} +#else + +#define PRINT_IOCTL_INFO(request, arg) + +#endif + + +#define LOCK(x) {\ + if(0 != pthread_mutex_lock(&(x->mutex))) {\ + camsrc_error("Mutex lock error");\ + camsrc_assert(0);\ + }\ +} + +#define UNLOCK(x) {\ + if(0 != pthread_mutex_unlock(&(x->mutex))) {\ + camsrc_error("Mutex unlock error");\ + camsrc_assert(0);\ + }\ +} + +#define AF_MUT_LOCK(p) {\ + if(0 != pthread_mutex_lock(&(p->af_mutex))) {\ + camsrc_error("AF Mutex locking error");\ + camsrc_assert(0);\ + }\ +} + +#define AF_MUT_UNLOCK(p) {\ + if(0 != pthread_mutex_unlock(&(p->af_mutex))) {\ + camsrc_error("AF Mutex unlocking error");\ + camsrc_assert(0);\ + }\ +} + +#define SET_CTRL_VAL(cid, in_value) {\ + int err = CAMERASRC_ERR_UNKNOWN;\ + struct v4l2_control control;\ + control.id = cid;\ + control.value = in_value;\ + camsrc_info("[VIDIOC_S_CTRL] >> [%x] request with value %d", cid, in_value); \ + err = _camerasrc_ioctl(handle, VIDIOC_S_CTRL, &control);\ + if(err != CAMERASRC_SUCCESS) {\ + return err;\ + }\ +} + +#define GET_CTRL_VAL(cid, ret_value) {\ + int err = CAMERASRC_ERR_UNKNOWN;\ + struct v4l2_control control;\ + control.id = cid;\ + err = _camerasrc_ioctl(handle, VIDIOC_G_CTRL, &control);\ + if(err != CAMERASRC_SUCCESS) {\ + return err;\ + }\ + ret_value = control.value;\ + camsrc_info("[VIDIOC_G_CTRL] << [%x] request with value %d", cid, ret_value); \ +} + +#define SET_CTRL_VAL_ERR(cid, in_value, err) {\ + struct v4l2_control control;\ + control.id = cid;\ + control.value = in_value;\ + camsrc_info("[VIDIOC_S_CTRL] >> [%x] request with value %d", cid, in_value); \ + _camerasrc_ioctl_with_err(handle, VIDIOC_S_CTRL, &control, &err);\ +} + +#define GET_CTRL_VAL_ERR(cid, ret_value, err) {\ + struct v4l2_control control;\ + control.id = cid;\ + _camerasrc_ioctl_with_err(handle, VIDIOC_G_CTRL, &control, &err);\ + ret_value = control.value;\ + camsrc_info("[VIDIOC_G_CTRL] << [%x] request with value %d", cid, ret_value); \ +} + +/* AF function */ +static int _camerasrc_start_autofocusing(camerasrc_handle_t *handle); +static int _camerasrc_stop_autofocusing(camerasrc_handle_t *handle); +static int _camerasrc_destroy_autofocusing(camerasrc_handle_t *handle); +static int _camerasrc_release_autofocusing(camerasrc_handle_t *handle); + + +int static af_retry_cnt = 0; + +static int _camerasrc_ioctl(camerasrc_handle_t *handle, int request, void *arg) +{ + int fd = handle->dev_fd; + int err; + int nAgain = 10; + char err_msg[CAMERASRC_ERRMSG_MAX_LEN] = {'\0',}; + + LOCK(handle); + + if (handle->check_esd == 1) { + camsrc_warning("ESD shock occured. All device control will success"); + UNLOCK(handle); + return CAMERASRC_SUCCESS; + } + + if (handle->dev_fd == CAMERASRC_DEV_FD_EMERGENCY_CLOSED) { + camsrc_warning("Device emergency closed. All device control will success"); + UNLOCK(handle); + return CAMERASRC_SUCCESS; + } + + PRINT_IOCTL_INFO(request, arg); + +again: + do { + err = ioctl (fd, request, arg); + } while (-1 == err && EINTR == errno); + + if (err != 0) { + handle->errnum = errno; + err = errno; + strerror_r(err, err_msg, CAMERASRC_ERRMSG_MAX_LEN); + camsrc_error("ioctl[%x] err : %s", request, err_msg); + if (err == EEXIST) { + camsrc_info("EEXIST occured, but can go."); + err = 0; + } else if (err == ENOENT) { + camsrc_info("ENOENT occured, but can go."); + err = 0; +#if defined (ENABLE_Q_ERROR) +#warning "ENABLE_Q_ERROR enabled" + } else if (request == VIDIOC_DQBUF) { + goto DQ_ERROR; + } else if (request == VIDIOC_QBUF) { + goto ENQ_ERROR; +#endif + } else if (err == EINVAL) { + camsrc_error("EINVAL occured, Shutdown"); + UNLOCK(handle); + return CAMERASRC_ERR_INVALID_PARAMETER; + } else if (err == EBUSY) { + camsrc_error("EBUSY occured, Shutdown"); + UNLOCK(handle); + return CAMERASRC_ERR_PRIVILEGE; + } else if (err == EAGAIN && nAgain--) { + goto again; + } else { + /* Why does this return SUCCESS? */ + camsrc_error("Unhandled exception occured on IOCTL"); + } + } + + UNLOCK(handle); + + return CAMERASRC_SUCCESS; + +#if defined (ENABLE_Q_ERROR) +DQ_ERROR: + camsrc_error("DQ Frame error occured"); + printf("DQ Frame error occured"); + UNLOCK(handle); + return CAMERASRC_ERR_INTERNAL; + +ENQ_ERROR: + camsrc_error("Q Frame error occured"); + printf("Q Frame error occured"); + UNLOCK(handle); + return CAMERASRC_ERR_INTERNAL; +#endif +} + + +static int _camerasrc_ioctl_with_err(camerasrc_handle_t *handle, int request, void *arg, int *error) +{ + int fd = handle->dev_fd; + int err; + char err_msg[CAMERASRC_ERRMSG_MAX_LEN] = {'\0',}; + + LOCK(handle); + + *error = 0; + + if (handle->check_esd == 1) { + camsrc_warning("ESD shock occured. All device control will success"); + UNLOCK(handle); + return CAMERASRC_SUCCESS; + } + + if (handle->dev_fd == CAMERASRC_DEV_FD_EMERGENCY_CLOSED) { + camsrc_warning("Device emergency closed. All device control will success"); + UNLOCK(handle); + return CAMERASRC_SUCCESS; + } + + PRINT_IOCTL_INFO(request, arg); + + do { + err = ioctl (fd, request, arg); + } while (-1 == err && EINTR == errno); + + if (err != 0) { + handle->errnum = errno; + *error = errno; + strerror_r(*error, err_msg, CAMERASRC_ERRMSG_MAX_LEN); + camsrc_error("ioctl[%x] err : %s", request, err_msg); + UNLOCK(handle); + return CAMERASRC_ERR_IO_CONTROL; + } + + UNLOCK(handle); + + return CAMERASRC_SUCCESS; +} + + +static int _camerasrc_ioctl_once(camerasrc_handle_t *handle, int request, void *arg) +{ + int fd = handle->dev_fd; + int err = -1; + int nAgain = 10; + char err_msg[CAMERASRC_ERRMSG_MAX_LEN] = {'\0',}; + + LOCK(handle); + + if (handle->check_esd == 1) { + camsrc_warning("ESD shock occured. All device control will success"); + UNLOCK(handle); + return CAMERASRC_SUCCESS; + } + + if (handle->dev_fd == CAMERASRC_DEV_FD_EMERGENCY_CLOSED) { + camsrc_warning("Device emergency closed. All device control will success"); + UNLOCK(handle); + return CAMERASRC_SUCCESS; + } + + PRINT_IOCTL_INFO(request, arg); + +again: + err = ioctl (fd, request, arg); + + if (err != 0) { + handle->errnum = errno; + err = errno; + strerror_r(err, err_msg, CAMERASRC_ERRMSG_MAX_LEN); + camsrc_error("ioctl[%x] err : %s", request, err_msg); + if (err == EEXIST) { + camsrc_info("EEXIST occured, but can go."); + err = 0; + } else if (err == ENOENT) { + camsrc_info("ENOENT occured, but can go."); + err = 0; +#if defined (ENABLE_Q_ERROR) +#warning "ENABLE_Q_ERROR enabled" + } else if (request == VIDIOC_DQBUF) { + goto DQ_ERROR; + } else if (request == VIDIOC_QBUF) { + goto ENQ_ERROR; +#endif + } else if (err == EINVAL) { + camsrc_error("EINVAL occured, Shutdown"); + UNLOCK(handle); + return CAMERASRC_ERR_INVALID_PARAMETER; + } else if (err == EAGAIN && nAgain--) { + goto again; + } else { + camsrc_error("Unhandled exception occured on IOCTL"); + } + } + + UNLOCK(handle); + + return CAMERASRC_SUCCESS; + +#if defined (ENABLE_Q_ERROR) +DQ_ERROR: + camsrc_error("DQ Frame error occured"); + printf("DQ Frame error occured"); + UNLOCK(handle); + return CAMERASRC_ERR_INTERNAL; + +ENQ_ERROR: + camsrc_error("Q Frame error occured"); + printf("Q Frame error occured"); + UNLOCK(handle); + return CAMERASRC_ERR_INTERNAL; +#endif +} + + +static int _camerasrc_skip_frame(camerasrc_handle_t *handle, long int timeout, int skip_frame) +{ + camerasrc_handle_t *p = NULL; + int err = CAMERASRC_ERR_UNKNOWN; + fd_set fds; + struct timeval tv; + int r; + int skip_frame_num = skip_frame; + + camsrc_error("enter"); + + p = handle; + + while (skip_frame_num--) { + camsrc_error("SKIP FRAME #%d", skip_frame-skip_frame_num+1); + + struct v4l2_buffer buf; + + FD_ZERO (&fds); + FD_SET (p->dev_fd, &fds); + + camsrc_error("************Still capture wait frame start"); + + /* Timeout. */ + tv.tv_sec = (long int)timeout/1000; + tv.tv_usec = timeout - tv.tv_sec * 1000; + + r = select (p->dev_fd + 1, &fds, NULL, NULL, &tv); + + if (-1 == r) { + if (EINTR == errno) { + return CAMERASRC_SUCCESS; + } + camsrc_error("select() failed."); + return CAMERASRC_ERR_INTERNAL; + } + + if (0 == r) { + camsrc_error("select() timeout."); + return CAMERASRC_ERR_DEVICE_WAIT_TIMEOUT; + } + + /**@note from samsung camera sample. *****************************************/ + /*SKIP FRAME START*/ + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = p->buffer_idx; + + if (-1 == _camerasrc_ioctl (p, VIDIOC_DQBUF, &buf)) { + switch (errno) { + case EAGAIN: + camsrc_info("VIDIOC_DQBUF [EAGAIN]"); + return CAMERASRC_SUCCESS; + case EIO: + /* Could ignore EIO, see spec. */ + /* fall through */ + camsrc_info("VIDIOC_DQBUF [EIO]"); + default: + camsrc_info("VIDIOC_DQBUF [%d]", errno); + return CAMERASRC_ERR_IO_CONTROL; + } + } + + if (-1 == _camerasrc_ioctl (p, VIDIOC_QBUF, &buf)) { + return CAMERASRC_ERR_IO_CONTROL; + } + } + + camsrc_error("leave"); + err = CAMERASRC_SUCCESS; + + return err; +} + +static int _camerasrc_init_autofocusing_mode(camerasrc_handle_t *handle) +{ + int ctrl_id = V4L2_CID_FOCUS_AUTO_MODE; + int mode; + + camsrc_info("enter"); + + if (handle->af_status == CAMERASRC_AUTO_FOCUS_STATUS_ONGOING) { + camsrc_info("Dev BUSY. Init failed."); + return CAMERASRC_ERR_INVALID_STATE; + } + + switch (handle->cur_af_mode) { + case CAMERASRC_AF_MODE_AUTO: + mode = V4L2_FOCUS_AUTO_NORMAL; + camsrc_info("ON AUTOFOCUSING...BY AUTO"); + break; + case CAMERASRC_AF_MODE_MANUAL: + ctrl_id = V4L2_CID_FOCUS_MODE; + mode = V4L2_FOCUS_MODE_MANUAL; + camsrc_info("ON AUTOFOCUSING...BY MANUAL"); + break; + case CAMERASRC_AF_MODE_CONTINUOUS: + mode = V4L2_FOCUS_AUTO_CONTINUOUS; + camsrc_info("ON AUTOFOCUSING...BY CONTINUOUS"); + if (handle->format.pix_format != CAMERASRC_PIX_NV12 && + handle->format.pix_format != CAMERASRC_PIX_SN12) { + camsrc_info("DO NOT CONTINUOUS AF when NV12 or SN12 format"); + return CAMERASRC_SUCCESS; + } + break; + case CAMERASRC_AF_MODE_TOUCH_AUTO: + mode = V4L2_FOCUS_AUTO_RECTANGLE; + camsrc_info("ON AUTOFOCUSING...BY TOUCH AUTO"); + break; + case CAMERASRC_AF_MODE_PAN: + camsrc_warning("PAN MODE focusing is not supported."); + default: + camsrc_warning("Unsupported AF mode[%d]", handle->cur_af_mode ); + return CAMERASRC_ERR_DEVICE_NOT_SUPPORT; + } + + /* MACRO is prior than other setting. FIXME */ + if (handle->cur_af_range == CAMERASRC_AF_RANGE_MACRO) { + mode = V4L2_FOCUS_AUTO_MACRO; + camsrc_info("ON AUTOFOCUSING...BY MACRO"); + } + + SET_CTRL_VAL(ctrl_id, mode); + + /* Start AF if continuous mode and preview is running */ + if (mode == V4L2_FOCUS_AUTO_CONTINUOUS && + handle->cur_state >= CAMERASRC_STATE_PREVIEW) { + _camerasrc_start_autofocusing(handle); + } + + return CAMERASRC_SUCCESS; +} + +static void __CAMERASRC_FUJITSU_GET_AF_CTRL_VAL(camerasrc_handle_t* handle, int* status) +{ + int err = 0; + + if (af_retry_cnt >= (int)CAMERASRC_AF_TOTALTIME/CAMERASRC_AF_INTERVAL) { + *status = CAMERASRC_SENSOR_AF_STATUS_FAILED; + af_retry_cnt = 0; + return; + } else { + af_retry_cnt++; + camsrc_info("retry count = %d", af_retry_cnt); + } + + SET_CTRL_VAL_ERR(V4L2_CID_CAMERA_SET_AUTO_FOCUS, 1, err); + switch (err) { + case 0: + camsrc_info("Succeeded"); + *status = CAMERASRC_SENSOR_AF_STATUS_FOCUSED; + af_retry_cnt = 0; + break; + case EBUSY: + camsrc_info("Busy"); + *status = CAMERASRC_SENSOR_AF_STATUS_ONGOING; + break; + default: + camsrc_info("Failed"); + *status = CAMERASRC_SENSOR_AF_STATUS_FAILED; + af_retry_cnt = 0; + break; + } + + return; +} + +static void* _camerasrc_run_autofocusing(camerasrc_handle_t *handle) +{ + int err = 0; + int sensor_status = 0; + + camsrc_info("enter"); + + while(1) { + AF_MUT_LOCK(handle); + switch (handle->af_cmd) { + case CAMERASRC_AUTO_FOCUS_CMD_START: + { + camsrc_info("AF CMD:START"); + __CAMERASRC_FUJITSU_GET_AF_CTRL_VAL(handle, &sensor_status); + + switch (sensor_status) { + case CAMERASRC_SENSOR_AF_STATUS_ONGOING: + camsrc_info("FOCUSING. IN PROGRESS..."); + handle->af_status = CAMERASRC_AUTO_FOCUS_STATUS_ONGOING; + break; + case CAMERASRC_SENSOR_AF_STATUS_FOCUSED: /* focus operation success. Go to Null. */ + camsrc_info("FOCUSED. stop autofocusing..."); + + handle->af_status = CAMERASRC_AUTO_FOCUS_STATUS_RELEASED; + handle->af_cmd = CAMERASRC_AUTO_FOCUS_CMD_NULL; + + CAMERASRC_SET_STATE(handle, CAMERASRC_STATE_PREVIEW); + + if (handle->af_cb != NULL) { + if (handle->af_usr_data != NULL) { + handle->af_cb(handle, CAMERASRC_AUTO_FOCUS_RESULT_FOCUSED, handle->af_usr_data); + } else { + handle->af_cb(handle, CAMERASRC_AUTO_FOCUS_RESULT_FOCUSED, NULL); + } + } + + AF_MUT_UNLOCK(handle); + continue; + case CAMERASRC_SENSOR_AF_STATUS_FAILED: /* focus operation failed. Set stop and go to NULL. */ + camsrc_info("FOCUSING FAILED"); + + if (handle->cur_af_mode != CAMERASRC_AF_MODE_CONTINUOUS ) { + SET_CTRL_VAL_ERR(V4L2_CID_CAMERA_SET_AUTO_FOCUS, 0, err); + camsrc_info("Stopping AF done. err = %d", err); + } + + handle->af_status = CAMERASRC_AUTO_FOCUS_STATUS_RELEASED; + handle->af_cmd = CAMERASRC_AUTO_FOCUS_CMD_NULL; + + CAMERASRC_SET_STATE(handle, CAMERASRC_STATE_PREVIEW); + + if (handle->af_cb != NULL) { + if(handle->af_usr_data != NULL) { + handle->af_cb(handle, CAMERASRC_AUTO_FOCUS_RESULT_FAILED, handle->af_usr_data); + } else { + handle->af_cb(handle, CAMERASRC_AUTO_FOCUS_RESULT_FAILED, NULL); + } + } + + AF_MUT_UNLOCK(handle); + continue; + default: + camsrc_error("Unrecognizable status"); + break; + } + break; + } + case CAMERASRC_AUTO_FOCUS_CMD_STOP: + { + camsrc_info("AF CMD:STOP"); + SET_CTRL_VAL_ERR(V4L2_CID_CAMERA_SET_AUTO_FOCUS, 0, err); + handle->af_status = CAMERASRC_AUTO_FOCUS_STATUS_RELEASED; + handle->af_cmd = CAMERASRC_AUTO_FOCUS_CMD_NULL; + camsrc_info("Stopping AF done. err = %d", err); + AF_MUT_UNLOCK(handle); + continue; + } + case CAMERASRC_AUTO_FOCUS_CMD_KILL: + { + camsrc_info("AF CMD:KILL"); + + SET_CTRL_VAL_ERR(V4L2_CID_CAMERA_SET_AUTO_FOCUS, 0, err); + camsrc_info("Stopping AF done. err = %d", err); + + handle->af_status = CAMERASRC_AUTO_FOCUS_STATUS_RELEASED; + handle->af_cmd = CAMERASRC_AUTO_FOCUS_CMD_NULL; + + AF_MUT_UNLOCK(handle); + goto OUT_OF_LOOP; + } + case CAMERASRC_AUTO_FOCUS_CMD_NULL: + default: + { + char err_msg[CAMERASRC_ERRMSG_MAX_LEN] = {'\0',}; + camsrc_info("AF CMD:NULL...."); + err = pthread_cond_wait(&handle->af_wait_cond, &handle->af_mutex); + if (err) { + strerror_r(err, err_msg, CAMERASRC_ERRMSG_MAX_LEN); + camsrc_error("AF CMD pthread_cond_wait - err:(%s)", err_msg); + } + + af_retry_cnt = 0; + + /* Start AF delay for AE */ + if (handle->af_cmd == CAMERASRC_AUTO_FOCUS_CMD_START) { + struct timeval cur_time; + int sec = 0; + int usec = 0; + int diff = 0; /* msec */ + int sleep_time = 0; /* usec */ + + SET_CTRL_VAL_ERR(V4L2_CID_CAMERA_SET_AUTO_FOCUS, 0, err); + + camsrc_info("Check set AF area Time(Delay:%d)", CAMERASRC_AF_DELAY_AFTER_SET_AF_AREA); + + if (handle->set_af_area_time.tv_sec != 0) { + gettimeofday(&cur_time, NULL); + sec = cur_time.tv_sec - handle->set_af_area_time.tv_sec; + usec = cur_time.tv_usec - handle->set_af_area_time.tv_usec; + + camsrc_info("diff sec:%d, usec:%d", sec, usec); + diff = (sec * 1000) + (usec / 1000); + + /* Skip sleep if diff is less than zero or greater than minimum exposure time */ + if (diff < 0 || diff > CAMERASRC_AF_DELAY_AFTER_SET_AF_AREA) { + camsrc_info("no need to sleep(diff: %d ms)", diff); + } else { + sleep_time = (CAMERASRC_AF_DELAY_AFTER_SET_AF_AREA - diff) * 1000; + camsrc_info("usleep(%d)", sleep_time); + usleep(sleep_time); + } + } + } + + AF_MUT_UNLOCK(handle); + continue; + } + } + + AF_MUT_UNLOCK(handle); + usleep(CAMERASRC_AF_INTERVAL); + } + +OUT_OF_LOOP: + camsrc_info("AF thread is finished."); + return NULL; +} + +static int _camerasrc_start_autofocusing(camerasrc_handle_t *handle) +{ + int err; + char err_msg[CAMERASRC_ERRMSG_MAX_LEN] = {'\0',}; + camsrc_info("enter"); + + AF_MUT_LOCK(handle); + + handle->af_cmd = CAMERASRC_AUTO_FOCUS_CMD_START; + err = pthread_cond_signal(&handle->af_wait_cond); + if (err) { + strerror_r(err, err_msg, CAMERASRC_ERRMSG_MAX_LEN); + camsrc_info("AF wait cond err(%s)", err_msg); + } + + AF_MUT_UNLOCK(handle); + + return CAMERASRC_SUCCESS; +} + +static int _camerasrc_stop_autofocusing(camerasrc_handle_t *handle) +{ + int err; + char err_msg[CAMERASRC_ERRMSG_MAX_LEN] = {'\0',}; + + camsrc_info("enter"); + + AF_MUT_LOCK(handle); + + handle->af_cmd = CAMERASRC_AUTO_FOCUS_CMD_STOP; + err = pthread_cond_signal(&handle->af_wait_cond); + if (err) { + strerror_r(err, err_msg, CAMERASRC_ERRMSG_MAX_LEN); + camsrc_info("AF wait cond err(%s)", err_msg); + } + + AF_MUT_UNLOCK(handle); + + return CAMERASRC_SUCCESS; +} + +static int _camerasrc_destroy_autofocusing(camerasrc_handle_t *handle) +{ + int err; + char err_msg[CAMERASRC_ERRMSG_MAX_LEN] = {'\0',}; + camsrc_info("enter"); + + AF_MUT_LOCK(handle); + + handle->af_cmd = CAMERASRC_AUTO_FOCUS_CMD_KILL; + err = pthread_cond_signal(&handle->af_wait_cond); + if (err) { + strerror_r(err, err_msg, CAMERASRC_ERRMSG_MAX_LEN); + camsrc_info("AF wait cond err(%s)", err_msg); + } + + AF_MUT_UNLOCK(handle); + + return CAMERASRC_SUCCESS; +} + +static int _camerasrc_release_autofocusing(camerasrc_handle_t *handle) +{ + int err; + camsrc_info("enter"); + + SET_CTRL_VAL_ERR(V4L2_CID_CAMERA_SET_AUTO_FOCUS, 0, err); + + return CAMERASRC_SUCCESS; +} + +static int _camerasrc_copy_frame(camerasrc_handle_t *handle, camerasrc_buffer_t *src_buffer, camerasrc_buffer_t *dst_buffer, int isThumbnail) +{ + if (handle == NULL || src_buffer == NULL || dst_buffer == NULL) { + camsrc_error("handle[%p], src_buffer[%p], dst_buffer[%p]", + handle, src_buffer, dst_buffer); + return CAMERASRC_ERR_NULL_POINTER; + } + + if (src_buffer->start == NULL || dst_buffer->start == NULL) { + camsrc_error("src_buffer->start[%p], dst_buffer->start[%p]", + src_buffer->start, dst_buffer->start); + return CAMERASRC_ERR_NULL_POINTER; + } + + if (handle->format.colorspace == CAMERASRC_COL_RAW) { + int cpy_len; + + if (handle->format.pix_format == CAMERASRC_PIX_YUV422P || + handle->format.pix_format == CAMERASRC_PIX_YUY2 || + handle->format.pix_format == CAMERASRC_PIX_UYVY) { + cpy_len = (YUV422_SIZE(handle)>=src_buffer->length)?src_buffer->length:YUV422_SIZE(handle); + } else if (handle->format.pix_format == CAMERASRC_PIX_YUV420P || + handle->format.pix_format == CAMERASRC_PIX_YUV420 || + handle->format.pix_format == CAMERASRC_PIX_NV12) { + cpy_len = (YUV420_SIZE(handle)>=src_buffer->length)?src_buffer->length:YUV420_SIZE(handle); + } else { + camsrc_error("UNSUPPORTED format [%x]", handle->format.pix_format ); + return CAMERASRC_ERR_INVALID_FORMAT; + } + +#if defined (USE_FRAME_COPY_BOUNDARY_CHECK) + camsrc_info("Boundary check %p ~ %p ... [length = %d] ", dst_buffer->start, dst_buffer->start+cpy_len, cpy_len); + memset(dst_buffer->start, 0, cpy_len); + camsrc_info("Boundary check OK"); +#endif + + camsrc_info("RAW frame dequeing..."); + dst_buffer->length = cpy_len; + + if (handle->format.pix_format == CAMERASRC_PIX_SN12) { + camsrc_error("Can't copy the frame with SN12 option"); + return CAMERASRC_ERR_DEVICE_NOT_SUPPORT; + } else if (handle->format.pix_format == CAMERASRC_PIX_ST12) { + camsrc_error("Can't copy the frame with ST12 option"); + return CAMERASRC_ERR_DEVICE_NOT_SUPPORT; + } + + camsrc_error("format[%d] copy occured. copy len = %d", handle->format.pix_format, cpy_len); + memcpy(dst_buffer->start, src_buffer->start, cpy_len ); + } else if (handle->format.colorspace == CAMERASRC_COL_JPEG) { +#if defined (USE_FRAME_COPY_BOUNDARY_CHECK) + camsrc_info("Boundary check %p ~ %p ...", dst_buffer->start, dst_buffer->start+src_buffer->length); + memset(dst_buffer->start, 0, src_buffer->length); + camsrc_info("Boundary check OK"); +#endif + + if (!isThumbnail) { + if (src_buffer->length <= 0) { + camsrc_error("length[%d] is too small", src_buffer->length ); + return CAMERASRC_ERR_INVALID_VALUE; + } + + dst_buffer->length = src_buffer->length; + camsrc_info("JPEG main frame copy... img length = %d", dst_buffer->length); + memcpy(dst_buffer->start, src_buffer->start, dst_buffer->length); + camsrc_info("JPEG main frame copy done."); + } else { + if (handle->format.pix_format == CAMERASRC_PIX_RGGB8) { + /* JPEG + JPEG */ + if (src_buffer->length <= 0) { + camsrc_error("length[%d] is too small", src_buffer->length ); + return CAMERASRC_ERR_INVALID_VALUE; + } + + dst_buffer->length = src_buffer->length; + camsrc_info("JPEG thm frame(JPEG) copy... img length = %d", dst_buffer->length); + memcpy(dst_buffer->start, src_buffer->start, dst_buffer->length); + camsrc_info("JPEG thm frame(JPEG) copy done."); + } else if (handle->format.pix_format == CAMERASRC_PIX_RGGB10) { + /* JPEG + YUV */ + dst_buffer->length = CAMERASRC_YUV_THMBNL_SIZE; + camsrc_info("JPEG thm frame(YUV) copy... img length = %d", CAMERASRC_YUV_THMBNL_SIZE); + memcpy(dst_buffer->start, src_buffer->start, CAMERASRC_YUV_THMBNL_SIZE); + camsrc_info("JPEG thm frame(YUV) copy done."); + } else { + camsrc_info("Unknown format [%d]", handle->format.pix_format ); + return CAMERASRC_ERR_INVALID_FORMAT; + } + } + } + + return CAMERASRC_SUCCESS; +} + + +static int _camerasrc_set_thumbnail_size(camerasrc_handle_t *handle) +{ + camsrc_info("enter"); + + return CAMERASRC_ERR_DEVICE_NOT_SUPPORT; +} + +static int _camerasrc_start_facedetection (camerasrc_handle_t *handle) +{ + camsrc_info("enter"); + camsrc_info("FACE DETECTION START!"); + SET_CTRL_VAL(V4L2_CID_FACE_DETECTION, CAM_FACE_DETECTION_ON); + camsrc_info("leave"); + return CAMERASRC_SUCCESS; +} + + +static int _camerasrc_stop_facedetection (camerasrc_handle_t *handle) +{ + camsrc_info("enter"); + camsrc_info("FACE DETECTION STOP!"); + SET_CTRL_VAL(V4L2_CID_FACE_DETECTION, CAM_FACE_DETECTION_OFF); + camsrc_info("leave"); + return CAMERASRC_SUCCESS; +} + + +static int _camerasrc_check_emp_shock(camerasrc_handle_t *handle, int *check_val) +{ + camsrc_info("enter"); + int ret_value = 0; + + GET_CTRL_VAL(V4L2_CID_ESD_INT, ret_value); + *check_val = ret_value; + + camsrc_info("leave"); + return CAMERASRC_SUCCESS; +} + + +static int _camerasrc_get_frame_data(camerasrc_handle_t *handle, camerasrc_frame_data_t *data) +{ + /*camsrc_info("enter");*/ + int err = CAMERASRC_ERR_UNKNOWN; + struct v4l2_control control; + + /* Get Y physical address */ + /*camsrc_info("[VIDIOC_G_CTRL] << [V4L2_CID_PADDR_Y] request with value");*/ + control.id = V4L2_CID_PADDR_Y; + control.value = data->index; + err = _camerasrc_ioctl(handle, VIDIOC_S_CTRL, &control); + if (err != CAMERASRC_SUCCESS) { + return err; + } + + data->phyAddrY = control.value; + + /* Get CbCr physical address */ + /*camsrc_info("[VIDIOC_G_CTRL] << [V4L2_CID_PADDR_CBCR] request with value");*/ + control.id = V4L2_CID_PADDR_CBCR; + control.value = data->index; + err = _camerasrc_ioctl(handle, VIDIOC_S_CTRL, &control); + if (err != CAMERASRC_SUCCESS) { + return err; + } + + data->phyAddrCbCr = control.value; + + /* Distance between Y ptr and CbCr ptr of virtual address is same with that of Physical one. */ + data->virAddrY = (unsigned int)handle->buffer[data->index].start; + data->virAddrCbCr = data->virAddrY + (data->phyAddrCbCr - data->phyAddrY); + + /*camsrc_info("virAddrY(%p), virAddrCbCr(%p)", data->virAddrY, data->virAddrCbCr);*/ + + return CAMERASRC_SUCCESS; +} + + +static void _dump_exif_info(camerasrc_exif_t *exif_struct) +{ + camsrc_info("== Dynamic value =="); + camsrc_info("unsigned int exposure_time_numerator = %d", exif_struct->exposure_time_numerator); + camsrc_info("unsigned int exposure_time_denominator = %d", exif_struct->exposure_time_denominator); + camsrc_info("int shutter_speed_numerator = %d", exif_struct->shutter_speed_numerator); + camsrc_info("int shutter_speed_denominator = %d", exif_struct->shutter_speed_denominator); + camsrc_info("int brigtness_numerator = %d", exif_struct->brigtness_numerator); + camsrc_info("int brightness_denominator = %d", exif_struct->brightness_denominator); + camsrc_info("unsigned short int iso = %d", exif_struct->iso); + camsrc_info("unsigned short int flash = %d", exif_struct->flash); + camsrc_info("int metering_mode = %d", exif_struct->metering_mode); + camsrc_info("int exif_image_width = %d", exif_struct->exif_image_width); + camsrc_info("int exif_image_height = %d", exif_struct->exif_image_height); + camsrc_info("int exposure_bias_in_APEX = %d", exif_struct->exposure_bias_in_APEX); + camsrc_info("int software_used = %d", exif_struct->software_used); + camsrc_info("int focal_len_numerator = %d", exif_struct->focal_len_numerator); + camsrc_info("int focal_len_denominator = %d", exif_struct->focal_len_denominator); + camsrc_info("int aperture_f_num_numerator = %d", exif_struct->aperture_f_num_numerator); + camsrc_info("int aperture_f_num_denominator = %d", exif_struct->aperture_f_num_denominator); + camsrc_info("int aperture_in_APEX = %d", exif_struct->aperture_in_APEX); + camsrc_info("int max_lens_aperture_in_APEX = %d", exif_struct->max_lens_aperture_in_APEX); + + camsrc_info("== Fixed value =="); + camsrc_info("int component_configuration = %x", exif_struct->component_configuration); + camsrc_info("int colorspace = %d", exif_struct->colorspace); + + return; +} + + +static int _camerasrc_get_exif_info (camerasrc_handle_t *handle, camerasrc_exif_t *exif_struct) +{ + int photometry_mode = V4L2_PHOTOMETRY_MULTISEG; + + if (exif_struct == NULL) { + return CAMERASRC_ERR_INVALID_PARAMETER; + } + + /** Dynamic value **/ + + /* exposure time */ + GET_CTRL_VAL(V4L2_CID_CAMERA_EXIF_EXPTIME, exif_struct->exposure_time_numerator); + exif_struct->exposure_time_denominator = 1; + + /* shutter speed */ + GET_CTRL_VAL(V4L2_CID_CAMERA_EXIF_TV, exif_struct->shutter_speed_numerator); + exif_struct->shutter_speed_denominator = 1; + + /* brightness */ + GET_CTRL_VAL(V4L2_CID_CAMERA_EXIF_BV, exif_struct->brigtness_numerator); + exif_struct->brightness_denominator = 1; + + /* iso */ + GET_CTRL_VAL(V4L2_CID_CAMERA_EXIF_ISO, exif_struct->iso); + ISO_APPROXIMATE_VALUE(exif_struct->iso, exif_struct->iso); + + /* flash */ + GET_CTRL_VAL(V4L2_CID_CAMERA_EXIF_FLASH, exif_struct->flash); + + /* image size */ + exif_struct->exif_image_width = handle->format.img_size.dim.width; + exif_struct->exif_image_height = handle->format.img_size.dim.height; + + /*FIXME focal length - Set fixed value at gst_camerasrc_control_get_exif_info function */ + exif_struct->focal_len_numerator = 1; + exif_struct->focal_len_denominator = 1; + + /*FIXME f number - Set fixed value at gst_camerasrc_control_get_exif_info function */ + exif_struct->aperture_f_num_numerator = 1; + exif_struct->aperture_f_num_denominator = 1; + + /* FIXME APEX */ + exif_struct->aperture_in_APEX \ + = CAMERASRC_EXIF_APERTURE_VALUE_IN_APEX(exif_struct->aperture_f_num_numerator, exif_struct->aperture_f_num_denominator); + exif_struct->max_lens_aperture_in_APEX = 1; + /*= CAMERASRC_EXIF_APERTURE_VALUE_IN_APEX(exif_info.max_aperture_f_num_numerator, exif_info.max_aperture_f_num_denominator);*/ + exif_struct->exposure_bias_in_APEX = exif_struct->aperture_in_APEX \ + + CAMERASRC_EXIF_SHUTTERSPEED_VALUE_IN_APEX(exif_struct->exposure_time_numerator, exif_struct->exposure_time_denominator); + + /* Get the value using CID */ + /* Not implemented yet + GET_CTRL_VAL(V4L2_CID_FW_VERSION, exif_struct->software_used); + */ + GET_CTRL_VAL(V4L2_CID_PHOTOMETRY, photometry_mode); + PHOTOMETRY_MODE_TO_METERING_MODE(photometry_mode, exif_struct->metering_mode); + + /** Fixed value **/ + exif_struct->component_configuration = _CAMERASRC_EXIF_COMP_CONF; + exif_struct->colorspace = _CAMERASRC_EXIF_COLORSPACE; + + _dump_exif_info(exif_struct); + + return CAMERASRC_SUCCESS; +} + +static int fd_on = 0; + +static int _camerasrc_set_cmd(camerasrc_handle_t *handle, _camsrc_cmd_t cmd, void *value) +{ + int err = CAMERASRC_ERR_UNKNOWN; + struct v4l2_jpegcompression comp_arg; + + switch (cmd) { + case _CAMERASRC_CMD_STROBE_MODE: + { + camerasrc_strobe_mode_t *mode = (camerasrc_strobe_mode_t*)value; + + camsrc_info("[_CAMERASRC_CMD_STROBE_MODE] cmd set value %d", *mode ); + + SET_CTRL_VAL(V4L2_CID_CAMERA_FLASH_MODE, *mode); + } + break; + case _CAMERASRC_CMD_FACEDETECTION: + { + int err = CAMERASRC_ERR_UNKNOWN; + struct v4l2_recognition recog; + + camsrc_info("[_CAMERASRC_CMD_FACEDETECTION] cmd set"); + if (((int)value) == _CAMERASRC_FACEDETECTION_START) { + camsrc_info("[_CAMERASRC_CMD_FACEDETECTION] start"); + recog.mode = V4L2_RECOGNITION_MODE_ON; + recog.pattern = V4L2_RECOG_PATTERN_FACE; + recog.obj_num = 10; + /*recog.detect_idx = 0;*/ + recog.action= V4L2_RECOGNITION_ACTION_NONE; + fd_on = 1; + } else if (((int)value) == _CAMERASRC_FACEDETECTION_STOP) { + camsrc_error("[_CAMERASRC_CMD_FACEDETECTION] stop"); + recog.mode = V4L2_RECOGNITION_MODE_OFF; + recog.pattern = V4L2_RECOG_PATTERN_FACE; + recog.obj_num = 10; + /*recog.detect_idx = 0;*/ + recog.action= V4L2_RECOGNITION_ACTION_NONE; + fd_on = 0; + } else { + camsrc_error("[_CAMERASRC_CMD_FACEDETECTION] not support cmd"); + } + + err = _camerasrc_ioctl(handle, VIDIOC_S_RECOGNITION, &recog); + if (err != CAMERASRC_SUCCESS) { + goto ERROR; + } + } + break; + case _CAMERASRC_CMD_SHUTTER_SPEED: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_SHUTTER_SPEED] cmd set"); + break; + case _CAMERASRC_CMD_JPEG_LENGTH: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_JPEG_LENGTH] cmd set"); + break; + case _CAMERASRC_CMD_JPEG_THMBNL_LENGTH: + camsrc_info("[_CAMERASRC_CMD_JPEG_THMBNL_LENGTH] cmd set"); + err = _camerasrc_set_thumbnail_size(handle); + if (err != CAMERASRC_SUCCESS) { + goto ERROR; + } + break; + case _CAMERASRC_CMD_EXPOSURE_VALUE: + camsrc_info("[_CAMERASRC_CMD_EXPOSURE_VALUE] cmd set"); + /* WRITEME */ + break; + case _CAMERASRC_CMD_ESD_CHECK: + camsrc_info("[_CAMERASRC_CMD_ESD_CHECK] cmd set"); + /* WRITEME */ + break; + case _CAMERASRC_CMD_CTRL: + camsrc_info("[_CAMERASRC_CMD_CTRL] cmd set"); + SET_CTRL_VAL(_CAMERASRC_GET_CID(((_camerasrc_ctrl_t *) value)->cid, handle->cur_dev_id), ((_camerasrc_ctrl_t *) value)->value); + break; + case _CAMERASRC_CMD_SUPPORT_EMBED_EXIF: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_SUPPORT_EMBED_EXIF] cmd set"); + break; + case _CAMERASRC_CMD_SUPPORT_JPEG_ENCODING: + camsrc_warning("[_CAMERASRC_CMD_SUPPORT_JPEG_ENCODING] cmd set isn't supported"); + break; + case _CAMERASRC_CMD_AF_CONTROL: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_AF_CONTROL] cmd set(value=%d)", value); + + /* FIXME : Please fix whole AF implementation!!! */ + switch ((int)value) { + case _CAMERASRC_AF_START: + _camerasrc_start_autofocusing(handle); + break; + case _CAMERASRC_AF_STOP: + _camerasrc_stop_autofocusing(handle); + break; + case _CAMERASRC_AF_DESTROY: + _camerasrc_destroy_autofocusing(handle); + break; + case _CAMERASRC_AF_RELEASE: + case _CAMERASRC_AF_INIT: + default: + _camerasrc_init_autofocusing_mode(handle); + break; + } + break; + case _CAMERASRC_CMD_AF_AREA: + { + camerasrc_rect_t *rect = (camerasrc_rect_t *)value; + + camsrc_info("[_CAMERASRC_CMD_AF_AREA] cmd set (%d,%d,%dx%d)", + rect->x, rect->y, rect->width, rect->height); + + SET_CTRL_VAL(V4L2_CID_FOCUS_AUTO_RECTANGLE_LEFT, rect->x); + SET_CTRL_VAL(V4L2_CID_FOCUS_AUTO_RECTANGLE_TOP, rect->y); + SET_CTRL_VAL(V4L2_CID_FOCUS_AUTO_RECTANGLE_WIDTH, 0);/*rect->width); Not supported */ + SET_CTRL_VAL(V4L2_CID_FOCUS_AUTO_RECTANGLE_HEIGHT, 0);/*rect->height); Not supported */ + + if (gettimeofday(&handle->set_af_area_time, NULL) == 0) { + camsrc_info("[_CAMERASRC_CMD_AF_AREA] Get Time Success" ); + } else { + handle->set_af_area_time.tv_sec = 0; + handle->set_af_area_time.tv_usec = 0; + camsrc_warning("[_CAMERASRC_CMD_AF_AREA] Get Time Failed" ); + } + break; + } + case _CAMERASRC_CMD_FRAME_DATA: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_FRAME_DATA] cmd set"); + break; + case _CAMERASRC_CMD_EXIF_INFO: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_EXIF_INFO] cmd set"); + break; + case _CAMERASRC_CMD_CHECK_ESD: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_CHECK_ESD] cmd set"); + break; + case _CAMERASRC_CMD_JPEG_COMPRESS_RATIO: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_JPEG_COMPRESS_RATIO] cmd set, val = %d", (int)(*((unsigned int*) value))); + if (handle->cur_dev_id == CAMERASRC_DEV_ID_PRIMARY) { + comp_arg.quality = (int)(*((unsigned int*) value)); + err = _camerasrc_ioctl(handle, VIDIOC_S_JPEGCOMP, &comp_arg); + if (err != CAMERASRC_SUCCESS) { + goto ERROR; + } + } else if (handle->cur_dev_id == CAMERASRC_DEV_ID_SECONDARY) { + err = CAMERASRC_ERR_DEVICE_NOT_SUPPORT; + goto ERROR; + } + break; + case _CAMERASRC_CMD_ROTATION: + { + int *rotate = (int *)value; + camsrc_info("[_CAMERASRC_CMD_ROTATION] cmd set : %d", *rotate); + SET_CTRL_VAL(V4L2_CID_ROTATION, (int)*rotate); + } + break; + case _CAMERASRC_CMD_SENSOR_MODE: + { + camerasrc_sensor_mode_t *mode = (camerasrc_sensor_mode_t *)value; + camsrc_info("[_CAMERASRC_CMD_SENSOR_MODE] cmd set : %d", *mode); + SET_CTRL_VAL(V4L2_CID_CAMERA_SENSOR_MODE, (int)*mode); + } + break; + case _CAMERASRC_CMD_VFLIP: + { + int *vflip = (int *)value; + camsrc_info("[_CAMERASRC_CMD_VFLIP] cmd set : %d", *vflip); + SET_CTRL_VAL(V4L2_CID_VFLIP, (int)*vflip); + } + break; + case _CAMERASRC_CMD_HFLIP: + { + int *hflip = (int *)value; + camsrc_info("[_CAMERASRC_CMD_HFLIP] cmd set : %d", *hflip); + SET_CTRL_VAL(V4L2_CID_HFLIP, (int)*hflip); + } + break; + default: + camsrc_error("[_CAMERASRC_CMD_UNKNOWN] cmd set"); + err = CAMERASRC_ERR_DEVICE_NOT_SUPPORT; + goto ERROR; + } + + return CAMERASRC_SUCCESS; + +ERROR: + camsrc_error("cmd execution error occured"); + + return err; +} + +static int _camerasrc_get_cmd(camerasrc_handle_t *handle, _camsrc_cmd_t cmd, void *value) +{ + int err = CAMERASRC_ERR_UNKNOWN; + struct v4l2_jpegcompression comp_arg; + + if (!value) { + camsrc_error("value is NULL"); + return CAMERASRC_ERR_NULL_POINTER; + } + + switch (cmd) { + case _CAMERASRC_CMD_SUPPORT_EMBED_EXIF: + camsrc_info("[_CAMERASRC_CMD_SUPPORT_EMBED_EXIF] cmd get"); + *((int*)value) = _CAMERASRC_CMD_SUPPORT_EMBED_EXIF_DEF; + break; + case _CAMERASRC_CMD_SUPPORT_JPEG_ENCODING: + camsrc_info("[_CAMERASRC_CMD_SUPPORT_JPEG_ENCODING] cmd get(cur_dev_id=%d)", handle->cur_dev_id); + if (handle->cur_dev_id == CAMERASRC_DEV_ID_PRIMARY) { + *((int*)value) = 1; + } else { + *((int*)value) = 0; + } + break; + case _CAMERASRC_CMD_STROBE_MODE: + { + camerasrc_strobe_mode_t mode; + + GET_CTRL_VAL(V4L2_CID_CAMERA_FLASH_MODE, mode); + *((camerasrc_strobe_mode_t*)value) = mode; + + camsrc_info("[_CAMERASRC_CMD_STROBE_MODE] cmd get - %d", mode); + } + break; + case _CAMERASRC_CMD_FACEDETECTION: + camsrc_info("[_CAMERASRC_CMD_FACEDETECTION] cmd get - %d", fd_on); + *(int *)value = fd_on; + break; + case _CAMERASRC_CMD_SHUTTER_SPEED: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_SHUTTER_SPEED] cmd get"); + break; + case _CAMERASRC_CMD_JPEG_LENGTH: + { + int err = CAMERASRC_ERR_UNKNOWN; + struct v4l2_control ctrl; + + ctrl.id = V4L2_CID_CAM_JPEG_MAIN_SIZE; + err = _camerasrc_ioctl( handle, VIDIOC_G_CTRL, &ctrl ); + if (err != CAMERASRC_SUCCESS) { + *((int*)value) = 0; + goto ERROR; + } + + *((int*)value) = ctrl.value; + camsrc_info("[_CAMERASRC_CMD_JPEG_LENGTH] cmd get"); + break; + } + case _CAMERASRC_CMD_JPEG_THMBNL_LENGTH: + { + int err = CAMERASRC_ERR_UNKNOWN; + struct v4l2_control ctrl; + + ctrl.id = V4L2_CID_CAM_JPEG_THUMB_SIZE; + err = _camerasrc_ioctl( handle, VIDIOC_G_CTRL, &ctrl ); + if (err != CAMERASRC_SUCCESS) { + *((int*)value) = 0; + goto ERROR; + } + + *((int*)value) = ctrl.value; + camsrc_info("[_CAMERASRC_CMD_JPEG_THMBNL_LENGTH] cmd get : %d", *((int*)value)); + break; + } + case _CAMERASRC_CMD_JPEG_THMBNL_OFFSET: + { + int err = CAMERASRC_ERR_UNKNOWN; + struct v4l2_control ctrl; + ctrl.id = V4L2_CID_CAM_JPEG_THUMB_OFFSET; + + err = _camerasrc_ioctl( handle, VIDIOC_G_CTRL, &ctrl ); + if(err != CAMERASRC_SUCCESS) + { + *((int*)value) = 0; + goto ERROR; + } + + *((int*)value) = ctrl.value; + camsrc_info("[_CAMERASRC_CMD_JPEG_THMBNL_OFFSET] cmd get : %x", *((int*)value)); + break; + } + case _CAMERASRC_CMD_JPEG_SCRNL_LENGTH: + { + int err = CAMERASRC_ERR_UNKNOWN; + struct v4l2_control ctrl; + ctrl.id = V4L2_CID_CAM_JPEG_POSTVIEW_SIZE; + + err = _camerasrc_ioctl(handle, VIDIOC_G_CTRL, &ctrl); + if (err != CAMERASRC_SUCCESS) { + *((int*)value) = 0; + goto ERROR; + } + + *((int*)value) = ctrl.value; + camsrc_info("[_CAMERASRC_CMD_JPEG_SCRNL_LENGTH] cmd get : %x", *((int*)value)); + break; + } + case _CAMERASRC_CMD_JPEG_SCRNL_OFFSET: + { + int err = CAMERASRC_ERR_UNKNOWN; + struct v4l2_control ctrl; + ctrl.id = V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET; + + err = _camerasrc_ioctl( handle, VIDIOC_G_CTRL, &ctrl ); + if (err != CAMERASRC_SUCCESS) { + *((int*)value) = 0; + goto ERROR; + } + + *((int*)value) = ctrl.value; + camsrc_info("[_CAMERASRC_CMD_JPEG_SCRNL_OFFSET] cmd get : %x", *((int*)value)); + break; + } + case _CAMERASRC_CMD_EXPOSURE_VALUE: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_EXPOSURE_VALUE] cmd get"); + break; + case _CAMERASRC_CMD_ESD_CHECK: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_ESD_CHECK] cmd get"); + break; + case _CAMERASRC_CMD_CTRL: + camsrc_info("[_CAMERASRC_CMD_CTRL] cmd get"); + GET_CTRL_VAL(_CAMERASRC_GET_CID(((_camerasrc_ctrl_t *) value)->cid, handle->cur_dev_id), ((_camerasrc_ctrl_t *) value)->value); + break; + case _CAMERASRC_CMD_AF_CONTROL: + /* WRITEME */ + camsrc_info("[_CAMERASRC_CMD_AF_CONTROL] cmd get"); + break; + case _CAMERASRC_CMD_AF_AREA: + { + camerasrc_rect_t* rect = (camerasrc_rect_t*)value; + + GET_CTRL_VAL(V4L2_CID_FOCUS_AUTO_RECTANGLE_LEFT, rect->x); + GET_CTRL_VAL(V4L2_CID_FOCUS_AUTO_RECTANGLE_TOP, rect->y); + GET_CTRL_VAL(V4L2_CID_FOCUS_AUTO_RECTANGLE_WIDTH, rect->width); + GET_CTRL_VAL(V4L2_CID_FOCUS_AUTO_RECTANGLE_HEIGHT, rect->height); + + camsrc_info("[_CAMERASRC_CMD_AF_AREA] cmd get (%d,%d,%dx%d)", + rect->x, rect->y, rect->width, rect->height); + break; + } + case _CAMERASRC_CMD_FRAME_DATA: + /* WRITEME */ + /*camsrc_info("[_CAMERASRC_CMD_FRAME_DATA] cmd get");*/ + err = _camerasrc_get_frame_data(handle, (camerasrc_frame_data_t*)value); + if (err != CAMERASRC_SUCCESS) { + goto ERROR; + } + break; + case _CAMERASRC_CMD_EXIF_INFO: + camsrc_info("[_CAMERASRC_CMD_EXIF_INFO] cmd get"); + err = _camerasrc_get_exif_info (handle, (camerasrc_exif_t*)value); + if (err != CAMERASRC_SUCCESS) { + goto ERROR; + } + break; + case _CAMERASRC_CMD_CHECK_ESD: + camsrc_info("[_CAMERASRC_CMD_CHECK_ESD] cmd get"); + GET_CTRL_VAL(V4L2_CID_ESD_INT, *((int *) value)); + break; + case _CAMERASRC_CMD_JPEG_COMPRESS_RATIO: + camsrc_info("[_CAMERASRC_CMD_JPEG_COMPRESS_RATIO] cmd get"); + err = _camerasrc_ioctl(handle, VIDIOC_G_JPEGCOMP, &comp_arg); + if (err != CAMERASRC_SUCCESS) { + goto ERROR; + } + *((unsigned int*)value) = (int)comp_arg.quality; + break; + case _CAMERASRC_CMD_ROTATION: + camsrc_info("[_CAMERASRC_CMD_ROTATION] cmd get"); + GET_CTRL_VAL(V4L2_CID_ROTATION, *(int*)value); + break; + case _CAMERASRC_CMD_SENSOR_MODE: + camsrc_info("[_CAMERASRC_CMD_SENSOR_MODE] cmd get"); + GET_CTRL_VAL(V4L2_CID_CAMERA_SENSOR_MODE, *(int*)value); + break; + case _CAMERASRC_CMD_VFLIP: + camsrc_info("[_CAMERASRC_CMD_VFLIP] cmd get"); + GET_CTRL_VAL(V4L2_CID_VFLIP, *(int*)value); + break; + case _CAMERASRC_CMD_HFLIP: + camsrc_info("[_CAMERASRC_CMD_HFLIP] cmd get"); + GET_CTRL_VAL(V4L2_CID_HFLIP, *(int*)value); + break; + default: + camsrc_error("[_CAMERASRC_CMD_UNKNOWN] cmd get"); + err = CAMERASRC_ERR_DEVICE_NOT_SUPPORT; + goto ERROR; + } + + return CAMERASRC_SUCCESS; + +ERROR: + camsrc_error("cmd execution error occured"); + + return err; +} + +static const CAMERASRC_DEV_DEPENDENT_MISC_FUNC dev_misc_functions = { + ._ioctl = _camerasrc_ioctl, + ._ioctl_once = _camerasrc_ioctl_once, + ._run_autofocusing = _camerasrc_run_autofocusing, + ._skip_frame = _camerasrc_skip_frame, + ._copy_frame = _camerasrc_copy_frame, + ._set_cmd = _camerasrc_set_cmd, + ._get_cmd = _camerasrc_get_cmd, +}; + +const CAMERASRC_DEV_DEPENDENT_MISC_FUNC *dev_misc_func = &dev_misc_functions; |