| /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| |
| // To remove |
| #include <cutils/properties.h> |
| |
| // System dependencies |
| #include <pthread.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <stdlib.h> |
| #include <sys/stat.h> |
| #include <dlfcn.h> |
| #define IOCTL_H <SYSTEM_HEADER_PREFIX/ioctl.h> |
| #include IOCTL_H |
| |
| // Camera dependencies |
| #include "cam_semaphore.h" |
| #include "mm_camera_dbg.h" |
| #include "mm_camera_sock.h" |
| #include "mm_camera_interface.h" |
| #include "mm_camera.h" |
| #include "mm_camera_muxer.h" |
| |
| #define SET_PARM_BIT32(parm, parm_arr) \ |
| (parm_arr[parm/32] |= (1<<(parm%32))) |
| |
| #define GET_PARM_BIT32(parm, parm_arr) \ |
| ((parm_arr[parm/32]>>(parm%32))& 0x1) |
| |
| /* internal function declare */ |
| int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj, |
| uint8_t reg_flag); |
| int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj, |
| mm_camera_event_t *event); |
| extern mm_camera_obj_t* mm_camera_util_get_camera_by_session_id |
| (uint32_t session_id); |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_util_get_channel_by_handler |
| * |
| * DESCRIPTION: utility function to get a channel object from its handle |
| * |
| * PARAMETERS : |
| * @cam_obj: ptr to a camera object |
| * @handler: channel handle |
| * |
| * RETURN : ptr to a channel object. |
| * NULL if failed. |
| *==========================================================================*/ |
| mm_channel_t * mm_camera_util_get_channel_by_handler( |
| mm_camera_obj_t * cam_obj, |
| uint32_t handler) |
| { |
| int i; |
| mm_channel_t *ch_obj = NULL; |
| for(i = 0; i < MM_CAMERA_CHANNEL_MAX; i++) { |
| if (handler == cam_obj->ch[i].my_hdl) { |
| ch_obj = &cam_obj->ch[i]; |
| break; |
| } |
| } |
| return ch_obj; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_util_chip_is_a_family |
| * |
| * DESCRIPTION: utility function to check if the host is A family chip |
| * |
| * PARAMETERS : |
| * |
| * RETURN : TRUE if A family. |
| * FALSE otherwise. |
| *==========================================================================*/ |
| uint8_t mm_camera_util_chip_is_a_family(void) |
| { |
| #ifdef USE_A_FAMILY |
| return TRUE; |
| #else |
| return FALSE; |
| #endif |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_dispatch_app_event |
| * |
| * DESCRIPTION: dispatch event to apps who regitster for event notify |
| * |
| * PARAMETERS : |
| * @cmd_cb: ptr to a struct storing event info |
| * @user_data: user data ptr (camera object) |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| static void mm_camera_dispatch_app_event(mm_camera_cmdcb_t *cmd_cb, |
| void* user_data) |
| { |
| int i; |
| mm_camera_event_t *event = &cmd_cb->u.evt; |
| mm_camera_obj_t * my_obj = (mm_camera_obj_t *)user_data; |
| if (NULL != my_obj) { |
| mm_camera_cmd_thread_name(my_obj->evt_thread.threadName); |
| pthread_mutex_lock(&my_obj->cb_lock); |
| for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) { |
| if(my_obj->evt.evt[i].evt_cb) { |
| my_obj->evt.evt[i].evt_cb( |
| my_obj->my_hdl, |
| event, |
| my_obj->evt.evt[i].user_data); |
| } |
| } |
| pthread_mutex_unlock(&my_obj->cb_lock); |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_event_notify |
| * |
| * DESCRIPTION: callback to handle event notify from kernel. This call will |
| * dequeue event from kernel. |
| * |
| * PARAMETERS : |
| * @user_data: user data ptr (camera object) |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| static void mm_camera_event_notify(void* user_data) |
| { |
| struct v4l2_event ev; |
| struct msm_v4l2_event_data *msm_evt = NULL; |
| int rc; |
| mm_camera_event_t evt; |
| memset(&evt, 0, sizeof(mm_camera_event_t)); |
| |
| mm_camera_obj_t *my_obj = (mm_camera_obj_t*)user_data; |
| if (NULL != my_obj) { |
| /* read evt */ |
| memset(&ev, 0, sizeof(ev)); |
| rc = ioctl(my_obj->ctrl_fd, VIDIOC_DQEVENT, &ev); |
| |
| if (rc >= 0 && ev.id == MSM_CAMERA_MSM_NOTIFY) { |
| msm_evt = (struct msm_v4l2_event_data *)ev.u.data; |
| switch (msm_evt->command) { |
| case CAM_EVENT_TYPE_DAEMON_PULL_REQ: |
| evt.server_event_type = CAM_EVENT_TYPE_DAEMON_PULL_REQ; |
| mm_camera_enqueue_evt(my_obj, &evt); |
| break; |
| case CAM_EVENT_TYPE_MAP_UNMAP_DONE: |
| pthread_mutex_lock(&my_obj->evt_lock); |
| my_obj->evt_rcvd.server_event_type = msm_evt->command; |
| my_obj->evt_rcvd.status = msm_evt->status; |
| pthread_cond_signal(&my_obj->evt_cond); |
| pthread_mutex_unlock(&my_obj->evt_lock); |
| break; |
| case CAM_EVENT_TYPE_INT_TAKE_JPEG: |
| case CAM_EVENT_TYPE_INT_TAKE_RAW: |
| { |
| evt.server_event_type = msm_evt->command; |
| mm_camera_enqueue_evt(my_obj, &evt); |
| } |
| break; |
| case MSM_CAMERA_PRIV_SHUTDOWN: |
| { |
| LOGE("Camera Event DAEMON DIED received"); |
| evt.server_event_type = CAM_EVENT_TYPE_DAEMON_DIED; |
| mm_camera_enqueue_evt(my_obj, &evt); |
| } |
| break; |
| case CAM_EVENT_TYPE_CAC_DONE: |
| { |
| evt.server_event_type = CAM_EVENT_TYPE_CAC_DONE; |
| mm_camera_enqueue_evt(my_obj, &evt); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_enqueue_evt |
| * |
| * DESCRIPTION: enqueue received event into event queue to be processed by |
| * event thread. |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a camera object |
| * @event : event to be queued |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj, |
| mm_camera_event_t *event) |
| { |
| int32_t rc = 0; |
| mm_camera_cmdcb_t *node = NULL; |
| |
| node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); |
| if (NULL != node) { |
| memset(node, 0, sizeof(mm_camera_cmdcb_t)); |
| node->cmd_type = MM_CAMERA_CMD_TYPE_EVT_CB; |
| node->u.evt = *event; |
| |
| /* enqueue to evt cmd thread */ |
| cam_queue_enq(&(my_obj->evt_thread.cmd_queue), node); |
| /* wake up evt cmd thread */ |
| cam_sem_post(&(my_obj->evt_thread.cmd_sem)); |
| } else { |
| LOGE("No memory for mm_camera_node_t"); |
| rc = -1; |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_open |
| * |
| * DESCRIPTION: open a camera |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a camera object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_open(mm_camera_obj_t *my_obj) |
| { |
| char dev_name[MM_CAMERA_DEV_NAME_LEN]; |
| int32_t rc = 0; |
| int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES; |
| uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP; |
| int cam_idx = 0; |
| const char *dev_name_value = NULL; |
| int l_errno = 0; |
| |
| LOGD("begin\n"); |
| |
| if (NULL == my_obj) { |
| goto on_error; |
| } |
| |
| dev_name_value = mm_camera_util_get_dev_name_by_num(my_obj->my_num, |
| my_obj->my_hdl); |
| if (NULL == dev_name_value) { |
| goto on_error; |
| } |
| snprintf(dev_name, sizeof(dev_name), "/dev/%s", |
| dev_name_value); |
| sscanf(dev_name, "/dev/video%d", &cam_idx); |
| LOGD("dev name = %s, cam_idx = %d", dev_name, cam_idx); |
| |
| do{ |
| n_try--; |
| errno = 0; |
| my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK); |
| l_errno = errno; |
| LOGD("ctrl_fd = %d, errno == %d", my_obj->ctrl_fd, l_errno); |
| if((my_obj->ctrl_fd >= 0) || (errno != EIO && errno != ETIMEDOUT) || (n_try <= 0 )) { |
| break; |
| } |
| LOGE("Failed with %s error, retrying after %d milli-seconds", |
| strerror(errno), sleep_msec); |
| usleep(sleep_msec * 1000U); |
| }while (n_try > 0); |
| |
| if (my_obj->ctrl_fd < 0) { |
| LOGE("cannot open control fd of '%s' (%s)\n", |
| dev_name, strerror(l_errno)); |
| if (l_errno == EBUSY) |
| rc = -EUSERS; |
| else |
| rc = -1; |
| goto on_error; |
| } else { |
| mm_camera_get_session_id(my_obj, &my_obj->sessionid); |
| LOGH("Camera Opened id = %d sessionid = %d", cam_idx, my_obj->sessionid); |
| } |
| |
| #ifdef DAEMON_PRESENT |
| /* open domain socket*/ |
| n_try = MM_CAMERA_DEV_OPEN_TRIES; |
| do { |
| n_try--; |
| my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP); |
| l_errno = errno; |
| LOGD("ds_fd = %d, errno = %d", my_obj->ds_fd, l_errno); |
| if((my_obj->ds_fd >= 0) || (n_try <= 0 )) { |
| LOGD("opened, break out while loop"); |
| break; |
| } |
| LOGD("failed with I/O error retrying after %d milli-seconds", |
| sleep_msec); |
| usleep(sleep_msec * 1000U); |
| } while (n_try > 0); |
| |
| if (my_obj->ds_fd < 0) { |
| LOGE("cannot open domain socket fd of '%s'(%s)\n", |
| dev_name, strerror(l_errno)); |
| rc = -1; |
| goto on_error; |
| } |
| #else /* DAEMON_PRESENT */ |
| cam_status_t cam_status; |
| cam_status = mm_camera_module_open_session(my_obj->sessionid, |
| mm_camera_module_event_handler); |
| if (cam_status < 0) { |
| LOGE("Failed to open session"); |
| if (cam_status == CAM_STATUS_BUSY) { |
| rc = -EUSERS; |
| } else { |
| rc = -1; |
| } |
| goto on_error; |
| } |
| #endif /* DAEMON_PRESENT */ |
| |
| pthread_mutex_init(&my_obj->msg_lock, NULL); |
| pthread_mutex_init(&my_obj->cb_lock, NULL); |
| pthread_mutex_init(&my_obj->evt_lock, NULL); |
| pthread_cond_init(&my_obj->evt_cond, NULL); |
| |
| LOGD("Launch evt Thread in Cam Open"); |
| snprintf(my_obj->evt_thread.threadName, THREAD_NAME_SIZE, "CAM_Dispatch"); |
| mm_camera_cmd_thread_launch(&my_obj->evt_thread, |
| mm_camera_dispatch_app_event, |
| (void *)my_obj); |
| |
| /* launch event poll thread |
| * we will add evt fd into event poll thread upon user first register for evt */ |
| LOGD("Launch evt Poll Thread in Cam Open"); |
| snprintf(my_obj->evt_poll_thread.threadName, THREAD_NAME_SIZE, "CAM_evntPoll"); |
| mm_camera_poll_thread_launch(&my_obj->evt_poll_thread, |
| MM_CAMERA_POLL_TYPE_EVT); |
| mm_camera_evt_sub(my_obj, TRUE); |
| |
| /* unlock cam_lock, we need release global intf_lock in camera_open(), |
| * in order not block operation of other Camera in dual camera use case.*/ |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| LOGD("end (rc = %d)\n", rc); |
| return rc; |
| |
| on_error: |
| |
| if (NULL == dev_name_value) { |
| LOGE("Invalid device name\n"); |
| rc = -1; |
| } |
| |
| if (NULL == my_obj) { |
| LOGE("Invalid camera object\n"); |
| rc = -1; |
| } else { |
| if (my_obj->ctrl_fd >= 0) { |
| close(my_obj->ctrl_fd); |
| my_obj->ctrl_fd = -1; |
| } |
| #ifdef DAEMON_PRESENT |
| if (my_obj->ds_fd >= 0) { |
| mm_camera_socket_close(my_obj->ds_fd); |
| my_obj->ds_fd = -1; |
| } |
| #endif |
| } |
| |
| /* unlock cam_lock, we need release global intf_lock in camera_open(), |
| * in order not block operation of other Camera in dual camera use case.*/ |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_close |
| * |
| * DESCRIPTION: enqueue received event into event queue to be processed by |
| * event thread. |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a camera object |
| * @event : event to be queued |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_close(mm_camera_obj_t *my_obj) |
| { |
| LOGD("unsubscribe evt"); |
| |
| #ifndef DAEMON_PRESENT |
| mm_camera_module_close_session(my_obj->sessionid); |
| #endif /* DAEMON_PRESENT */ |
| |
| mm_camera_evt_sub(my_obj, FALSE); |
| |
| LOGD("Close evt Poll Thread in Cam Close"); |
| mm_camera_poll_thread_release(&my_obj->evt_poll_thread); |
| |
| LOGD("Close evt cmd Thread in Cam Close"); |
| mm_camera_cmd_thread_release(&my_obj->evt_thread); |
| |
| if(my_obj->ctrl_fd >= 0) { |
| close(my_obj->ctrl_fd); |
| my_obj->ctrl_fd = -1; |
| } |
| |
| #ifdef DAEMON_PRESENT |
| if(my_obj->ds_fd >= 0) { |
| mm_camera_socket_close(my_obj->ds_fd); |
| my_obj->ds_fd = -1; |
| } |
| #endif |
| |
| if (my_obj->master_cam_obj != NULL) { |
| my_obj->master_cam_obj->num_s_cnt--; |
| my_obj->master_cam_obj->aux_cam_obj[my_obj->master_cam_obj->num_s_cnt] = NULL; |
| } |
| pthread_mutex_destroy(&my_obj->msg_lock); |
| pthread_mutex_destroy(&my_obj->cb_lock); |
| pthread_mutex_destroy(&my_obj->evt_lock); |
| pthread_cond_destroy(&my_obj->evt_cond); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return 0; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_register_event_notify_internal |
| * |
| * DESCRIPTION: internal implementation for registering callback for event notify. |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a camera object |
| * @evt_cb : callback to be registered to handle event notify |
| * @user_data: user data ptr |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_register_event_notify_internal(mm_camera_obj_t *my_obj, |
| mm_camera_event_notify_t evt_cb, |
| void * user_data) |
| { |
| int i; |
| int rc = -1; |
| mm_camera_evt_obj_t *evt_array = NULL; |
| |
| pthread_mutex_lock(&my_obj->cb_lock); |
| evt_array = &my_obj->evt; |
| if(evt_cb) { |
| /* this is reg case */ |
| for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) { |
| if(evt_array->evt[i].user_data == NULL) { |
| evt_array->evt[i].evt_cb = evt_cb; |
| evt_array->evt[i].user_data = user_data; |
| evt_array->reg_count++; |
| rc = 0; |
| break; |
| } |
| } |
| } else { |
| /* this is unreg case */ |
| for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) { |
| if(evt_array->evt[i].user_data == user_data) { |
| evt_array->evt[i].evt_cb = NULL; |
| evt_array->evt[i].user_data = NULL; |
| evt_array->reg_count--; |
| rc = 0; |
| break; |
| } |
| } |
| } |
| |
| pthread_mutex_unlock(&my_obj->cb_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_register_event_notify |
| * |
| * DESCRIPTION: registering a callback for event notify. |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a camera object |
| * @evt_cb : callback to be registered to handle event notify |
| * @user_data: user data ptr |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_register_event_notify(mm_camera_obj_t *my_obj, |
| mm_camera_event_notify_t evt_cb, |
| void * user_data) |
| { |
| int rc = -1; |
| rc = mm_camera_register_event_notify_internal(my_obj, |
| evt_cb, |
| user_data); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_qbuf |
| * |
| * DESCRIPTION: enqueue buffer back to kernel |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @buf : buf ptr to be enqueued |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_qbuf(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| mm_camera_buf_def_t *buf) |
| { |
| int rc = -1; |
| mm_channel_t * ch_obj = NULL; |
| ch_obj = mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| /* we always assume qbuf will be done before channel/stream is fully stopped |
| * because qbuf is done within dataCB context |
| * in order to avoid deadlock, we are not locking ch_lock for qbuf */ |
| if (NULL != ch_obj) { |
| rc = mm_channel_qbuf(ch_obj, buf); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_get_queued_buf_count |
| * |
| * DESCRIPTION: return queued buffer count |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @stream_id : stream id |
| * |
| * RETURN : queued buffer count |
| *==========================================================================*/ |
| int32_t mm_camera_get_queued_buf_count(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, uint32_t stream_id) |
| { |
| int rc = -1; |
| mm_channel_t * ch_obj = NULL; |
| uint32_t payload; |
| ch_obj = mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| payload = stream_id; |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_GET_STREAM_QUEUED_BUF_COUNT, |
| (void *)&payload, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_query_capability |
| * |
| * DESCRIPTION: query camera capability |
| * |
| * PARAMETERS : |
| * @my_obj: camera object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_query_capability(mm_camera_obj_t *my_obj) |
| { |
| int32_t rc = 0; |
| |
| #ifdef DAEMON_PRESENT |
| struct v4l2_capability cap; |
| /* get camera capabilities */ |
| memset(&cap, 0, sizeof(cap)); |
| rc = ioctl(my_obj->ctrl_fd, VIDIOC_QUERYCAP, &cap); |
| #else /* DAEMON_PRESENT */ |
| cam_shim_packet_t *shim_cmd; |
| cam_shim_cmd_data shim_cmd_data; |
| memset(&shim_cmd_data, 0, sizeof(shim_cmd_data)); |
| shim_cmd_data.command = MSM_CAMERA_PRIV_QUERY_CAP; |
| shim_cmd_data.stream_id = 0; |
| shim_cmd_data.value = NULL; |
| shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_GET_PARM, |
| my_obj->sessionid,&shim_cmd_data); |
| rc = mm_camera_module_send_cmd(shim_cmd); |
| mm_camera_destroy_shim_cmd_packet(shim_cmd); |
| #endif /* DAEMON_PRESENT */ |
| if (rc != 0) { |
| LOGE("cannot get camera capabilities, rc = %d, errno %d", |
| rc, errno); |
| } |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_set_parms |
| * |
| * DESCRIPTION: set parameters per camera |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @parms : ptr to a param struct to be set to server |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : Assume the parms struct buf is already mapped to server via |
| * domain socket. Corresponding fields of parameters to be set |
| * are already filled in by upper layer caller. |
| *==========================================================================*/ |
| int32_t mm_camera_set_parms(mm_camera_obj_t *my_obj, |
| parm_buffer_t *parms) |
| { |
| int32_t rc = -1; |
| int32_t value = 0; |
| if (parms != NULL) { |
| rc = mm_camera_util_s_ctrl(my_obj, 0, my_obj->ctrl_fd, |
| CAM_PRIV_PARM, &value); |
| } |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_get_parms |
| * |
| * DESCRIPTION: get parameters per camera |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @parms : ptr to a param struct to be get from server |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : Assume the parms struct buf is already mapped to server via |
| * domain socket. Parameters to be get from server are already |
| * filled in by upper layer caller. After this call, corresponding |
| * fields of requested parameters will be filled in by server with |
| * detailed information. |
| *==========================================================================*/ |
| int32_t mm_camera_get_parms(mm_camera_obj_t *my_obj, |
| parm_buffer_t *parms) |
| { |
| int32_t rc = -1; |
| int32_t value = 0; |
| if (parms != NULL) { |
| rc = mm_camera_util_g_ctrl(my_obj, 0, my_obj->ctrl_fd, CAM_PRIV_PARM, &value); |
| } |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_do_auto_focus |
| * |
| * DESCRIPTION: performing auto focus |
| * |
| * PARAMETERS : |
| * @camera_handle: camera handle |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : if this call success, we will always assume there will |
| * be an auto_focus event following up. |
| *==========================================================================*/ |
| int32_t mm_camera_do_auto_focus(mm_camera_obj_t *my_obj) |
| { |
| int32_t rc = -1; |
| int32_t value = 0; |
| rc = mm_camera_util_s_ctrl(my_obj, 0, my_obj->ctrl_fd, CAM_PRIV_DO_AUTO_FOCUS, &value); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_cancel_auto_focus |
| * |
| * DESCRIPTION: cancel auto focus |
| * |
| * PARAMETERS : |
| * @camera_handle: camera handle |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_cancel_auto_focus(mm_camera_obj_t *my_obj) |
| { |
| int32_t rc = -1; |
| int32_t value = 0; |
| rc = mm_camera_util_s_ctrl(my_obj, 0, my_obj->ctrl_fd, CAM_PRIV_CANCEL_AUTO_FOCUS, &value); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_prepare_snapshot |
| * |
| * DESCRIPTION: prepare hardware for snapshot |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @do_af_flag : flag indicating if AF is needed |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_prepare_snapshot(mm_camera_obj_t *my_obj, |
| int32_t do_af_flag) |
| { |
| int32_t rc = -1; |
| int32_t value = do_af_flag; |
| rc = mm_camera_util_s_ctrl(my_obj, 0, my_obj->ctrl_fd, CAM_PRIV_PREPARE_SNAPSHOT, &value); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_start_zsl_snapshot |
| * |
| * DESCRIPTION: start zsl snapshot |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_start_zsl_snapshot(mm_camera_obj_t *my_obj) |
| { |
| int32_t rc = -1; |
| int32_t value = 0; |
| |
| rc = mm_camera_util_s_ctrl(my_obj, 0, my_obj->ctrl_fd, |
| CAM_PRIV_START_ZSL_SNAPSHOT, &value); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_stop_zsl_snapshot |
| * |
| * DESCRIPTION: stop zsl capture |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_stop_zsl_snapshot(mm_camera_obj_t *my_obj) |
| { |
| int32_t rc = -1; |
| int32_t value; |
| rc = mm_camera_util_s_ctrl(my_obj, 0, my_obj->ctrl_fd, |
| CAM_PRIV_STOP_ZSL_SNAPSHOT, &value); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_flush |
| * |
| * DESCRIPTION: flush the current camera state and buffers |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_flush(mm_camera_obj_t *my_obj) |
| { |
| int32_t rc = -1; |
| int32_t value; |
| rc = mm_camera_util_s_ctrl(my_obj, 0, my_obj->ctrl_fd, |
| CAM_PRIV_FLUSH, &value); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_add_channel |
| * |
| * DESCRIPTION: add a channel |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @attr : bundle attribute of the channel if needed |
| * @channel_cb : callback function for bundle data notify |
| * @userdata : user data ptr |
| * |
| * RETURN : uint32_t type of channel handle |
| * 0 -- invalid channel handle, meaning the op failed |
| * >0 -- successfully added a channel with a valid handle |
| * NOTE : if no bundle data notify is needed, meaning each stream in the |
| * channel will have its own stream data notify callback, then |
| * attr, channel_cb, and userdata can be NULL. In this case, |
| * no matching logic will be performed in channel for the bundling. |
| *==========================================================================*/ |
| uint32_t mm_camera_add_channel(mm_camera_obj_t *my_obj, |
| mm_camera_channel_attr_t *attr, |
| mm_camera_buf_notify_t channel_cb, |
| void *userdata) |
| { |
| mm_channel_t *ch_obj = NULL; |
| uint8_t ch_idx = 0; |
| uint32_t ch_hdl = 0; |
| |
| for(ch_idx = 0; ch_idx < MM_CAMERA_CHANNEL_MAX; ch_idx++) { |
| if (MM_CHANNEL_STATE_NOTUSED == my_obj->ch[ch_idx].state) { |
| ch_obj = &my_obj->ch[ch_idx]; |
| break; |
| } |
| } |
| |
| if (NULL != ch_obj) { |
| /* initialize channel obj */ |
| memset(ch_obj, 0, sizeof(mm_channel_t)); |
| ch_hdl = mm_camera_util_generate_handler_by_num(my_obj->my_num, ch_idx); |
| ch_obj->my_hdl = ch_hdl; |
| ch_obj->state = MM_CHANNEL_STATE_STOPPED; |
| ch_obj->cam_obj = my_obj; |
| pthread_mutex_init(&ch_obj->ch_lock, NULL); |
| ch_obj->sessionid = my_obj->sessionid; |
| mm_channel_init(ch_obj, attr, channel_cb, userdata); |
| } |
| |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return ch_hdl; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_del_channel |
| * |
| * DESCRIPTION: delete a channel by its handle |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : all streams in the channel should be stopped already before |
| * this channel can be deleted. |
| *==========================================================================*/ |
| int32_t mm_camera_del_channel(mm_camera_obj_t *my_obj, |
| uint32_t ch_id) |
| { |
| int32_t rc = -1; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_DELETE, |
| NULL, |
| NULL); |
| |
| if (ch_obj->master_ch_obj != NULL) { |
| ch_obj->master_ch_obj->num_s_cnt--; |
| ch_obj->master_ch_obj->aux_ch_obj[ch_obj->master_ch_obj->num_s_cnt] = NULL; |
| } |
| pthread_mutex_destroy(&ch_obj->ch_lock); |
| memset(ch_obj, 0, sizeof(mm_channel_t)); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_get_bundle_info |
| * |
| * DESCRIPTION: query bundle info of the channel |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @bundle_info : bundle info to be filled in |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : all streams in the channel should be stopped already before |
| * this channel can be deleted. |
| *==========================================================================*/ |
| int32_t mm_camera_get_bundle_info(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| cam_bundle_config_t *bundle_info) |
| { |
| int32_t rc = -1; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_GET_BUNDLE_INFO, |
| (void *)bundle_info, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_link_stream |
| * |
| * DESCRIPTION: link a stream into a channel |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @stream_id : stream that will be linked |
| * @linked_ch_id : channel in which the stream will be linked |
| * |
| * RETURN : uint32_t type of stream handle |
| * 0 -- invalid stream handle, meaning the op failed |
| * >0 -- successfully linked a stream with a valid handle |
| *==========================================================================*/ |
| uint32_t mm_camera_link_stream(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| uint32_t stream_id, |
| uint32_t linked_ch_id) |
| { |
| uint32_t s_hdl = 0; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, linked_ch_id); |
| mm_channel_t * owner_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if ((NULL != ch_obj) && (NULL != owner_obj)) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| mm_camera_stream_link_t stream_link; |
| memset(&stream_link, 0, sizeof(mm_camera_stream_link_t)); |
| stream_link.ch = owner_obj; |
| stream_link.stream_id = stream_id; |
| mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_LINK_STREAM, |
| (void*)&stream_link, |
| (void*)&s_hdl); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return s_hdl; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_add_stream |
| * |
| * DESCRIPTION: add a stream into a channel |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * |
| * RETURN : uint32_t type of stream handle |
| * 0 -- invalid stream handle, meaning the op failed |
| * >0 -- successfully added a stream with a valid handle |
| *==========================================================================*/ |
| uint32_t mm_camera_add_stream(mm_camera_obj_t *my_obj, |
| uint32_t ch_id) |
| { |
| uint32_t s_hdl = 0; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_ADD_STREAM, |
| NULL, |
| (void *)&s_hdl); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return s_hdl; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_del_stream |
| * |
| * DESCRIPTION: delete a stream by its handle |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @stream_id : stream handle |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : stream should be stopped already before it can be deleted. |
| *==========================================================================*/ |
| int32_t mm_camera_del_stream(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| uint32_t stream_id) |
| { |
| int32_t rc = -1; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_DEL_STREAM, |
| (void *)&stream_id, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_start_zsl_snapshot_ch |
| * |
| * DESCRIPTION: starts zsl snapshot for specific channel |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_start_zsl_snapshot_ch(mm_camera_obj_t *my_obj, |
| uint32_t ch_id) |
| { |
| int32_t rc = -1; |
| mm_channel_t *ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_START_ZSL_SNAPSHOT, |
| NULL, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_stop_zsl_snapshot_ch |
| * |
| * DESCRIPTION: stops zsl snapshot for specific channel |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_stop_zsl_snapshot_ch(mm_camera_obj_t *my_obj, |
| uint32_t ch_id) |
| { |
| int32_t rc = -1; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_STOP_ZSL_SNAPSHOT, |
| NULL, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_config_stream |
| * |
| * DESCRIPTION: configure a stream |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @stream_id : stream handle |
| * @config : stream configuration |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_config_stream(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| uint32_t stream_id, |
| mm_camera_stream_config_t *config) |
| { |
| int32_t rc = -1; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| mm_evt_paylod_config_stream_t payload; |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| memset(&payload, 0, sizeof(mm_evt_paylod_config_stream_t)); |
| payload.stream_id = stream_id; |
| payload.config = config; |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_CONFIG_STREAM, |
| (void *)&payload, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_start_channel |
| * |
| * DESCRIPTION: start a channel, which will start all streams in the channel |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_start_channel(mm_camera_obj_t *my_obj, uint32_t ch_id) |
| { |
| int32_t rc = -1; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_START, |
| NULL, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_stop_channel |
| * |
| * DESCRIPTION: stop a channel, which will stop all streams in the channel |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_stop_channel(mm_camera_obj_t *my_obj, |
| uint32_t ch_id) |
| { |
| int32_t rc = 0; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_STOP, |
| NULL, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_request_super_buf |
| * |
| * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched |
| * frames from superbuf queue |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @num_buf_requested : number of matched frames needed |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_request_super_buf(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, mm_camera_req_buf_t *buf) |
| { |
| int32_t rc = -1; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if ((NULL != ch_obj) && (buf != NULL)) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| rc = mm_channel_fsm_fn(ch_obj, MM_CHANNEL_EVT_REQUEST_SUPER_BUF, |
| (void *)buf, NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_cancel_super_buf_request |
| * |
| * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount |
| * of matched frames from superbuf queue |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_cancel_super_buf_request(mm_camera_obj_t *my_obj, uint32_t ch_id) |
| { |
| int32_t rc = -1; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF, |
| NULL, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_flush_super_buf_queue |
| * |
| * DESCRIPTION: flush out all frames in the superbuf queue |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_flush_super_buf_queue(mm_camera_obj_t *my_obj, uint32_t ch_id, |
| uint32_t frame_idx) |
| { |
| int32_t rc = -1; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE, |
| (void *)&frame_idx, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_config_channel_notify |
| * |
| * DESCRIPTION: configures the channel notification mode |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @notify_mode : notification mode |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_config_channel_notify(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| mm_camera_super_buf_notify_mode_t notify_mode) |
| { |
| int32_t rc = -1; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE, |
| (void *)¬ify_mode, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_set_stream_parms |
| * |
| * DESCRIPTION: set parameters per stream |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @s_id : stream handle |
| * @parms : ptr to a param struct to be set to server |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : Assume the parms struct buf is already mapped to server via |
| * domain socket. Corresponding fields of parameters to be set |
| * are already filled in by upper layer caller. |
| *==========================================================================*/ |
| int32_t mm_camera_set_stream_parms(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| uint32_t s_id, |
| cam_stream_parm_buffer_t *parms) |
| { |
| int32_t rc = -1; |
| mm_evt_paylod_set_get_stream_parms_t payload; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| memset(&payload, 0, sizeof(payload)); |
| payload.stream_id = s_id; |
| payload.parms = parms; |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_SET_STREAM_PARM, |
| (void *)&payload, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_get_stream_parms |
| * |
| * DESCRIPTION: get parameters per stream |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @s_id : stream handle |
| * @parms : ptr to a param struct to be get from server |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : Assume the parms struct buf is already mapped to server via |
| * domain socket. Parameters to be get from server are already |
| * filled in by upper layer caller. After this call, corresponding |
| * fields of requested parameters will be filled in by server with |
| * detailed information. |
| *==========================================================================*/ |
| int32_t mm_camera_get_stream_parms(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| uint32_t s_id, |
| cam_stream_parm_buffer_t *parms) |
| { |
| int32_t rc = -1; |
| mm_evt_paylod_set_get_stream_parms_t payload; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| memset(&payload, 0, sizeof(payload)); |
| payload.stream_id = s_id; |
| payload.parms = parms; |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_GET_STREAM_PARM, |
| (void *)&payload, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_do_stream_action |
| * |
| * DESCRIPTION: request server to perform stream based action. Maybe removed later |
| * if the functionality is included in mm_camera_set_parms |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @s_id : stream handle |
| * @actions : ptr to an action struct buf to be performed by server |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : Assume the action struct buf is already mapped to server via |
| * domain socket. Actions to be performed by server are already |
| * filled in by upper layer caller. |
| *==========================================================================*/ |
| int32_t mm_camera_do_stream_action(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| uint32_t stream_id, |
| void *actions) |
| { |
| int32_t rc = -1; |
| mm_evt_paylod_do_stream_action_t payload; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| memset(&payload, 0, sizeof(payload)); |
| payload.stream_id = stream_id; |
| payload.actions = actions; |
| |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_DO_ACTION, |
| (void*)&payload, NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_map_stream_buf |
| * |
| * DESCRIPTION: mapping stream buffer via domain socket to server |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @s_id : stream handle |
| * @buf_type : type of buffer to be mapped. could be following values: |
| * CAM_MAPPING_BUF_TYPE_STREAM_BUF |
| * CAM_MAPPING_BUF_TYPE_STREAM_INFO |
| * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF |
| * @buf_idx : index of buffer within the stream buffers, only valid if |
| * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or |
| * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF |
| * @plane_idx : plane index. If all planes share the same fd, |
| * plane_idx = -1; otherwise, plean_idx is the |
| * index to plane (0..num_of_planes) |
| * @fd : file descriptor of the buffer |
| * @size : size of the buffer |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_map_stream_buf(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| uint32_t stream_id, |
| uint8_t buf_type, |
| uint32_t buf_idx, |
| int32_t plane_idx, |
| int fd, |
| size_t size, |
| void *buffer) |
| { |
| int32_t rc = -1; |
| cam_buf_map_type payload; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| memset(&payload, 0, sizeof(payload)); |
| payload.stream_id = stream_id; |
| payload.type = buf_type; |
| payload.frame_idx = buf_idx; |
| payload.plane_idx = plane_idx; |
| payload.fd = fd; |
| payload.size = size; |
| payload.buffer = buffer; |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_MAP_STREAM_BUF, |
| (void*)&payload, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_map_stream_bufs |
| * |
| * DESCRIPTION: mapping stream buffers via domain socket to server |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @buf_map_list : list of buffers to be mapped |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_map_stream_bufs(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| const cam_buf_map_type_list *buf_map_list) |
| { |
| int32_t rc = -1; |
| cam_buf_map_type_list payload; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| memcpy(&payload, buf_map_list, sizeof(payload)); |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_MAP_STREAM_BUFS, |
| (void*)&payload, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_unmap_stream_buf |
| * |
| * DESCRIPTION: unmapping stream buffer via domain socket to server |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @s_id : stream handle |
| * @buf_type : type of buffer to be mapped. could be following values: |
| * CAM_MAPPING_BUF_TYPE_STREAM_BUF |
| * CAM_MAPPING_BUF_TYPE_STREAM_INFO |
| * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF |
| * @buf_idx : index of buffer within the stream buffers, only valid if |
| * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or |
| * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF |
| * @plane_idx : plane index. If all planes share the same fd, |
| * plane_idx = -1; otherwise, plean_idx is the |
| * index to plane (0..num_of_planes) |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_unmap_stream_buf(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, |
| uint32_t stream_id, |
| uint8_t buf_type, |
| uint32_t buf_idx, |
| int32_t plane_idx) |
| { |
| int32_t rc = -1; |
| cam_buf_unmap_type payload; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| memset(&payload, 0, sizeof(payload)); |
| payload.stream_id = stream_id; |
| payload.type = buf_type; |
| payload.frame_idx = buf_idx; |
| payload.plane_idx = plane_idx; |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_UNMAP_STREAM_BUF, |
| (void*)&payload, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_evt_sub |
| * |
| * DESCRIPTION: subscribe/unsubscribe event notify from kernel |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @reg_flag : 1 -- subscribe ; 0 -- unsubscribe |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj, |
| uint8_t reg_flag) |
| { |
| int32_t rc = 0; |
| struct v4l2_event_subscription sub; |
| |
| memset(&sub, 0, sizeof(sub)); |
| sub.type = MSM_CAMERA_V4L2_EVENT_TYPE; |
| sub.id = MSM_CAMERA_MSM_NOTIFY; |
| if(FALSE == reg_flag) { |
| /* unsubscribe */ |
| rc = ioctl(my_obj->ctrl_fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); |
| if (rc < 0) { |
| LOGE("unsubscribe event rc = %d, errno %d", |
| rc, errno); |
| return rc; |
| } |
| /* remove evt fd from the polling thraed when unreg the last event */ |
| rc = mm_camera_poll_thread_del_poll_fd(&my_obj->evt_poll_thread, |
| 0, my_obj->my_hdl, mm_camera_sync_call); |
| } else { |
| rc = ioctl(my_obj->ctrl_fd, VIDIOC_SUBSCRIBE_EVENT, &sub); |
| if (rc < 0) { |
| LOGE("subscribe event rc = %d, errno %d", |
| rc, errno); |
| return rc; |
| } |
| /* add evt fd to polling thread when subscribe the first event */ |
| rc = mm_camera_poll_thread_add_poll_fd(&my_obj->evt_poll_thread, |
| 0, my_obj->my_hdl, my_obj->ctrl_fd, mm_camera_event_notify, |
| (void*)my_obj, mm_camera_sync_call); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_util_wait_for_event |
| * |
| * DESCRIPTION: utility function to wait for certain events |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @evt_mask : mask for events to be waited. Any of event in the mask would |
| * trigger the wait to end |
| * @status : status of the event |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void mm_camera_util_wait_for_event(mm_camera_obj_t *my_obj, |
| uint32_t evt_mask, |
| uint32_t *status) |
| { |
| int32_t rc = 0; |
| struct timespec ts; |
| |
| pthread_mutex_lock(&my_obj->evt_lock); |
| while (!(my_obj->evt_rcvd.server_event_type & evt_mask)) { |
| clock_gettime(CLOCK_REALTIME, &ts); |
| ts.tv_sec += WAIT_TIMEOUT; |
| rc = pthread_cond_timedwait(&my_obj->evt_cond, &my_obj->evt_lock, &ts); |
| if (rc) { |
| LOGE("pthread_cond_timedwait of evt_mask 0x%x failed %d", |
| evt_mask, rc); |
| break; |
| } |
| } |
| if (!rc) { |
| *status = my_obj->evt_rcvd.status; |
| } else { |
| *status = MSM_CAMERA_STATUS_FAIL; |
| } |
| /* reset local storage for recieved event for next event */ |
| memset(&my_obj->evt_rcvd, 0, sizeof(mm_camera_event_t)); |
| pthread_mutex_unlock(&my_obj->evt_lock); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_util_bundled_sendmsg |
| * |
| * DESCRIPTION: utility function to send bundled msg via domain socket |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @msg : message to be sent |
| * @buf_size : size of the message to be sent |
| * @sendfds : array of file descriptors to be sent |
| * @numfds : number of file descriptors to be sent |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_util_bundled_sendmsg(mm_camera_obj_t *my_obj, |
| void *msg, |
| size_t buf_size, |
| int sendfds[CAM_MAX_NUM_BUFS_PER_STREAM], |
| int numfds) |
| { |
| int32_t rc = -1; |
| uint32_t status; |
| |
| /* need to lock msg_lock, since sendmsg until response back is deemed as one operation*/ |
| pthread_mutex_lock(&my_obj->msg_lock); |
| if(mm_camera_socket_bundle_sendmsg(my_obj->ds_fd, msg, buf_size, sendfds, numfds) > 0) { |
| /* wait for event that mapping/unmapping is done */ |
| mm_camera_util_wait_for_event(my_obj, CAM_EVENT_TYPE_MAP_UNMAP_DONE, &status); |
| if (MSM_CAMERA_STATUS_SUCCESS == status) { |
| rc = 0; |
| } |
| } |
| pthread_mutex_unlock(&my_obj->msg_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_util_sendmsg |
| * |
| * DESCRIPTION: utility function to send msg via domain socket |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @msg : message to be sent |
| * @buf_size : size of the message to be sent |
| * @sendfd : >0 if any file descriptor need to be passed across process |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_util_sendmsg(mm_camera_obj_t *my_obj, |
| void *msg, |
| size_t buf_size, |
| int sendfd) |
| { |
| int32_t rc = -1; |
| uint32_t status; |
| |
| /* need to lock msg_lock, since sendmsg until reposonse back is deemed as one operation*/ |
| pthread_mutex_lock(&my_obj->msg_lock); |
| if(mm_camera_socket_sendmsg(my_obj->ds_fd, msg, buf_size, sendfd) > 0) { |
| /* wait for event that mapping/unmapping is done */ |
| mm_camera_util_wait_for_event(my_obj, CAM_EVENT_TYPE_MAP_UNMAP_DONE, &status); |
| if (MSM_CAMERA_STATUS_SUCCESS == status) { |
| rc = 0; |
| } |
| } |
| pthread_mutex_unlock(&my_obj->msg_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTIOa : mm_camera_map_buf |
| * |
| * DESCRIPTION: mapping camera buffer via domain socket to server |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @buf_type : type of buffer to be mapped. could be following values: |
| * CAM_MAPPING_BUF_TYPE_CAPABILITY |
| * CAM_MAPPING_BUF_TYPE_SETPARM_BUF |
| * CAM_MAPPING_BUF_TYPE_GETPARM_BUF |
| * @fd : file descriptor of the buffer |
| * @size : size of the buffer |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_map_buf(mm_camera_obj_t *my_obj, |
| uint8_t buf_type, int fd, size_t size, void *buffer) |
| { |
| int32_t rc = 0; |
| |
| cam_sock_packet_t packet; |
| memset(&packet, 0, sizeof(cam_sock_packet_t)); |
| packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING; |
| packet.payload.buf_map.type = buf_type; |
| packet.payload.buf_map.fd = fd; |
| packet.payload.buf_map.size = size; |
| packet.payload.buf_map.buffer = buffer; |
| #ifdef DAEMON_PRESENT |
| rc = mm_camera_util_sendmsg(my_obj, |
| &packet, |
| sizeof(cam_sock_packet_t), |
| fd); |
| #else |
| cam_shim_packet_t *shim_cmd; |
| shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_REG_BUF, |
| my_obj->sessionid, &packet); |
| rc = mm_camera_module_send_cmd(shim_cmd); |
| mm_camera_destroy_shim_cmd_packet(shim_cmd); |
| #endif |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_map_bufs |
| * |
| * DESCRIPTION: mapping camera buffers via domain socket to server |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @buf_map_list : list of buffers to be mapped |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_map_bufs(mm_camera_obj_t *my_obj, |
| const cam_buf_map_type_list* buf_map_list) |
| { |
| int32_t rc = 0; |
| cam_sock_packet_t packet; |
| memset(&packet, 0, sizeof(cam_sock_packet_t)); |
| packet.msg_type = CAM_MAPPING_TYPE_FD_BUNDLED_MAPPING; |
| |
| memcpy(&packet.payload.buf_map_list, buf_map_list, |
| sizeof(packet.payload.buf_map_list)); |
| |
| int sendfds[CAM_MAX_NUM_BUFS_PER_STREAM]; |
| uint32_t numbufs = packet.payload.buf_map_list.length; |
| uint32_t i; |
| for (i = 0; i < numbufs; i++) { |
| sendfds[i] = packet.payload.buf_map_list.buf_maps[i].fd; |
| packet.payload.buf_map_list.buf_maps[i].buffer = |
| buf_map_list->buf_maps[i].buffer; |
| } |
| for (i = numbufs; i < CAM_MAX_NUM_BUFS_PER_STREAM; i++) { |
| packet.payload.buf_map_list.buf_maps[i].fd = -1; |
| sendfds[i] = -1; |
| } |
| |
| #ifdef DAEMON_PRESENT |
| rc = mm_camera_util_bundled_sendmsg(my_obj, |
| &packet, sizeof(cam_sock_packet_t), |
| sendfds, numbufs); |
| #else |
| cam_shim_packet_t *shim_cmd; |
| shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_REG_BUF, |
| my_obj->sessionid, &packet); |
| rc = mm_camera_module_send_cmd(shim_cmd); |
| mm_camera_destroy_shim_cmd_packet(shim_cmd); |
| #endif |
| |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_unmap_buf |
| * |
| * DESCRIPTION: unmapping camera buffer via domain socket to server |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @buf_type : type of buffer to be mapped. could be following values: |
| * CAM_MAPPING_BUF_TYPE_CAPABILITY |
| * CAM_MAPPING_BUF_TYPE_SETPARM_BUF |
| * CAM_MAPPING_BUF_TYPE_GETPARM_BUF |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_unmap_buf(mm_camera_obj_t *my_obj, |
| uint8_t buf_type) |
| { |
| int32_t rc = 0; |
| cam_sock_packet_t packet; |
| memset(&packet, 0, sizeof(cam_sock_packet_t)); |
| packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING; |
| packet.payload.buf_unmap.type = buf_type; |
| #ifdef DAEMON_PRESENT |
| rc = mm_camera_util_sendmsg(my_obj, |
| &packet, |
| sizeof(cam_sock_packet_t), |
| -1); |
| #else |
| cam_shim_packet_t *shim_cmd; |
| shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_REG_BUF, |
| my_obj->sessionid, &packet); |
| rc = mm_camera_module_send_cmd(shim_cmd); |
| mm_camera_destroy_shim_cmd_packet(shim_cmd); |
| #endif |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_util_s_ctrl |
| * |
| * DESCRIPTION: utility function to send v4l2 ioctl for s_ctrl |
| * |
| * PARAMETERS : |
| * @my_obj :Camera object |
| * @stream_id :streamID |
| * @fd : file descritpor for sending ioctl |
| * @id : control id |
| * @value : value of the ioctl to be sent |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_util_s_ctrl(__unused mm_camera_obj_t *my_obj, |
| __unused int stream_id, int32_t fd, |
| uint32_t id, int32_t *value) |
| { |
| int rc = 0; |
| |
| #ifdef DAEMON_PRESENT |
| struct v4l2_control control; |
| memset(&control, 0, sizeof(control)); |
| control.id = id; |
| if (value != NULL) { |
| control.value = *value; |
| } |
| rc = ioctl(fd, VIDIOC_S_CTRL, &control); |
| LOGD("fd=%d, S_CTRL, id=0x%x, value = %p, rc = %d\n", |
| fd, id, value, rc); |
| if (rc < 0) { |
| LOGE("ioctl failed %d, errno %d", rc, errno); |
| } else if (value != NULL) { |
| *value = control.value; |
| } |
| #else /* DAEMON_PRESENT */ |
| cam_shim_packet_t *shim_cmd; |
| cam_shim_cmd_data shim_cmd_data; |
| (void)fd; |
| (void)value; |
| memset(&shim_cmd_data, 0, sizeof(shim_cmd_data)); |
| |
| shim_cmd_data.command = id; |
| shim_cmd_data.stream_id = stream_id; |
| shim_cmd_data.value = NULL; |
| shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_SET_PARM, |
| my_obj->sessionid,&shim_cmd_data); |
| rc = mm_camera_module_send_cmd(shim_cmd); |
| mm_camera_destroy_shim_cmd_packet(shim_cmd); |
| #endif /* DAEMON_PRESENT */ |
| return (rc >= 0)? 0 : -1; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_util_g_ctrl |
| * |
| * DESCRIPTION: utility function to send v4l2 ioctl for g_ctrl |
| * |
| * PARAMETERS : |
| * @my_obj :Camera object |
| * @stream_id :streamID |
| * @fd : file descritpor for sending ioctl |
| * @id : control id |
| * @value : value of the ioctl to be sent |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_util_g_ctrl(__unused mm_camera_obj_t *my_obj, |
| __unused int stream_id, int32_t fd, uint32_t id, int32_t *value) |
| { |
| int rc = 0; |
| struct v4l2_control control; |
| |
| memset(&control, 0, sizeof(control)); |
| control.id = id; |
| if (value != NULL) { |
| control.value = *value; |
| } |
| |
| #ifdef DAEMON_PRESENT |
| rc = ioctl(fd, VIDIOC_G_CTRL, &control); |
| LOGD("fd=%d, G_CTRL, id=0x%x, rc = %d\n", fd, id, rc); |
| if (value != NULL) { |
| *value = control.value; |
| } |
| #else /* DAEMON_PRESENT */ |
| cam_shim_packet_t *shim_cmd; |
| cam_shim_cmd_data shim_cmd_data; |
| (void)fd; |
| memset(&shim_cmd_data, 0, sizeof(shim_cmd_data)); |
| |
| shim_cmd_data.command = id; |
| shim_cmd_data.stream_id = stream_id; |
| shim_cmd_data.value = value; |
| shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_GET_PARM, |
| my_obj->sessionid, &shim_cmd_data); |
| |
| rc = mm_camera_module_send_cmd(shim_cmd); |
| mm_camera_destroy_shim_cmd_packet(shim_cmd); |
| #endif /* DAEMON_PRESENT */ |
| return (rc >= 0)? 0 : -1; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_create_shim_cmd |
| * |
| * DESCRIPTION: Prepare comand packet to pass to back-end through shim layer |
| * |
| * PARAMETERS : |
| * @type : type of command |
| * @sessionID : camera sessionID |
| * @data : command data |
| * |
| * RETURN : NULL in case of failures |
| allocated pointer to shim packet |
| *==========================================================================*/ |
| cam_shim_packet_t *mm_camera_create_shim_cmd_packet(cam_shim_cmd_type type, |
| uint32_t sessionID, void *data) |
| { |
| cam_shim_packet_t *shim_pack = NULL; |
| uint32_t i = 0; |
| |
| shim_pack = (cam_shim_packet_t *)malloc(sizeof(cam_shim_packet_t)); |
| if (shim_pack == NULL) { |
| LOGE("Cannot allocate a memory for shim packet"); |
| return NULL; |
| } |
| memset(shim_pack, 0, sizeof(cam_shim_packet_t)); |
| shim_pack->cmd_type = type; |
| shim_pack->session_id = sessionID; |
| switch (type) { |
| case CAM_SHIM_SET_PARM: |
| case CAM_SHIM_GET_PARM: { |
| cam_shim_cmd_data *cmd_data = (cam_shim_cmd_data *)data; |
| shim_pack->cmd_data = *cmd_data; |
| break; |
| } |
| case CAM_SHIM_REG_BUF: { |
| cam_reg_buf_t *cmd_data = (cam_reg_buf_t *)data; |
| shim_pack->reg_buf = *cmd_data; |
| break; |
| } |
| case CAM_SHIM_BUNDLE_CMD: { |
| cam_shim_stream_cmd_packet_t *cmd_data = (cam_shim_stream_cmd_packet_t *)data; |
| for (i = 0; i < cmd_data->stream_count; i++) { |
| shim_pack->bundle_cmd.stream_event[i] = cmd_data->stream_event[i]; |
| } |
| shim_pack->bundle_cmd.stream_count = cmd_data->stream_count; |
| break; |
| } |
| default: |
| LOGW("No Data for this command"); |
| } |
| return shim_pack; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_destroy_shim_cmd |
| * |
| * DESCRIPTION: destroy shim packet |
| * |
| * PARAMETERS : |
| * @cmd : ptr to shim packet |
| |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_destroy_shim_cmd_packet(cam_shim_packet_t *cmd) |
| { |
| int32_t rc = 0; |
| uint32_t i = 0, j = 0; |
| |
| if (cmd == NULL) { |
| LOGW("Command is NULL"); |
| return rc; |
| } |
| |
| switch (cmd->cmd_type) { |
| case CAM_SHIM_SET_PARM: |
| case CAM_SHIM_GET_PARM: |
| case CAM_SHIM_REG_BUF: |
| break; |
| case CAM_SHIM_BUNDLE_CMD: { |
| cam_shim_stream_cmd_packet_t *cmd_data = (cam_shim_stream_cmd_packet_t *)cmd; |
| for (i = 0; i < cmd_data->stream_count; i++) { |
| cam_shim_cmd_packet_t *stream_evt = &cmd_data->stream_event[i]; |
| for (j = 0; j < stream_evt->cmd_count; j++) { |
| if (stream_evt->cmd != NULL) { |
| if(stream_evt->cmd->cmd_type == CAM_SHIM_BUNDLE_CMD) { |
| mm_camera_destroy_shim_cmd_packet(stream_evt->cmd); |
| } |
| free(stream_evt->cmd); |
| stream_evt->cmd = NULL; |
| } |
| } |
| } |
| break; |
| } |
| default: |
| LOGW("No Data for this command"); |
| } |
| free(cmd); |
| cmd = NULL; |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_channel_advanced_capture |
| * |
| * DESCRIPTION: sets the channel advanced capture |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @type : advanced capture type. |
| * @start_flag : flag to indicate start/stop |
| * @in_value : input configaration |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_channel_advanced_capture(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, mm_camera_advanced_capture_t type, |
| uint32_t trigger, void *in_value) |
| { |
| LOGD("E type = %d", type); |
| int32_t rc = -1; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| switch (type) { |
| case MM_CAMERA_AF_BRACKETING: |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_AF_BRACKETING, |
| (void *)&trigger, |
| NULL); |
| break; |
| case MM_CAMERA_AE_BRACKETING: |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_AE_BRACKETING, |
| (void *)&trigger, |
| NULL); |
| break; |
| case MM_CAMERA_FLASH_BRACKETING: |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_FLASH_BRACKETING, |
| (void *)&trigger, |
| NULL); |
| break; |
| case MM_CAMERA_ZOOM_1X: |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_ZOOM_1X, |
| (void *)&trigger, |
| NULL); |
| break; |
| case MM_CAMERA_FRAME_CAPTURE: |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CAMERA_EVT_CAPTURE_SETTING, |
| (void *)in_value, |
| NULL); |
| break; |
| default: |
| break; |
| } |
| |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| LOGD("X"); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_get_session_id |
| * |
| * DESCRIPTION: get the session identity |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @sessionid: pointer to the output session id |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : if this call succeeds, we will get a valid session id |
| *==========================================================================*/ |
| int32_t mm_camera_get_session_id(mm_camera_obj_t *my_obj, |
| uint32_t* sessionid) |
| { |
| int32_t rc = -1; |
| int32_t value = 0; |
| if(sessionid != NULL) { |
| struct v4l2_control control; |
| memset(&control, 0, sizeof(control)); |
| control.id = MSM_CAMERA_PRIV_G_SESSION_ID; |
| control.value = value; |
| |
| rc = ioctl(my_obj->ctrl_fd, VIDIOC_G_CTRL, &control); |
| value = control.value; |
| LOGD("fd=%d, get_session_id, id=0x%x, value = %d, rc = %d\n", |
| my_obj->ctrl_fd, MSM_CAMERA_PRIV_G_SESSION_ID, |
| value, rc); |
| *sessionid = value; |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_sync_related_sensors |
| * |
| * DESCRIPTION: send sync cmd |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @parms : ptr to the related cam info to be sent to server |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : Assume the sync struct buf is already mapped to server via |
| * domain socket. Corresponding fields of parameters to be set |
| * are already filled in by upper layer caller. |
| *==========================================================================*/ |
| int32_t mm_camera_sync_related_sensors(mm_camera_obj_t *my_obj, |
| cam_sync_related_sensors_event_info_t* parms) |
| { |
| int32_t rc = -1; |
| int32_t value = 0; |
| if (parms != NULL) { |
| rc = mm_camera_util_s_ctrl(my_obj, 0, my_obj->ctrl_fd, |
| CAM_PRIV_SYNC_RELATED_SENSORS, &value); |
| } |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_reg_stream_buf_cb |
| * |
| * DESCRIPTION: Register callback for stream buffer |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @stream_id : stream that will be linked |
| * @buf_cb : special callback needs to be registered for stream buffer |
| * @cb_type : Callback type SYNC/ASYNC |
| * @userdata : user data pointer |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * 1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_reg_stream_buf_cb(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, uint32_t stream_id, mm_camera_buf_notify_t stream_cb, |
| mm_camera_stream_cb_type cb_type, void *userdata) |
| { |
| int rc = 0; |
| mm_stream_data_cb_t buf_cb; |
| mm_channel_t * ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| |
| memset(&buf_cb, 0, sizeof(mm_stream_data_cb_t)); |
| buf_cb.cb = stream_cb; |
| buf_cb.cb_count = -1; |
| buf_cb.cb_type = cb_type; |
| buf_cb.user_data = userdata; |
| |
| mm_evt_paylod_reg_stream_buf_cb payload; |
| memset(&payload, 0, sizeof(mm_evt_paylod_reg_stream_buf_cb)); |
| payload.buf_cb = buf_cb; |
| payload.stream_id = stream_id; |
| mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_REG_STREAM_BUF_CB, |
| (void*)&payload, NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_register_frame_sync |
| * |
| * DESCRIPTION: register/configure frame sync for this camera |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @stream_id : stream that will be linked |
| * @sync_attr : attibutes for sync queue |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * 1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_reg_frame_sync(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, uint32_t stream_id, |
| mm_camera_frame_sync_t *sync_attr) |
| { |
| int32_t rc = -1; |
| uint32_t sync_id = 0; |
| mm_evt_paylod_reg_frame_sync payload; |
| |
| mm_channel_t *ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| mm_channel_t *a_ch_obj = NULL; |
| |
| if (sync_attr != NULL && sync_attr->a_cam_obj != NULL) { |
| a_ch_obj = mm_camera_util_get_channel_by_handler( |
| sync_attr->a_cam_obj, sync_attr->a_ch_id); |
| } else { |
| LOGE("Invalid arguments"); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| return rc; |
| } |
| |
| if (NULL != ch_obj && a_ch_obj != NULL) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| memset(&payload, 0, sizeof(payload)); |
| payload.stream_id = stream_id; |
| payload.sync_attr = sync_attr; |
| payload.a_ch_obj = a_ch_obj; |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_REG_FRAME_SYNC, |
| (void*)&payload, (void*)&sync_id); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_start_frame_sync |
| * |
| * DESCRIPTION: start frame sync under this camera |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @stream_id : stream that will be linked |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * 1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_start_frame_sync(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, uint32_t stream_id) |
| { |
| int32_t rc = -1; |
| |
| mm_channel_t *ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| mm_evt_paylod_trigger_frame_sync payload; |
| payload.enable_frame_sync = 1; |
| payload.stream_id = stream_id; |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_TRIGGER_FRAME_SYNC, |
| (void*)&payload, NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_stop_frame_sync |
| * |
| * DESCRIPTION: stop frame sync under this camera |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @stream_id : stream that will be linked |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * 1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_stop_frame_sync(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, uint32_t stream_id) |
| { |
| int32_t rc = -1; |
| |
| mm_channel_t *ch_obj = |
| mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| mm_evt_paylod_trigger_frame_sync payload; |
| payload.enable_frame_sync = 0; |
| payload.stream_id = stream_id; |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_TRIGGER_FRAME_SYNC, |
| (void*)&payload, NULL); |
| |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_camera_switch_stream_cb |
| * |
| * DESCRIPTION: switch stream callbacks in case of multiple instance of streams |
| * |
| * PARAMETERS : |
| * @my_obj : camera object |
| * @ch_id : channel handle |
| * @stream_id : stream id |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * 1 -- failure |
| *==========================================================================*/ |
| int32_t mm_camera_switch_stream_cb(mm_camera_obj_t *my_obj, |
| uint32_t ch_id, uint32_t stream_id) |
| { |
| int rc = -1; |
| mm_channel_t *ch_obj = NULL; |
| ch_obj = mm_camera_util_get_channel_by_handler(my_obj, ch_id); |
| |
| if (NULL != ch_obj) { |
| pthread_mutex_lock(&ch_obj->ch_lock); |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| rc = mm_channel_fsm_fn(ch_obj, |
| MM_CHANNEL_EVT_SWITCH_STREAM_CB, |
| (void *)&stream_id, |
| NULL); |
| } else { |
| pthread_mutex_unlock(&my_obj->cam_lock); |
| } |
| |
| return rc; |
| } |
| |
| #ifdef QCAMERA_REDEFINE_LOG |
| /*=========================================================================== |
| * DESCRIPTION: mm camera debug interface |
| * |
| *==========================================================================*/ |
| pthread_mutex_t dbg_log_mutex; |
| |
| static int cam_soft_assert = 0; |
| static FILE *cam_log_fd = NULL; |
| static const char *cam_log_filename = "/data/misc/camera/cam_dbg_log_hal.txt"; |
| |
| #undef LOG_TAG |
| #define LOG_TAG "QCamera" |
| #define CDBG_MAX_STR_LEN 1024 |
| #define CDBG_MAX_LINE_LENGTH 256 |
| |
| /* current trace loggin permissions |
| * {NONE, ERR, WARN, HIGH, DEBUG, LOW, INFO} */ |
| int g_cam_log[CAM_LAST_MODULE][CAM_GLBL_DBG_INFO + 1] = { |
| {0, 1, 0, 0, 0, 0, 1}, /* CAM_NO_MODULE */ |
| {0, 1, 0, 0, 0, 0, 1}, /* CAM_HAL_MODULE */ |
| {0, 1, 0, 0, 0, 0, 1}, /* CAM_MCI_MODULE */ |
| {0, 1, 0, 0, 0, 0, 1}, /* CAM_JPEG_MODULE */ |
| }; |
| |
| /* string representation for logging level */ |
| static const char *cam_dbg_level_to_str[] = { |
| "", /* CAM_GLBL_DBG_NONE */ |
| "<ERROR>", /* CAM_GLBL_DBG_ERR */ |
| "<WARN>", /* CAM_GLBL_DBG_WARN */ |
| "<HIGH>", /* CAM_GLBL_DBG_HIGH */ |
| "<DBG>", /* CAM_GLBL_DBG_DEBUG */ |
| "<LOW>", /* CAM_GLBL_DBG_LOW */ |
| "<INFO>" /* CAM_GLBL_DBG_INFO */ |
| }; |
| |
| /* current trace logging configuration */ |
| typedef struct { |
| cam_global_debug_level_t level; |
| int initialized; |
| const char *name; |
| const char *prop; |
| } module_debug_t; |
| |
| static module_debug_t cam_loginfo[(int)CAM_LAST_MODULE] = { |
| {CAM_GLBL_DBG_ERR, 1, |
| "", "persist.camera.global.debug" }, /* CAM_NO_MODULE */ |
| {CAM_GLBL_DBG_ERR, 1, |
| "<HAL>", "persist.camera.hal.debug" }, /* CAM_HAL_MODULE */ |
| {CAM_GLBL_DBG_ERR, 1, |
| "<MCI>", "persist.camera.mci.debug" }, /* CAM_MCI_MODULE */ |
| {CAM_GLBL_DBG_ERR, 1, |
| "<JPEG>", "persist.camera.mmstill.logs" }, /* CAM_JPEG_MODULE */ |
| }; |
| |
| /** cam_get_dbg_level |
| * |
| * @module: module name |
| * @level: module debug logging level |
| * |
| * Maps debug log string to value. |
| * |
| * Return: logging level |
| **/ |
| __unused |
| static cam_global_debug_level_t cam_get_dbg_level(const char *module, |
| char *pValue) { |
| |
| cam_global_debug_level_t rc = CAM_GLBL_DBG_NONE; |
| |
| if (!strcmp(pValue, "none")) { |
| rc = CAM_GLBL_DBG_NONE; |
| } else if (!strcmp(pValue, "warn")) { |
| rc = CAM_GLBL_DBG_WARN; |
| } else if (!strcmp(pValue, "debug")) { |
| rc = CAM_GLBL_DBG_DEBUG; |
| } else if (!strcmp(pValue, "error")) { |
| rc = CAM_GLBL_DBG_ERR; |
| } else if (!strcmp(pValue, "low")) { |
| rc = CAM_GLBL_DBG_LOW; |
| } else if (!strcmp(pValue, "high")) { |
| rc = CAM_GLBL_DBG_HIGH; |
| } else if (!strcmp(pValue, "info")) { |
| rc = CAM_GLBL_DBG_INFO; |
| } else { |
| ALOGE("Invalid %s debug log level %s\n", module, pValue); |
| } |
| |
| ALOGD("%s debug log level: %s\n", module, cam_dbg_level_to_str[rc]); |
| |
| return rc; |
| } |
| |
| /** cam_vsnprintf |
| * @pdst: destination buffer pointer |
| * @size: size of destination b uffer |
| * @pfmt: string format |
| * @argptr: variabkle length argument list |
| * |
| * Processes variable length argument list to a formatted string. |
| * |
| * Return: n/a |
| **/ |
| static void cam_vsnprintf(char* pdst, unsigned int size, |
| const char* pfmt, va_list argptr) { |
| int num_chars_written = 0; |
| |
| pdst[0] = '\0'; |
| num_chars_written = vsnprintf(pdst, size, pfmt, argptr); |
| |
| if ((num_chars_written >= (int)size) && (size > 0)) { |
| /* Message length exceeds the buffer limit size */ |
| num_chars_written = size - 1; |
| pdst[size - 1] = '\0'; |
| } |
| } |
| |
| /** mm_camera_debug_log |
| * @module: origin or log message |
| * @level: logging level |
| * @func: caller function name |
| * @line: caller line number |
| * @fmt: log message formatting string |
| * @...: variable argument list |
| * |
| * Generig logger method. |
| * |
| * Return: N/A |
| **/ |
| void mm_camera_debug_log(const cam_modules_t module, |
| const cam_global_debug_level_t level, |
| const char *func, const int line, const char *fmt, ...) { |
| char str_buffer[CDBG_MAX_STR_LEN]; |
| va_list args; |
| |
| va_start(args, fmt); |
| cam_vsnprintf(str_buffer, CDBG_MAX_STR_LEN, fmt, args); |
| va_end(args); |
| |
| switch (level) { |
| case CAM_GLBL_DBG_WARN: |
| ALOGW("%s%s %s: %d: %s", cam_loginfo[module].name, |
| cam_dbg_level_to_str[level], func, line, str_buffer); |
| break; |
| case CAM_GLBL_DBG_ERR: |
| ALOGE("%s%s %s: %d: %s", cam_loginfo[module].name, |
| cam_dbg_level_to_str[level], func, line, str_buffer); |
| break; |
| case CAM_GLBL_DBG_INFO: |
| ALOGI("%s%s %s: %d: %s", cam_loginfo[module].name, |
| cam_dbg_level_to_str[level], func, line, str_buffer); |
| break; |
| case CAM_GLBL_DBG_HIGH: |
| case CAM_GLBL_DBG_DEBUG: |
| case CAM_GLBL_DBG_LOW: |
| default: |
| ALOGD("%s%s %s: %d: %s", cam_loginfo[module].name, |
| cam_dbg_level_to_str[level], func, line, str_buffer); |
| } |
| |
| |
| if (cam_log_fd != NULL) { |
| char new_str_buffer[CDBG_MAX_STR_LEN]; |
| pthread_mutex_lock(&dbg_log_mutex); |
| |
| struct timeval tv; |
| struct timezone tz; |
| gettimeofday(&tv, &tz); |
| |
| struct tm *now; |
| now = gmtime((time_t *)&tv.tv_sec); |
| snprintf(new_str_buffer, CDBG_MAX_STR_LEN, "%2d %02d:%02d:%02d.%03ld %d:%d Camera%s%s %d: %s: %s", |
| now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec, tv.tv_usec, getpid(),gettid(), |
| cam_dbg_level_to_str[level], cam_loginfo[module].name, |
| line, func, str_buffer); |
| |
| fprintf(cam_log_fd, "%s", new_str_buffer); |
| pthread_mutex_unlock(&dbg_log_mutex); |
| } |
| |
| } |
| |
| /** mm_camera_set_dbg_log_properties |
| * |
| * Set global and module log level properties. |
| * |
| * Return: N/A |
| **/ |
| void mm_camera_set_dbg_log_properties(void) { |
| int i; |
| unsigned int j; |
| char property_value[PROPERTY_VALUE_MAX] = {0}; |
| char default_value[PROPERTY_VALUE_MAX] = {0}; |
| |
| /* set global and individual module logging levels */ |
| pthread_mutex_lock(&dbg_log_mutex); |
| for (i = CAM_NO_MODULE; i < CAM_LAST_MODULE; i++) { |
| cam_global_debug_level_t log_level; |
| snprintf(default_value, PROPERTY_VALUE_MAX, "%d", (int)cam_loginfo[i].level); |
| property_get(cam_loginfo[i].prop, property_value, default_value); |
| log_level = (cam_global_debug_level_t)atoi(property_value); |
| |
| /* fix KW warnings */ |
| if (log_level > CAM_GLBL_DBG_INFO) { |
| log_level = CAM_GLBL_DBG_INFO; |
| } |
| |
| cam_loginfo[i].level = log_level; |
| |
| /* The logging macros will produce a log message when logging level for |
| * a module is less or equal to the level specified in the property for |
| * the module, or less or equal the level specified by the global logging |
| * property. Currently we don't allow INFO logging to be turned off */ |
| for (j = CAM_GLBL_DBG_ERR; j <= CAM_GLBL_DBG_LOW; j++) { |
| g_cam_log[i][j] = (cam_loginfo[CAM_NO_MODULE].level != CAM_GLBL_DBG_NONE) && |
| (cam_loginfo[i].level != CAM_GLBL_DBG_NONE) && |
| ((j <= cam_loginfo[i].level) || |
| (j <= cam_loginfo[CAM_NO_MODULE].level)); |
| } |
| } |
| pthread_mutex_unlock(&dbg_log_mutex); |
| } |
| |
| /** mm_camera_debug_open |
| * |
| * Open log file if it is enabled |
| * |
| * Return: N/A |
| **/ |
| void mm_camera_debug_open(void) { |
| char property_value[PROPERTY_VALUE_MAX] = {0}; |
| |
| pthread_mutex_init(&dbg_log_mutex, 0); |
| mm_camera_set_dbg_log_properties(); |
| |
| /* configure asserts */ |
| property_get("persist.camera.debug.assert", property_value, "0"); |
| cam_soft_assert = atoi(property_value); |
| |
| /* open default log file according to property setting */ |
| if (cam_log_fd == NULL) { |
| property_get("persist.camera.debug.logfile", property_value, "0"); |
| if (atoi(property_value)) { |
| /* we always put the current process id at end of log file name */ |
| char pid_str[255] = {0}; |
| char new_log_file_name[1024] = {0}; |
| |
| snprintf(pid_str, 255, "_%d", getpid()); |
| strlcpy(new_log_file_name, cam_log_filename, sizeof(new_log_file_name)); |
| strlcat(new_log_file_name, pid_str, sizeof(new_log_file_name)); |
| |
| cam_log_fd = fopen(new_log_file_name, "a"); |
| if (cam_log_fd == NULL) { |
| ALOGE("Failed to create debug log file %s\n", |
| new_log_file_name); |
| } else { |
| ALOGD("Debug log file %s open\n", new_log_file_name); |
| } |
| } else { |
| property_set("persist.camera.debug.logfile", "0"); |
| ALOGD("Debug log file is not enabled"); |
| return; |
| } |
| } |
| } |
| |
| /** cam_debug_close |
| * |
| * Release logging resources. |
| * |
| * Return: N/A |
| **/ |
| void mm_camera_debug_close(void) { |
| |
| if (cam_log_fd != NULL) { |
| fclose(cam_log_fd); |
| cam_log_fd = NULL; |
| } |
| |
| pthread_mutex_destroy(&dbg_log_mutex); |
| } |
| #endif |