Home | History | Annotate | Download | only in src
      1 /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
      2  *
      3  * Redistribution and use in source and binary forms, with or without
      4  * modification, are permitted provided that the following conditions are
      5  * met:
      6  *     * Redistributions of source code must retain the above copyright
      7  *       notice, this list of conditions and the following disclaimer.
      8  *     * Redistributions in binary form must reproduce the above
      9  *       copyright notice, this list of conditions and the following
     10  *       disclaimer in the documentation and/or other materials provided
     11  *       with the distribution.
     12  *     * Neither the name of The Linux Foundation nor the names of its
     13  *       contributors may be used to endorse or promote products derived
     14  *       from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  *
     28  */
     29 
     30 #include <pthread.h>
     31 #include <errno.h>
     32 #include <sys/ioctl.h>
     33 #include <sys/types.h>
     34 #include <sys/stat.h>
     35 #include <fcntl.h>
     36 #include <poll.h>
     37 
     38 #include <cam_semaphore.h>
     39 
     40 #include "mm_camera_dbg.h"
     41 #include "mm_camera_sock.h"
     42 #include "mm_camera_interface.h"
     43 #include "mm_camera.h"
     44 
     45 #define SET_PARM_BIT32(parm, parm_arr) \
     46     (parm_arr[parm/32] |= (1<<(parm%32)))
     47 
     48 #define GET_PARM_BIT32(parm, parm_arr) \
     49     ((parm_arr[parm/32]>>(parm%32))& 0x1)
     50 
     51 /* internal function declare */
     52 int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj,
     53                           uint8_t reg_flag);
     54 int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj,
     55                               mm_camera_event_t *event);
     56 
     57 /*===========================================================================
     58  * FUNCTION   : mm_camera_util_get_channel_by_handler
     59  *
     60  * DESCRIPTION: utility function to get a channel object from its handle
     61  *
     62  * PARAMETERS :
     63  *   @cam_obj: ptr to a camera object
     64  *   @handler: channel handle
     65  *
     66  * RETURN     : ptr to a channel object.
     67  *              NULL if failed.
     68  *==========================================================================*/
     69 mm_channel_t * mm_camera_util_get_channel_by_handler(
     70                                     mm_camera_obj_t * cam_obj,
     71                                     uint32_t handler)
     72 {
     73     int i;
     74     mm_channel_t *ch_obj = NULL;
     75     for(i = 0; i < MM_CAMERA_CHANNEL_MAX; i++) {
     76         if (handler == cam_obj->ch[i].my_hdl) {
     77             ch_obj = &cam_obj->ch[i];
     78             break;
     79         }
     80     }
     81     return ch_obj;
     82 }
     83 
     84 /*===========================================================================
     85  * FUNCTION   : mm_camera_util_chip_is_a_family
     86  *
     87  * DESCRIPTION: utility function to check if the host is A family chip
     88  *
     89  * PARAMETERS :
     90  *
     91  * RETURN     : TRUE if A family.
     92  *              FALSE otherwise.
     93  *==========================================================================*/
     94 uint8_t mm_camera_util_chip_is_a_family(void)
     95 {
     96 #ifdef USE_A_FAMILY
     97     return TRUE;
     98 #else
     99     return FALSE;
    100 #endif
    101 }
    102 
    103 /*===========================================================================
    104  * FUNCTION   : mm_camera_dispatch_app_event
    105  *
    106  * DESCRIPTION: dispatch event to apps who regitster for event notify
    107  *
    108  * PARAMETERS :
    109  *   @cmd_cb: ptr to a struct storing event info
    110  *   @user_data: user data ptr (camera object)
    111  *
    112  * RETURN     : none
    113  *==========================================================================*/
    114 static void mm_camera_dispatch_app_event(mm_camera_cmdcb_t *cmd_cb,
    115                                          void* user_data)
    116 {
    117     mm_camera_cmd_thread_name("mm_cam_event");
    118     int i;
    119     mm_camera_event_t *event = &cmd_cb->u.evt;
    120     mm_camera_obj_t * my_obj = (mm_camera_obj_t *)user_data;
    121     if (NULL != my_obj) {
    122         pthread_mutex_lock(&my_obj->cb_lock);
    123         for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
    124             if(my_obj->evt.evt[i].evt_cb) {
    125                 my_obj->evt.evt[i].evt_cb(
    126                     my_obj->my_hdl,
    127                     event,
    128                     my_obj->evt.evt[i].user_data);
    129             }
    130         }
    131         pthread_mutex_unlock(&my_obj->cb_lock);
    132     }
    133 }
    134 
    135 /*===========================================================================
    136  * FUNCTION   : mm_camera_event_notify
    137  *
    138  * DESCRIPTION: callback to handle event notify from kernel. This call will
    139  *              dequeue event from kernel.
    140  *
    141  * PARAMETERS :
    142  *   @user_data: user data ptr (camera object)
    143  *
    144  * RETURN     : none
    145  *==========================================================================*/
    146 static void mm_camera_event_notify(void* user_data)
    147 {
    148     struct v4l2_event ev;
    149     struct msm_v4l2_event_data *msm_evt = NULL;
    150     int rc;
    151     mm_camera_event_t evt;
    152     memset(&evt, 0, sizeof(mm_camera_event_t));
    153 
    154     mm_camera_obj_t *my_obj = (mm_camera_obj_t*)user_data;
    155     if (NULL != my_obj) {
    156         /* read evt */
    157         memset(&ev, 0, sizeof(ev));
    158         rc = ioctl(my_obj->ctrl_fd, VIDIOC_DQEVENT, &ev);
    159 
    160         if (rc >= 0 && ev.id == MSM_CAMERA_MSM_NOTIFY) {
    161             msm_evt = (struct msm_v4l2_event_data *)ev.u.data;
    162             switch (msm_evt->command) {
    163             case CAM_EVENT_TYPE_DAEMON_PULL_REQ:
    164                 evt.server_event_type = CAM_EVENT_TYPE_DAEMON_PULL_REQ;
    165                 mm_camera_enqueue_evt(my_obj, &evt);
    166                 break;
    167             case CAM_EVENT_TYPE_MAP_UNMAP_DONE:
    168                 pthread_mutex_lock(&my_obj->evt_lock);
    169                 my_obj->evt_rcvd.server_event_type = msm_evt->command;
    170                 my_obj->evt_rcvd.status = msm_evt->status;
    171                 pthread_cond_signal(&my_obj->evt_cond);
    172                 pthread_mutex_unlock(&my_obj->evt_lock);
    173                 break;
    174             case MSM_CAMERA_PRIV_SHUTDOWN:
    175                 {
    176                     evt.server_event_type = CAM_EVENT_TYPE_DAEMON_DIED;
    177                     mm_camera_enqueue_evt(my_obj, &evt);
    178                 }
    179                 break;
    180             default:
    181                 break;
    182             }
    183         }
    184     }
    185 }
    186 
    187 /*===========================================================================
    188  * FUNCTION   : mm_camera_enqueue_evt
    189  *
    190  * DESCRIPTION: enqueue received event into event queue to be processed by
    191  *              event thread.
    192  *
    193  * PARAMETERS :
    194  *   @my_obj   : ptr to a camera object
    195  *   @event    : event to be queued
    196  *
    197  * RETURN     : int32_t type of status
    198  *              0  -- success
    199  *              -1 -- failure
    200  *==========================================================================*/
    201 int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj,
    202                               mm_camera_event_t *event)
    203 {
    204     int32_t rc = 0;
    205     mm_camera_cmdcb_t *node = NULL;
    206 
    207     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    208     if (NULL != node) {
    209         memset(node, 0, sizeof(mm_camera_cmdcb_t));
    210         node->cmd_type = MM_CAMERA_CMD_TYPE_EVT_CB;
    211         node->u.evt = *event;
    212 
    213         /* enqueue to evt cmd thread */
    214         cam_queue_enq(&(my_obj->evt_thread.cmd_queue), node);
    215         /* wake up evt cmd thread */
    216         cam_sem_post(&(my_obj->evt_thread.cmd_sem));
    217     } else {
    218         CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
    219         rc = -1;
    220     }
    221 
    222     return rc;
    223 }
    224 
    225 /*===========================================================================
    226  * FUNCTION   : mm_camera_open
    227  *
    228  * DESCRIPTION: open a camera
    229  *
    230  * PARAMETERS :
    231  *   @my_obj   : ptr to a camera object
    232  *
    233  * RETURN     : int32_t type of status
    234  *              0  -- success
    235  *              -1 -- failure
    236  *==========================================================================*/
    237 int32_t mm_camera_open(mm_camera_obj_t *my_obj)
    238 {
    239     char dev_name[MM_CAMERA_DEV_NAME_LEN];
    240     int32_t rc = 0;
    241     int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;
    242     uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP;
    243     unsigned int cam_idx = 0;
    244 
    245     CDBG("%s:  begin\n", __func__);
    246 
    247     if (NULL == my_obj) {
    248         goto on_error;
    249     }
    250     snprintf(dev_name, sizeof(dev_name), "/dev/%s",
    251              mm_camera_util_get_dev_name(my_obj->my_hdl));
    252     sscanf(dev_name, "/dev/video%u", &cam_idx);
    253     CDBG_HIGH("%s: dev name = %s, cam_idx = %d", __func__, dev_name, cam_idx);
    254 
    255     do{
    256         n_try--;
    257         errno = 0;
    258         my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);
    259         CDBG("%s:  ctrl_fd = %d, errno == %d", __func__, my_obj->ctrl_fd, errno);
    260         if((my_obj->ctrl_fd >= 0) || (errno != EIO && errno != ETIMEDOUT) || (n_try <= 0 )) {
    261             CDBG_HIGH("%s:  opened, break out while loop", __func__);
    262             break;
    263         }
    264         ALOGE("%s:Failed with %s error, retrying after %d milli-seconds",
    265              __func__, strerror(errno), sleep_msec);
    266         usleep(sleep_msec * 1000);
    267     }while (n_try > 0);
    268 
    269     if (my_obj->ctrl_fd < 0) {
    270         CDBG_ERROR("%s: cannot open control fd of '%s' (%s)\n",
    271                  __func__, dev_name, strerror(errno));
    272         rc = -1;
    273         goto on_error;
    274     }
    275 
    276     /* open domain socket*/
    277     n_try = MM_CAMERA_DEV_OPEN_TRIES;
    278     do {
    279         n_try--;
    280         my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP);
    281         CDBG("%s:  ds_fd = %d, errno = %d", __func__, my_obj->ds_fd, errno);
    282         if((my_obj->ds_fd >= 0) || (n_try <= 0 )) {
    283             CDBG("%s:  opened, break out while loop", __func__);
    284             break;
    285         }
    286         CDBG("%s:failed with I/O error retrying after %d milli-seconds",
    287              __func__, sleep_msec);
    288         usleep(sleep_msec * 1000);
    289     } while (n_try > 0);
    290 
    291     if (my_obj->ds_fd < 0) {
    292         CDBG_ERROR("%s: cannot open domain socket fd of '%s'(%s)\n",
    293                  __func__, dev_name, strerror(errno));
    294         rc = -1;
    295         goto on_error;
    296     }
    297     pthread_mutex_init(&my_obj->msg_lock, NULL);
    298 
    299     pthread_mutex_init(&my_obj->cb_lock, NULL);
    300     pthread_mutex_init(&my_obj->evt_lock, NULL);
    301     pthread_cond_init(&my_obj->evt_cond, NULL);
    302 
    303     CDBG("%s : Launch evt Thread in Cam Open",__func__);
    304     mm_camera_cmd_thread_launch(&my_obj->evt_thread,
    305                                 mm_camera_dispatch_app_event,
    306                                 (void *)my_obj);
    307 
    308     /* launch event poll thread
    309      * we will add evt fd into event poll thread upon user first register for evt */
    310     CDBG("%s : Launch evt Poll Thread in Cam Open", __func__);
    311     mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
    312                                  MM_CAMERA_POLL_TYPE_EVT);
    313     mm_camera_evt_sub(my_obj, TRUE);
    314 
    315     CDBG("%s:  end (rc = %d)\n", __func__, rc);
    316     /* we do not need to unlock cam_lock here before return
    317      * because for open, it's done within intf_lock */
    318     return rc;
    319 
    320 on_error:
    321     if (NULL == my_obj) {
    322         CDBG_ERROR("%s: Invalid camera object\n", __func__);
    323         rc = -1;
    324     } else {
    325         if (my_obj->ctrl_fd >= 0) {
    326             close(my_obj->ctrl_fd);
    327             my_obj->ctrl_fd = -1;
    328         }
    329         if (my_obj->ds_fd >= 0) {
    330             mm_camera_socket_close(my_obj->ds_fd);
    331             my_obj->ds_fd = -1;
    332         }
    333     }
    334 
    335     /* we do not need to unlock cam_lock here before return
    336      * because for open, it's done within intf_lock */
    337     return rc;
    338 }
    339 
    340 /*===========================================================================
    341  * FUNCTION   : mm_camera_close
    342  *
    343  * DESCRIPTION: enqueue received event into event queue to be processed by
    344  *              event thread.
    345  *
    346  * PARAMETERS :
    347  *   @my_obj   : ptr to a camera object
    348  *   @event    : event to be queued
    349  *
    350  * RETURN     : int32_t type of status
    351  *              0  -- success
    352  *              -1 -- failure
    353  *==========================================================================*/
    354 int32_t mm_camera_close(mm_camera_obj_t *my_obj)
    355 {
    356     CDBG("%s : unsubscribe evt", __func__);
    357     mm_camera_evt_sub(my_obj, FALSE);
    358 
    359     CDBG("%s : Close evt Poll Thread in Cam Close",__func__);
    360     mm_camera_poll_thread_release(&my_obj->evt_poll_thread);
    361 
    362     CDBG("%s : Close evt cmd Thread in Cam Close",__func__);
    363     mm_camera_cmd_thread_release(&my_obj->evt_thread);
    364 
    365     if(my_obj->ctrl_fd >= 0) {
    366         close(my_obj->ctrl_fd);
    367         my_obj->ctrl_fd = -1;
    368     }
    369     if(my_obj->ds_fd >= 0) {
    370         mm_camera_socket_close(my_obj->ds_fd);
    371         my_obj->ds_fd = -1;
    372     }
    373     pthread_mutex_destroy(&my_obj->msg_lock);
    374 
    375     pthread_mutex_destroy(&my_obj->cb_lock);
    376     pthread_mutex_destroy(&my_obj->evt_lock);
    377     pthread_cond_destroy(&my_obj->evt_cond);
    378 
    379     pthread_mutex_unlock(&my_obj->cam_lock);
    380     return 0;
    381 }
    382 
    383 /*===========================================================================
    384  * FUNCTION   : mm_camera_register_event_notify_internal
    385  *
    386  * DESCRIPTION: internal implementation for registering callback for event notify.
    387  *
    388  * PARAMETERS :
    389  *   @my_obj   : ptr to a camera object
    390  *   @evt_cb   : callback to be registered to handle event notify
    391  *   @user_data: user data ptr
    392  *
    393  * RETURN     : int32_t type of status
    394  *              0  -- success
    395  *              -1 -- failure
    396  *==========================================================================*/
    397 int32_t mm_camera_register_event_notify_internal(mm_camera_obj_t *my_obj,
    398                                                  mm_camera_event_notify_t evt_cb,
    399                                                  void * user_data)
    400 {
    401     int i;
    402     int rc = -1;
    403     mm_camera_evt_obj_t *evt_array = NULL;
    404 
    405     pthread_mutex_lock(&my_obj->cb_lock);
    406     evt_array = &my_obj->evt;
    407     if(evt_cb) {
    408         /* this is reg case */
    409         for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
    410             if(evt_array->evt[i].user_data == NULL) {
    411                 evt_array->evt[i].evt_cb = evt_cb;
    412                 evt_array->evt[i].user_data = user_data;
    413                 evt_array->reg_count++;
    414                 rc = 0;
    415                 break;
    416             }
    417         }
    418     } else {
    419         /* this is unreg case */
    420         for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
    421             if(evt_array->evt[i].user_data == user_data) {
    422                 evt_array->evt[i].evt_cb = NULL;
    423                 evt_array->evt[i].user_data = NULL;
    424                 evt_array->reg_count--;
    425                 rc = 0;
    426                 break;
    427             }
    428         }
    429     }
    430 
    431     pthread_mutex_unlock(&my_obj->cb_lock);
    432     return rc;
    433 }
    434 
    435 /*===========================================================================
    436  * FUNCTION   : mm_camera_register_event_notify
    437  *
    438  * DESCRIPTION: registering a callback for event notify.
    439  *
    440  * PARAMETERS :
    441  *   @my_obj   : ptr to a camera object
    442  *   @evt_cb   : callback to be registered to handle event notify
    443  *   @user_data: user data ptr
    444  *
    445  * RETURN     : int32_t type of status
    446  *              0  -- success
    447  *              -1 -- failure
    448  *==========================================================================*/
    449 int32_t mm_camera_register_event_notify(mm_camera_obj_t *my_obj,
    450                                         mm_camera_event_notify_t evt_cb,
    451                                         void * user_data)
    452 {
    453     int rc = -1;
    454     rc = mm_camera_register_event_notify_internal(my_obj,
    455                                                   evt_cb,
    456                                                   user_data);
    457     pthread_mutex_unlock(&my_obj->cam_lock);
    458     return rc;
    459 }
    460 
    461 /*===========================================================================
    462  * FUNCTION   : mm_camera_qbuf
    463  *
    464  * DESCRIPTION: enqueue buffer back to kernel
    465  *
    466  * PARAMETERS :
    467  *   @my_obj       : camera object
    468  *   @ch_id        : channel handle
    469  *   @buf          : buf ptr to be enqueued
    470  *
    471  * RETURN     : int32_t type of status
    472  *              0  -- success
    473  *              -1 -- failure
    474  *==========================================================================*/
    475 int32_t mm_camera_qbuf(mm_camera_obj_t *my_obj,
    476                        uint32_t ch_id,
    477                        mm_camera_buf_def_t *buf)
    478 {
    479     int rc = -1;
    480     mm_channel_t * ch_obj = NULL;
    481     ch_obj = mm_camera_util_get_channel_by_handler(my_obj, ch_id);
    482 
    483     pthread_mutex_unlock(&my_obj->cam_lock);
    484 
    485     /* we always assume qbuf will be done before channel/stream is fully stopped
    486      * because qbuf is done within dataCB context
    487      * in order to avoid deadlock, we are not locking ch_lock for qbuf */
    488     if (NULL != ch_obj) {
    489         rc = mm_channel_qbuf(ch_obj, buf);
    490     }
    491 
    492     return rc;
    493 }
    494 
    495 /*===========================================================================
    496  * FUNCTION   : mm_camera_query_capability
    497  *
    498  * DESCRIPTION: query camera capability
    499  *
    500  * PARAMETERS :
    501  *   @my_obj: camera object
    502  *
    503  * RETURN     : int32_t type of status
    504  *              0  -- success
    505  *              -1 -- failure
    506  *==========================================================================*/
    507 int32_t mm_camera_query_capability(mm_camera_obj_t *my_obj)
    508 {
    509     int32_t rc = 0;
    510     struct v4l2_capability cap;
    511 
    512     /* get camera capabilities */
    513     memset(&cap, 0, sizeof(cap));
    514     rc = ioctl(my_obj->ctrl_fd, VIDIOC_QUERYCAP, &cap);
    515     if (rc != 0) {
    516         CDBG_ERROR("%s: cannot get camera capabilities, rc = %d\n", __func__, rc);
    517     }
    518 
    519     pthread_mutex_unlock(&my_obj->cam_lock);
    520     return rc;
    521 
    522 }
    523 
    524 /*===========================================================================
    525  * FUNCTION   : mm_camera_set_parms
    526  *
    527  * DESCRIPTION: set parameters per camera
    528  *
    529  * PARAMETERS :
    530  *   @my_obj       : camera object
    531  *   @parms        : ptr to a param struct to be set to server
    532  *
    533  * RETURN     : int32_t type of status
    534  *              0  -- success
    535  *              -1 -- failure
    536  * NOTE       : Assume the parms struct buf is already mapped to server via
    537  *              domain socket. Corresponding fields of parameters to be set
    538  *              are already filled in by upper layer caller.
    539  *==========================================================================*/
    540 int32_t mm_camera_set_parms(mm_camera_obj_t *my_obj,
    541                             parm_buffer_t *parms)
    542 {
    543     int32_t rc = -1;
    544     int32_t value = 0;
    545     if (parms !=  NULL) {
    546         rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_PARM, &value);
    547     }
    548     pthread_mutex_unlock(&my_obj->cam_lock);
    549     return rc;
    550 }
    551 
    552 /*===========================================================================
    553  * FUNCTION   : mm_camera_get_parms
    554  *
    555  * DESCRIPTION: get parameters per camera
    556  *
    557  * PARAMETERS :
    558  *   @my_obj       : camera object
    559  *   @parms        : ptr to a param struct to be get from server
    560  *
    561  * RETURN     : int32_t type of status
    562  *              0  -- success
    563  *              -1 -- failure
    564  * NOTE       : Assume the parms struct buf is already mapped to server via
    565  *              domain socket. Parameters to be get from server are already
    566  *              filled in by upper layer caller. After this call, corresponding
    567  *              fields of requested parameters will be filled in by server with
    568  *              detailed information.
    569  *==========================================================================*/
    570 int32_t mm_camera_get_parms(mm_camera_obj_t *my_obj,
    571                             parm_buffer_t *parms)
    572 {
    573     int32_t rc = -1;
    574     int32_t value = 0;
    575     if (parms != NULL) {
    576         rc = mm_camera_util_g_ctrl(my_obj->ctrl_fd, CAM_PRIV_PARM, &value);
    577     }
    578     pthread_mutex_unlock(&my_obj->cam_lock);
    579     return rc;
    580 }
    581 
    582 /*===========================================================================
    583  * FUNCTION   : mm_camera_do_auto_focus
    584  *
    585  * DESCRIPTION: performing auto focus
    586  *
    587  * PARAMETERS :
    588  *   @camera_handle: camera handle
    589  *
    590  * RETURN     : int32_t type of status
    591  *              0  -- success
    592  *              -1 -- failure
    593  * NOTE       : if this call success, we will always assume there will
    594  *              be an auto_focus event following up.
    595  *==========================================================================*/
    596 int32_t mm_camera_do_auto_focus(mm_camera_obj_t *my_obj)
    597 {
    598     int32_t rc = -1;
    599     int32_t value = 0;
    600     rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_DO_AUTO_FOCUS, &value);
    601     pthread_mutex_unlock(&my_obj->cam_lock);
    602     return rc;
    603 }
    604 
    605 /*===========================================================================
    606  * FUNCTION   : mm_camera_cancel_auto_focus
    607  *
    608  * DESCRIPTION: cancel auto focus
    609  *
    610  * PARAMETERS :
    611  *   @camera_handle: camera handle
    612  *
    613  * RETURN     : int32_t type of status
    614  *              0  -- success
    615  *              -1 -- failure
    616  *==========================================================================*/
    617 int32_t mm_camera_cancel_auto_focus(mm_camera_obj_t *my_obj)
    618 {
    619     int32_t rc = -1;
    620     int32_t value = 0;
    621     rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_CANCEL_AUTO_FOCUS, &value);
    622     pthread_mutex_unlock(&my_obj->cam_lock);
    623     return rc;
    624 }
    625 
    626 /*===========================================================================
    627  * FUNCTION   : mm_camera_prepare_snapshot
    628  *
    629  * DESCRIPTION: prepare hardware for snapshot
    630  *
    631  * PARAMETERS :
    632  *   @my_obj       : camera object
    633  *   @do_af_flag   : flag indicating if AF is needed
    634  *
    635  * RETURN     : int32_t type of status
    636  *              0  -- success
    637  *              -1 -- failure
    638  *==========================================================================*/
    639 int32_t mm_camera_prepare_snapshot(mm_camera_obj_t *my_obj,
    640                                    int32_t do_af_flag)
    641 {
    642     int32_t rc = -1;
    643     int32_t value = do_af_flag;
    644     rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_PREPARE_SNAPSHOT, &value);
    645     pthread_mutex_unlock(&my_obj->cam_lock);
    646     return rc;
    647 }
    648 
    649 /*===========================================================================
    650  * FUNCTION   : mm_camera_start_zsl_snapshot
    651  *
    652  * DESCRIPTION: start zsl snapshot
    653  *
    654  * PARAMETERS :
    655  *   @my_obj       : camera object
    656  *
    657  * RETURN     : int32_t type of status
    658  *              0  -- success
    659  *              -1 -- failure
    660  *==========================================================================*/
    661 int32_t mm_camera_start_zsl_snapshot(mm_camera_obj_t *my_obj)
    662 {
    663     int32_t rc = -1;
    664     int32_t value = 0;
    665 
    666     rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
    667              CAM_PRIV_START_ZSL_SNAPSHOT, &value);
    668     return rc;
    669 }
    670 
    671 /*===========================================================================
    672  * FUNCTION   : mm_camera_stop_zsl_snapshot
    673  *
    674  * DESCRIPTION: stop zsl capture
    675  *
    676  * PARAMETERS :
    677  *   @my_obj       : camera object
    678  *
    679  * RETURN     : int32_t type of status
    680  *              0  -- success
    681  *              -1 -- failure
    682  *==========================================================================*/
    683 int32_t mm_camera_stop_zsl_snapshot(mm_camera_obj_t *my_obj)
    684 {
    685     int32_t rc = -1;
    686     int32_t value;
    687     rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
    688              CAM_PRIV_STOP_ZSL_SNAPSHOT, &value);
    689     return rc;
    690 }
    691 
    692 /*===========================================================================
    693  * FUNCTION   : mm_camera_add_channel
    694  *
    695  * DESCRIPTION: add a channel
    696  *
    697  * PARAMETERS :
    698  *   @my_obj       : camera object
    699  *   @attr         : bundle attribute of the channel if needed
    700  *   @channel_cb   : callback function for bundle data notify
    701  *   @userdata     : user data ptr
    702  *
    703  * RETURN     : uint32_t type of channel handle
    704  *              0  -- invalid channel handle, meaning the op failed
    705  *              >0 -- successfully added a channel with a valid handle
    706  * NOTE       : if no bundle data notify is needed, meaning each stream in the
    707  *              channel will have its own stream data notify callback, then
    708  *              attr, channel_cb, and userdata can be NULL. In this case,
    709  *              no matching logic will be performed in channel for the bundling.
    710  *==========================================================================*/
    711 uint32_t mm_camera_add_channel(mm_camera_obj_t *my_obj,
    712                                mm_camera_channel_attr_t *attr,
    713                                mm_camera_buf_notify_t channel_cb,
    714                                void *userdata)
    715 {
    716     mm_channel_t *ch_obj = NULL;
    717     uint8_t ch_idx = 0;
    718     uint32_t ch_hdl = 0;
    719 
    720     for(ch_idx = 0; ch_idx < MM_CAMERA_CHANNEL_MAX; ch_idx++) {
    721         if (MM_CHANNEL_STATE_NOTUSED == my_obj->ch[ch_idx].state) {
    722             ch_obj = &my_obj->ch[ch_idx];
    723             break;
    724         }
    725     }
    726 
    727     if (NULL != ch_obj) {
    728         /* initialize channel obj */
    729         memset(ch_obj, 0, sizeof(mm_channel_t));
    730         ch_hdl = mm_camera_util_generate_handler(ch_idx);
    731         ch_obj->my_hdl = ch_hdl;
    732         ch_obj->state = MM_CHANNEL_STATE_STOPPED;
    733         ch_obj->cam_obj = my_obj;
    734         pthread_mutex_init(&ch_obj->ch_lock, NULL);
    735         mm_channel_init(ch_obj, attr, channel_cb, userdata);
    736     }
    737 
    738     pthread_mutex_unlock(&my_obj->cam_lock);
    739 
    740     return ch_hdl;
    741 }
    742 
    743 /*===========================================================================
    744  * FUNCTION   : mm_camera_del_channel
    745  *
    746  * DESCRIPTION: delete a channel by its handle
    747  *
    748  * PARAMETERS :
    749  *   @my_obj       : camera object
    750  *   @ch_id        : channel handle
    751  *
    752  * RETURN     : int32_t type of status
    753  *              0  -- success
    754  *              -1 -- failure
    755  * NOTE       : all streams in the channel should be stopped already before
    756  *              this channel can be deleted.
    757  *==========================================================================*/
    758 int32_t mm_camera_del_channel(mm_camera_obj_t *my_obj,
    759                               uint32_t ch_id)
    760 {
    761     int32_t rc = -1;
    762     mm_channel_t * ch_obj =
    763         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
    764 
    765     if (NULL != ch_obj) {
    766         pthread_mutex_lock(&ch_obj->ch_lock);
    767         pthread_mutex_unlock(&my_obj->cam_lock);
    768 
    769         rc = mm_channel_fsm_fn(ch_obj,
    770                                MM_CHANNEL_EVT_DELETE,
    771                                NULL,
    772                                NULL);
    773 
    774         pthread_mutex_destroy(&ch_obj->ch_lock);
    775         memset(ch_obj, 0, sizeof(mm_channel_t));
    776     } else {
    777         pthread_mutex_unlock(&my_obj->cam_lock);
    778     }
    779     return rc;
    780 }
    781 
    782 /*===========================================================================
    783  * FUNCTION   : mm_camera_get_bundle_info
    784  *
    785  * DESCRIPTION: query bundle info of the channel
    786  *
    787  * PARAMETERS :
    788  *   @my_obj       : camera object
    789  *   @ch_id        : channel handle
    790  *   @bundle_info  : bundle info to be filled in
    791  *
    792  * RETURN     : int32_t type of status
    793  *              0  -- success
    794  *              -1 -- failure
    795  * NOTE       : all streams in the channel should be stopped already before
    796  *              this channel can be deleted.
    797  *==========================================================================*/
    798 int32_t mm_camera_get_bundle_info(mm_camera_obj_t *my_obj,
    799                                   uint32_t ch_id,
    800                                   cam_bundle_config_t *bundle_info)
    801 {
    802     int32_t rc = -1;
    803     mm_channel_t * ch_obj =
    804         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
    805 
    806     if (NULL != ch_obj) {
    807         pthread_mutex_lock(&ch_obj->ch_lock);
    808         pthread_mutex_unlock(&my_obj->cam_lock);
    809 
    810         rc = mm_channel_fsm_fn(ch_obj,
    811                                MM_CHANNEL_EVT_GET_BUNDLE_INFO,
    812                                (void *)bundle_info,
    813                                NULL);
    814     } else {
    815         pthread_mutex_unlock(&my_obj->cam_lock);
    816     }
    817     return rc;
    818 }
    819 
    820 /*===========================================================================
    821  * FUNCTION   : mm_camera_add_stream
    822  *
    823  * DESCRIPTION: add a stream into a channel
    824  *
    825  * PARAMETERS :
    826  *   @my_obj       : camera object
    827  *   @ch_id        : channel handle
    828  *
    829  * RETURN     : uint32_t type of stream handle
    830  *              0  -- invalid stream handle, meaning the op failed
    831  *              >0 -- successfully added a stream with a valid handle
    832  *==========================================================================*/
    833 uint32_t mm_camera_add_stream(mm_camera_obj_t *my_obj,
    834                               uint32_t ch_id)
    835 {
    836     uint32_t s_hdl = 0;
    837     mm_channel_t * ch_obj =
    838         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
    839 
    840     if (NULL != ch_obj) {
    841         pthread_mutex_lock(&ch_obj->ch_lock);
    842         pthread_mutex_unlock(&my_obj->cam_lock);
    843 
    844         mm_channel_fsm_fn(ch_obj,
    845                           MM_CHANNEL_EVT_ADD_STREAM,
    846                           NULL,
    847                           (void*)&s_hdl);
    848     } else {
    849         pthread_mutex_unlock(&my_obj->cam_lock);
    850     }
    851 
    852     return s_hdl;
    853 }
    854 
    855 /*===========================================================================
    856  * FUNCTION   : mm_camera_del_stream
    857  *
    858  * DESCRIPTION: delete a stream by its handle
    859  *
    860  * PARAMETERS :
    861  *   @my_obj       : camera object
    862  *   @ch_id        : channel handle
    863  *   @stream_id    : stream handle
    864  *
    865  * RETURN     : int32_t type of status
    866  *              0  -- success
    867  *              -1 -- failure
    868  * NOTE       : stream should be stopped already before it can be deleted.
    869  *==========================================================================*/
    870 int32_t mm_camera_del_stream(mm_camera_obj_t *my_obj,
    871                              uint32_t ch_id,
    872                              uint32_t stream_id)
    873 {
    874     int32_t rc = -1;
    875     mm_channel_t * ch_obj =
    876         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
    877 
    878     if (NULL != ch_obj) {
    879         pthread_mutex_lock(&ch_obj->ch_lock);
    880         pthread_mutex_unlock(&my_obj->cam_lock);
    881 
    882         rc = mm_channel_fsm_fn(ch_obj,
    883                                MM_CHANNEL_EVT_DEL_STREAM,
    884                                (void*)stream_id,
    885                                NULL);
    886     } else {
    887         pthread_mutex_unlock(&my_obj->cam_lock);
    888     }
    889 
    890     return rc;
    891 }
    892 
    893 /*===========================================================================
    894  * FUNCTION   : mm_camera_start_zsl_snapshot_ch
    895  *
    896  * DESCRIPTION: starts zsl snapshot for specific channel
    897  *
    898  * PARAMETERS :
    899  *   @my_obj       : camera object
    900  *   @ch_id        : channel handle
    901  *
    902  * RETURN     : int32_t type of status
    903  *              0  -- success
    904  *              -1 -- failure
    905  *==========================================================================*/
    906 int32_t mm_camera_start_zsl_snapshot_ch(mm_camera_obj_t *my_obj,
    907         uint32_t ch_id)
    908 {
    909     int32_t rc = -1;
    910     mm_channel_t * ch_obj =
    911         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
    912 
    913     if (NULL != ch_obj) {
    914         pthread_mutex_lock(&ch_obj->ch_lock);
    915         pthread_mutex_unlock(&my_obj->cam_lock);
    916 
    917         rc = mm_channel_fsm_fn(ch_obj,
    918                                MM_CHANNEL_EVT_START_ZSL_SNAPSHOT,
    919                                NULL,
    920                                NULL);
    921     } else {
    922         pthread_mutex_unlock(&my_obj->cam_lock);
    923     }
    924 
    925     return rc;
    926 }
    927 
    928 /*===========================================================================
    929  * FUNCTION   : mm_camera_stop_zsl_snapshot_ch
    930  *
    931  * DESCRIPTION: stops zsl snapshot for specific channel
    932  *
    933  * PARAMETERS :
    934  *   @my_obj       : camera object
    935  *   @ch_id        : channel handle
    936  *
    937  * RETURN     : int32_t type of status
    938  *              0  -- success
    939  *              -1 -- failure
    940  *==========================================================================*/
    941 int32_t mm_camera_stop_zsl_snapshot_ch(mm_camera_obj_t *my_obj,
    942         uint32_t ch_id)
    943 {
    944     int32_t rc = -1;
    945     mm_channel_t * ch_obj =
    946         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
    947 
    948     if (NULL != ch_obj) {
    949         pthread_mutex_lock(&ch_obj->ch_lock);
    950         pthread_mutex_unlock(&my_obj->cam_lock);
    951 
    952         rc = mm_channel_fsm_fn(ch_obj,
    953                                MM_CHANNEL_EVT_STOP_ZSL_SNAPSHOT,
    954                                NULL,
    955                                NULL);
    956     } else {
    957         pthread_mutex_unlock(&my_obj->cam_lock);
    958     }
    959 
    960     return rc;
    961 }
    962 
    963 /*===========================================================================
    964  * FUNCTION   : mm_camera_config_stream
    965  *
    966  * DESCRIPTION: configure a stream
    967  *
    968  * PARAMETERS :
    969  *   @my_obj       : camera object
    970  *   @ch_id        : channel handle
    971  *   @stream_id    : stream handle
    972  *   @config       : stream configuration
    973  *
    974  * RETURN     : int32_t type of status
    975  *              0  -- success
    976  *              -1 -- failure
    977  *==========================================================================*/
    978 int32_t mm_camera_config_stream(mm_camera_obj_t *my_obj,
    979                                 uint32_t ch_id,
    980                                 uint32_t stream_id,
    981                                 mm_camera_stream_config_t *config)
    982 {
    983     int32_t rc = -1;
    984     mm_channel_t * ch_obj =
    985         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
    986     mm_evt_paylod_config_stream_t payload;
    987 
    988     if (NULL != ch_obj) {
    989         pthread_mutex_lock(&ch_obj->ch_lock);
    990         pthread_mutex_unlock(&my_obj->cam_lock);
    991 
    992         memset(&payload, 0, sizeof(mm_evt_paylod_config_stream_t));
    993         payload.stream_id = stream_id;
    994         payload.config = config;
    995         rc = mm_channel_fsm_fn(ch_obj,
    996                                MM_CHANNEL_EVT_CONFIG_STREAM,
    997                                (void*)&payload,
    998                                NULL);
    999     } else {
   1000         pthread_mutex_unlock(&my_obj->cam_lock);
   1001     }
   1002 
   1003     return rc;
   1004 }
   1005 
   1006 /*===========================================================================
   1007  * FUNCTION   : mm_camera_start_channel
   1008  *
   1009  * DESCRIPTION: start a channel, which will start all streams in the channel
   1010  *
   1011  * PARAMETERS :
   1012  *   @my_obj       : camera object
   1013  *   @ch_id        : channel handle
   1014  *
   1015  * RETURN     : int32_t type of status
   1016  *              0  -- success
   1017  *              -1 -- failure
   1018  *==========================================================================*/
   1019 int32_t mm_camera_start_channel(mm_camera_obj_t *my_obj,
   1020                                 uint32_t ch_id)
   1021 {
   1022     int32_t rc = -1;
   1023     mm_channel_t * ch_obj =
   1024         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1025 
   1026     if (NULL != ch_obj) {
   1027         pthread_mutex_lock(&ch_obj->ch_lock);
   1028         pthread_mutex_unlock(&my_obj->cam_lock);
   1029 
   1030         rc = mm_channel_fsm_fn(ch_obj,
   1031                                MM_CHANNEL_EVT_START,
   1032                                NULL,
   1033                                NULL);
   1034     } else {
   1035         pthread_mutex_unlock(&my_obj->cam_lock);
   1036     }
   1037 
   1038     return rc;
   1039 }
   1040 
   1041 /*===========================================================================
   1042  * FUNCTION   : mm_camera_stop_channel
   1043  *
   1044  * DESCRIPTION: stop a channel, which will stop all streams in the channel
   1045  *
   1046  * PARAMETERS :
   1047  *   @my_obj       : camera object
   1048  *   @ch_id        : channel handle
   1049  *
   1050  * RETURN     : int32_t type of status
   1051  *              0  -- success
   1052  *              -1 -- failure
   1053  *==========================================================================*/
   1054 int32_t mm_camera_stop_channel(mm_camera_obj_t *my_obj,
   1055                                uint32_t ch_id)
   1056 {
   1057     int32_t rc = 0;
   1058     mm_channel_t * ch_obj =
   1059         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1060 
   1061     if (NULL != ch_obj) {
   1062         pthread_mutex_lock(&ch_obj->ch_lock);
   1063         pthread_mutex_unlock(&my_obj->cam_lock);
   1064 
   1065         rc = mm_channel_fsm_fn(ch_obj,
   1066                                MM_CHANNEL_EVT_STOP,
   1067                                NULL,
   1068                                NULL);
   1069     } else {
   1070         pthread_mutex_unlock(&my_obj->cam_lock);
   1071     }
   1072     return rc;
   1073 }
   1074 
   1075 /*===========================================================================
   1076  * FUNCTION   : mm_camera_request_super_buf
   1077  *
   1078  * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched
   1079  *              frames from superbuf queue
   1080  *
   1081  * PARAMETERS :
   1082  *   @my_obj       : camera object
   1083  *   @ch_id        : channel handle
   1084  *   @num_buf_requested : number of matched frames needed
   1085  *
   1086  * RETURN     : int32_t type of status
   1087  *              0  -- success
   1088  *              -1 -- failure
   1089  *==========================================================================*/
   1090 int32_t mm_camera_request_super_buf(mm_camera_obj_t *my_obj,
   1091                                     uint32_t ch_id,
   1092                                     uint32_t num_buf_requested,
   1093                                     uint32_t num_retro_buf_requested)
   1094 {
   1095     int32_t rc = -1;
   1096     mm_channel_t * ch_obj =
   1097         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1098 
   1099     if (NULL != ch_obj) {
   1100         pthread_mutex_lock(&ch_obj->ch_lock);
   1101         pthread_mutex_unlock(&my_obj->cam_lock);
   1102 
   1103         rc = mm_channel_fsm_fn(ch_obj,
   1104                                MM_CHANNEL_EVT_REQUEST_SUPER_BUF,
   1105                                (void*)num_buf_requested,
   1106                                (void*)num_retro_buf_requested);
   1107     } else {
   1108         pthread_mutex_unlock(&my_obj->cam_lock);
   1109     }
   1110 
   1111     return rc;
   1112 }
   1113 
   1114 /*===========================================================================
   1115  * FUNCTION   : mm_camera_cancel_super_buf_request
   1116  *
   1117  * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount
   1118  *              of matched frames from superbuf queue
   1119  *
   1120  * PARAMETERS :
   1121  *   @my_obj       : camera object
   1122  *   @ch_id        : channel handle
   1123  *
   1124  * RETURN     : int32_t type of status
   1125  *              0  -- success
   1126  *              -1 -- failure
   1127  *==========================================================================*/
   1128 int32_t mm_camera_cancel_super_buf_request(mm_camera_obj_t *my_obj, uint32_t ch_id)
   1129 {
   1130     int32_t rc = -1;
   1131     mm_channel_t * ch_obj =
   1132         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1133 
   1134     if (NULL != ch_obj) {
   1135         pthread_mutex_lock(&ch_obj->ch_lock);
   1136         pthread_mutex_unlock(&my_obj->cam_lock);
   1137 
   1138         rc = mm_channel_fsm_fn(ch_obj,
   1139                                MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF,
   1140                                NULL,
   1141                                NULL);
   1142     } else {
   1143         pthread_mutex_unlock(&my_obj->cam_lock);
   1144     }
   1145 
   1146     return rc;
   1147 }
   1148 
   1149 /*===========================================================================
   1150  * FUNCTION   : mm_camera_flush_super_buf_queue
   1151  *
   1152  * DESCRIPTION: flush out all frames in the superbuf queue
   1153  *
   1154  * PARAMETERS :
   1155  *   @my_obj       : camera object
   1156  *   @ch_id        : channel handle
   1157  *
   1158  * RETURN     : int32_t type of status
   1159  *              0  -- success
   1160  *              -1 -- failure
   1161  *==========================================================================*/
   1162 int32_t mm_camera_flush_super_buf_queue(mm_camera_obj_t *my_obj, uint32_t ch_id,
   1163                                                              uint32_t frame_idx)
   1164 {
   1165     int32_t rc = -1;
   1166     mm_channel_t * ch_obj =
   1167         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1168 
   1169     if (NULL != ch_obj) {
   1170         pthread_mutex_lock(&ch_obj->ch_lock);
   1171         pthread_mutex_unlock(&my_obj->cam_lock);
   1172 
   1173         rc = mm_channel_fsm_fn(ch_obj,
   1174                                MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE,
   1175                                (void *)frame_idx,
   1176                                NULL);
   1177     } else {
   1178         pthread_mutex_unlock(&my_obj->cam_lock);
   1179     }
   1180 
   1181     return rc;
   1182 }
   1183 
   1184 /*===========================================================================
   1185  * FUNCTION   : mm_camera_config_channel_notify
   1186  *
   1187  * DESCRIPTION: configures the channel notification mode
   1188  *
   1189  * PARAMETERS :
   1190  *   @my_obj       : camera object
   1191  *   @ch_id        : channel handle
   1192  *   @notify_mode  : notification mode
   1193  *
   1194  * RETURN     : int32_t type of status
   1195  *              0  -- success
   1196  *              -1 -- failure
   1197  *==========================================================================*/
   1198 int32_t mm_camera_config_channel_notify(mm_camera_obj_t *my_obj,
   1199                                         uint32_t ch_id,
   1200                                         mm_camera_super_buf_notify_mode_t notify_mode)
   1201 {
   1202     int32_t rc = -1;
   1203     mm_channel_t * ch_obj =
   1204         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1205 
   1206     if (NULL != ch_obj) {
   1207         pthread_mutex_lock(&ch_obj->ch_lock);
   1208         pthread_mutex_unlock(&my_obj->cam_lock);
   1209 
   1210         rc = mm_channel_fsm_fn(ch_obj,
   1211                                MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE,
   1212                                (void *)notify_mode,
   1213                                NULL);
   1214     } else {
   1215         pthread_mutex_unlock(&my_obj->cam_lock);
   1216     }
   1217 
   1218     return rc;
   1219 }
   1220 
   1221 /*===========================================================================
   1222  * FUNCTION   : mm_camera_set_stream_parms
   1223  *
   1224  * DESCRIPTION: set parameters per stream
   1225  *
   1226  * PARAMETERS :
   1227  *   @my_obj       : camera object
   1228  *   @ch_id        : channel handle
   1229  *   @s_id         : stream handle
   1230  *   @parms        : ptr to a param struct to be set to server
   1231  *
   1232  * RETURN     : int32_t type of status
   1233  *              0  -- success
   1234  *              -1 -- failure
   1235  * NOTE       : Assume the parms struct buf is already mapped to server via
   1236  *              domain socket. Corresponding fields of parameters to be set
   1237  *              are already filled in by upper layer caller.
   1238  *==========================================================================*/
   1239 int32_t mm_camera_set_stream_parms(mm_camera_obj_t *my_obj,
   1240                                    uint32_t ch_id,
   1241                                    uint32_t s_id,
   1242                                    cam_stream_parm_buffer_t *parms)
   1243 {
   1244     int32_t rc = -1;
   1245     mm_evt_paylod_set_get_stream_parms_t payload;
   1246     mm_channel_t * ch_obj =
   1247         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1248 
   1249     if (NULL != ch_obj) {
   1250         pthread_mutex_lock(&ch_obj->ch_lock);
   1251         pthread_mutex_unlock(&my_obj->cam_lock);
   1252 
   1253         memset(&payload, 0, sizeof(payload));
   1254         payload.stream_id = s_id;
   1255         payload.parms = parms;
   1256 
   1257         rc = mm_channel_fsm_fn(ch_obj,
   1258                                MM_CHANNEL_EVT_SET_STREAM_PARM,
   1259                                (void *)&payload,
   1260                                NULL);
   1261     } else {
   1262         pthread_mutex_unlock(&my_obj->cam_lock);
   1263     }
   1264 
   1265     return rc;
   1266 }
   1267 
   1268 /*===========================================================================
   1269  * FUNCTION   : mm_camera_get_stream_parms
   1270  *
   1271  * DESCRIPTION: get parameters per stream
   1272  *
   1273  * PARAMETERS :
   1274  *   @my_obj       : camera object
   1275  *   @ch_id        : channel handle
   1276  *   @s_id         : stream handle
   1277  *   @parms        : ptr to a param struct to be get from server
   1278  *
   1279  * RETURN     : int32_t type of status
   1280  *              0  -- success
   1281  *              -1 -- failure
   1282  * NOTE       : Assume the parms struct buf is already mapped to server via
   1283  *              domain socket. Parameters to be get from server are already
   1284  *              filled in by upper layer caller. After this call, corresponding
   1285  *              fields of requested parameters will be filled in by server with
   1286  *              detailed information.
   1287  *==========================================================================*/
   1288 int32_t mm_camera_get_stream_parms(mm_camera_obj_t *my_obj,
   1289                                    uint32_t ch_id,
   1290                                    uint32_t s_id,
   1291                                    cam_stream_parm_buffer_t *parms)
   1292 {
   1293     int32_t rc = -1;
   1294     mm_evt_paylod_set_get_stream_parms_t payload;
   1295     mm_channel_t * ch_obj =
   1296         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1297 
   1298     if (NULL != ch_obj) {
   1299         pthread_mutex_lock(&ch_obj->ch_lock);
   1300         pthread_mutex_unlock(&my_obj->cam_lock);
   1301 
   1302         memset(&payload, 0, sizeof(payload));
   1303         payload.stream_id = s_id;
   1304         payload.parms = parms;
   1305 
   1306         rc = mm_channel_fsm_fn(ch_obj,
   1307                                MM_CHANNEL_EVT_GET_STREAM_PARM,
   1308                                (void *)&payload,
   1309                                NULL);
   1310     } else {
   1311         pthread_mutex_unlock(&my_obj->cam_lock);
   1312     }
   1313 
   1314     return rc;
   1315 }
   1316 
   1317 /*===========================================================================
   1318  * FUNCTION   : mm_camera_do_stream_action
   1319  *
   1320  * DESCRIPTION: request server to perform stream based action. Maybe removed later
   1321  *              if the functionality is included in mm_camera_set_parms
   1322  *
   1323  * PARAMETERS :
   1324  *   @my_obj       : camera object
   1325  *   @ch_id        : channel handle
   1326  *   @s_id         : stream handle
   1327  *   @actions      : ptr to an action struct buf to be performed by server
   1328  *
   1329  * RETURN     : int32_t type of status
   1330  *              0  -- success
   1331  *              -1 -- failure
   1332  * NOTE       : Assume the action struct buf is already mapped to server via
   1333  *              domain socket. Actions to be performed by server are already
   1334  *              filled in by upper layer caller.
   1335  *==========================================================================*/
   1336 int32_t mm_camera_do_stream_action(mm_camera_obj_t *my_obj,
   1337                                    uint32_t ch_id,
   1338                                    uint32_t stream_id,
   1339                                    void *actions)
   1340 {
   1341     int32_t rc = -1;
   1342     mm_evt_paylod_do_stream_action_t payload;
   1343     mm_channel_t * ch_obj =
   1344         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1345 
   1346     if (NULL != ch_obj) {
   1347         pthread_mutex_lock(&ch_obj->ch_lock);
   1348         pthread_mutex_unlock(&my_obj->cam_lock);
   1349 
   1350         memset(&payload, 0, sizeof(payload));
   1351         payload.stream_id = stream_id;
   1352         payload.actions = actions;
   1353 
   1354         rc = mm_channel_fsm_fn(ch_obj,
   1355                                MM_CHANNEL_EVT_DO_STREAM_ACTION,
   1356                                (void*)&payload,
   1357                                NULL);
   1358     } else {
   1359         pthread_mutex_unlock(&my_obj->cam_lock);
   1360     }
   1361 
   1362     return rc;
   1363 }
   1364 
   1365 /*===========================================================================
   1366  * FUNCTION   : mm_camera_map_stream_buf
   1367  *
   1368  * DESCRIPTION: mapping stream buffer via domain socket to server
   1369  *
   1370  * PARAMETERS :
   1371  *   @my_obj       : camera object
   1372  *   @ch_id        : channel handle
   1373  *   @s_id         : stream handle
   1374  *   @buf_type     : type of buffer to be mapped. could be following values:
   1375  *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
   1376  *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
   1377  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
   1378  *   @buf_idx      : index of buffer within the stream buffers, only valid if
   1379  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
   1380  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
   1381  *   @plane_idx    : plane index. If all planes share the same fd,
   1382  *                   plane_idx = -1; otherwise, plean_idx is the
   1383  *                   index to plane (0..num_of_planes)
   1384  *   @fd           : file descriptor of the buffer
   1385  *   @size         : size of the buffer
   1386  *
   1387  * RETURN     : int32_t type of status
   1388  *              0  -- success
   1389  *              -1 -- failure
   1390  *==========================================================================*/
   1391 int32_t mm_camera_map_stream_buf(mm_camera_obj_t *my_obj,
   1392                                  uint32_t ch_id,
   1393                                  uint32_t stream_id,
   1394                                  uint8_t buf_type,
   1395                                  uint32_t buf_idx,
   1396                                  int32_t plane_idx,
   1397                                  int fd,
   1398                                  uint32_t size)
   1399 {
   1400     int32_t rc = -1;
   1401     mm_evt_paylod_map_stream_buf_t payload;
   1402     mm_channel_t * ch_obj =
   1403         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1404 
   1405     if (NULL != ch_obj) {
   1406         pthread_mutex_lock(&ch_obj->ch_lock);
   1407         pthread_mutex_unlock(&my_obj->cam_lock);
   1408 
   1409         memset(&payload, 0, sizeof(payload));
   1410         payload.stream_id = stream_id;
   1411         payload.buf_type = buf_type;
   1412         payload.buf_idx = buf_idx;
   1413         payload.plane_idx = plane_idx;
   1414         payload.fd = fd;
   1415         payload.size = size;
   1416         rc = mm_channel_fsm_fn(ch_obj,
   1417                                MM_CHANNEL_EVT_MAP_STREAM_BUF,
   1418                                (void*)&payload,
   1419                                NULL);
   1420     } else {
   1421         pthread_mutex_unlock(&my_obj->cam_lock);
   1422     }
   1423 
   1424     return rc;
   1425 }
   1426 
   1427 /*===========================================================================
   1428  * FUNCTION   : mm_camera_unmap_stream_buf
   1429  *
   1430  * DESCRIPTION: unmapping stream buffer via domain socket to server
   1431  *
   1432  * PARAMETERS :
   1433  *   @my_obj       : camera object
   1434  *   @ch_id        : channel handle
   1435  *   @s_id         : stream handle
   1436  *   @buf_type     : type of buffer to be mapped. could be following values:
   1437  *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
   1438  *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
   1439  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
   1440  *   @buf_idx      : index of buffer within the stream buffers, only valid if
   1441  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
   1442  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
   1443  *   @plane_idx    : plane index. If all planes share the same fd,
   1444  *                   plane_idx = -1; otherwise, plean_idx is the
   1445  *                   index to plane (0..num_of_planes)
   1446  *
   1447  * RETURN     : int32_t type of status
   1448  *              0  -- success
   1449  *              -1 -- failure
   1450  *==========================================================================*/
   1451 int32_t mm_camera_unmap_stream_buf(mm_camera_obj_t *my_obj,
   1452                                    uint32_t ch_id,
   1453                                    uint32_t stream_id,
   1454                                    uint8_t buf_type,
   1455                                    uint32_t buf_idx,
   1456                                    int32_t plane_idx)
   1457 {
   1458     int32_t rc = -1;
   1459     mm_evt_paylod_unmap_stream_buf_t payload;
   1460     mm_channel_t * ch_obj =
   1461         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1462 
   1463     if (NULL != ch_obj) {
   1464         pthread_mutex_lock(&ch_obj->ch_lock);
   1465         pthread_mutex_unlock(&my_obj->cam_lock);
   1466 
   1467         memset(&payload, 0, sizeof(payload));
   1468         payload.stream_id = stream_id;
   1469         payload.buf_type = buf_type;
   1470         payload.buf_idx = buf_idx;
   1471         payload.plane_idx = plane_idx;
   1472         rc = mm_channel_fsm_fn(ch_obj,
   1473                                MM_CHANNEL_EVT_UNMAP_STREAM_BUF,
   1474                                (void*)&payload,
   1475                                NULL);
   1476     } else {
   1477         pthread_mutex_unlock(&my_obj->cam_lock);
   1478     }
   1479 
   1480     return rc;
   1481 }
   1482 
   1483 /*===========================================================================
   1484  * FUNCTION   : mm_camera_evt_sub
   1485  *
   1486  * DESCRIPTION: subscribe/unsubscribe event notify from kernel
   1487  *
   1488  * PARAMETERS :
   1489  *   @my_obj       : camera object
   1490  *   @reg_flag     : 1 -- subscribe ; 0 -- unsubscribe
   1491  *
   1492  * RETURN     : int32_t type of status
   1493  *              0  -- success
   1494  *              -1 -- failure
   1495  *==========================================================================*/
   1496 int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj,
   1497                           uint8_t reg_flag)
   1498 {
   1499     int32_t rc = 0;
   1500     struct v4l2_event_subscription sub;
   1501 
   1502     memset(&sub, 0, sizeof(sub));
   1503     sub.type = MSM_CAMERA_V4L2_EVENT_TYPE;
   1504     sub.id = MSM_CAMERA_MSM_NOTIFY;
   1505     if(FALSE == reg_flag) {
   1506         /* unsubscribe */
   1507         rc = ioctl(my_obj->ctrl_fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
   1508         if (rc < 0) {
   1509             CDBG_ERROR("%s: unsubscribe event rc = %d", __func__, rc);
   1510             return rc;
   1511         }
   1512         /* remove evt fd from the polling thraed when unreg the last event */
   1513         rc = mm_camera_poll_thread_del_poll_fd(&my_obj->evt_poll_thread,
   1514                                                my_obj->my_hdl,
   1515                                                mm_camera_sync_call);
   1516     } else {
   1517         rc = ioctl(my_obj->ctrl_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
   1518         if (rc < 0) {
   1519             CDBG_ERROR("%s: subscribe event rc = %d", __func__, rc);
   1520             return rc;
   1521         }
   1522         /* add evt fd to polling thread when subscribe the first event */
   1523         rc = mm_camera_poll_thread_add_poll_fd(&my_obj->evt_poll_thread,
   1524                                                my_obj->my_hdl,
   1525                                                my_obj->ctrl_fd,
   1526                                                mm_camera_event_notify,
   1527                                                (void*)my_obj,
   1528                                                mm_camera_sync_call);
   1529     }
   1530     return rc;
   1531 }
   1532 
   1533 /*===========================================================================
   1534  * FUNCTION   : mm_camera_util_wait_for_event
   1535  *
   1536  * DESCRIPTION: utility function to wait for certain events
   1537  *
   1538  * PARAMETERS :
   1539  *   @my_obj       : camera object
   1540  *   @evt_mask     : mask for events to be waited. Any of event in the mask would
   1541  *                   trigger the wait to end
   1542  *   @status       : status of the event
   1543  *
   1544  * RETURN     : none
   1545  *==========================================================================*/
   1546 void mm_camera_util_wait_for_event(mm_camera_obj_t *my_obj,
   1547                                    uint32_t evt_mask,
   1548                                    int32_t *status)
   1549 {
   1550     pthread_mutex_lock(&my_obj->evt_lock);
   1551     while (!(my_obj->evt_rcvd.server_event_type & evt_mask)) {
   1552         pthread_cond_wait(&my_obj->evt_cond, &my_obj->evt_lock);
   1553     }
   1554     *status = my_obj->evt_rcvd.status;
   1555     /* reset local storage for recieved event for next event */
   1556     memset(&my_obj->evt_rcvd, 0, sizeof(mm_camera_event_t));
   1557     pthread_mutex_unlock(&my_obj->evt_lock);
   1558 }
   1559 
   1560 /*===========================================================================
   1561  * FUNCTION   : mm_camera_util_sendmsg
   1562  *
   1563  * DESCRIPTION: utility function to send msg via domain socket
   1564  *
   1565  * PARAMETERS :
   1566  *   @my_obj       : camera object
   1567  *   @msg          : message to be sent
   1568  *   @buf_size     : size of the message to be sent
   1569  *   @sendfd       : >0 if any file descriptor need to be passed across process
   1570  *
   1571  * RETURN     : int32_t type of status
   1572  *              0  -- success
   1573  *              -1 -- failure
   1574  *==========================================================================*/
   1575 int32_t mm_camera_util_sendmsg(mm_camera_obj_t *my_obj,
   1576                                void *msg,
   1577                                uint32_t buf_size,
   1578                                int sendfd)
   1579 {
   1580     int32_t rc = -1;
   1581     int32_t status;
   1582 
   1583     /* need to lock msg_lock, since sendmsg until reposonse back is deemed as one operation*/
   1584     pthread_mutex_lock(&my_obj->msg_lock);
   1585     if(mm_camera_socket_sendmsg(my_obj->ds_fd, msg, buf_size, sendfd) > 0) {
   1586         /* wait for event that mapping/unmapping is done */
   1587         mm_camera_util_wait_for_event(my_obj, CAM_EVENT_TYPE_MAP_UNMAP_DONE, &status);
   1588         if (MSM_CAMERA_STATUS_SUCCESS == status) {
   1589             rc = 0;
   1590         }
   1591     }
   1592     pthread_mutex_unlock(&my_obj->msg_lock);
   1593     return rc;
   1594 }
   1595 
   1596 /*===========================================================================
   1597  * FUNCTION   : mm_camera_map_buf
   1598  *
   1599  * DESCRIPTION: mapping camera buffer via domain socket to server
   1600  *
   1601  * PARAMETERS :
   1602  *   @my_obj       : camera object
   1603  *   @buf_type     : type of buffer to be mapped. could be following values:
   1604  *                   CAM_MAPPING_BUF_TYPE_CAPABILITY
   1605  *                   CAM_MAPPING_BUF_TYPE_SETPARM_BUF
   1606  *                   CAM_MAPPING_BUF_TYPE_GETPARM_BUF
   1607  *   @fd           : file descriptor of the buffer
   1608  *   @size         : size of the buffer
   1609  *
   1610  * RETURN     : int32_t type of status
   1611  *              0  -- success
   1612  *              -1 -- failure
   1613  *==========================================================================*/
   1614 int32_t mm_camera_map_buf(mm_camera_obj_t *my_obj,
   1615                           uint8_t buf_type,
   1616                           int fd,
   1617                           uint32_t size)
   1618 {
   1619     int32_t rc = 0;
   1620     cam_sock_packet_t packet;
   1621     memset(&packet, 0, sizeof(cam_sock_packet_t));
   1622     packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
   1623     packet.payload.buf_map.type = buf_type;
   1624     packet.payload.buf_map.fd = fd;
   1625     packet.payload.buf_map.size = size;
   1626     rc = mm_camera_util_sendmsg(my_obj,
   1627                                 &packet,
   1628                                 sizeof(cam_sock_packet_t),
   1629                                 fd);
   1630     pthread_mutex_unlock(&my_obj->cam_lock);
   1631     return rc;
   1632 }
   1633 
   1634 /*===========================================================================
   1635  * FUNCTION   : mm_camera_unmap_buf
   1636  *
   1637  * DESCRIPTION: unmapping camera buffer via domain socket to server
   1638  *
   1639  * PARAMETERS :
   1640  *   @my_obj       : camera object
   1641  *   @buf_type     : type of buffer to be mapped. could be following values:
   1642  *                   CAM_MAPPING_BUF_TYPE_CAPABILITY
   1643  *                   CAM_MAPPING_BUF_TYPE_SETPARM_BUF
   1644  *                   CAM_MAPPING_BUF_TYPE_GETPARM_BUF
   1645  *
   1646  * RETURN     : int32_t type of status
   1647  *              0  -- success
   1648  *              -1 -- failure
   1649  *==========================================================================*/
   1650 int32_t mm_camera_unmap_buf(mm_camera_obj_t *my_obj,
   1651                             uint8_t buf_type)
   1652 {
   1653     int32_t rc = 0;
   1654     cam_sock_packet_t packet;
   1655     memset(&packet, 0, sizeof(cam_sock_packet_t));
   1656     packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING;
   1657     packet.payload.buf_unmap.type = buf_type;
   1658     rc = mm_camera_util_sendmsg(my_obj,
   1659                                 &packet,
   1660                                 sizeof(cam_sock_packet_t),
   1661                                 0);
   1662     pthread_mutex_unlock(&my_obj->cam_lock);
   1663     return rc;
   1664 }
   1665 
   1666 /*===========================================================================
   1667  * FUNCTION   : mm_camera_util_s_ctrl
   1668  *
   1669  * DESCRIPTION: utility function to send v4l2 ioctl for s_ctrl
   1670  *
   1671  * PARAMETERS :
   1672  *   @fd      : file descritpor for sending ioctl
   1673  *   @id      : control id
   1674  *   @value   : value of the ioctl to be sent
   1675  *
   1676  * RETURN     : int32_t type of status
   1677  *              0  -- success
   1678  *              -1 -- failure
   1679  *==========================================================================*/
   1680 int32_t mm_camera_util_s_ctrl(int32_t fd,  uint32_t id, int32_t *value)
   1681 {
   1682     int rc = 0;
   1683     struct v4l2_control control;
   1684 
   1685     memset(&control, 0, sizeof(control));
   1686     control.id = id;
   1687     if (value != NULL) {
   1688         control.value = *value;
   1689     }
   1690     rc = ioctl(fd, VIDIOC_S_CTRL, &control);
   1691 
   1692     CDBG("%s: fd=%d, S_CTRL, id=0x%x, value = 0x%x, rc = %d\n",
   1693          __func__, fd, id, (uint32_t)value, rc);
   1694     if (value != NULL) {
   1695         *value = control.value;
   1696     }
   1697     return (rc >= 0)? 0 : -1;
   1698 }
   1699 
   1700 /*===========================================================================
   1701  * FUNCTION   : mm_camera_util_g_ctrl
   1702  *
   1703  * DESCRIPTION: utility function to send v4l2 ioctl for g_ctrl
   1704  *
   1705  * PARAMETERS :
   1706  *   @fd      : file descritpor for sending ioctl
   1707  *   @id      : control id
   1708  *   @value   : value of the ioctl to be sent
   1709  *
   1710  * RETURN     : int32_t type of status
   1711  *              0  -- success
   1712  *              -1 -- failure
   1713  *==========================================================================*/
   1714 int32_t mm_camera_util_g_ctrl( int32_t fd, uint32_t id, int32_t *value)
   1715 {
   1716     int rc = 0;
   1717     struct v4l2_control control;
   1718 
   1719     memset(&control, 0, sizeof(control));
   1720     control.id = id;
   1721     if (value != NULL) {
   1722         control.value = *value;
   1723     }
   1724     rc = ioctl(fd, VIDIOC_G_CTRL, &control);
   1725     CDBG("%s: fd=%d, G_CTRL, id=0x%x, rc = %d\n", __func__, fd, id, rc);
   1726     if (value != NULL) {
   1727         *value = control.value;
   1728     }
   1729     return (rc >= 0)? 0 : -1;
   1730 }
   1731 
   1732 /*===========================================================================
   1733  * FUNCTION   : mm_camera_channel_advanced_capture
   1734  *
   1735  * DESCRIPTION: sets the channel advanced capture
   1736  *
   1737  * PARAMETERS :
   1738  *   @my_obj       : camera object
   1739  *   @advanced_capture_type : advanced capture type.
   1740  *   @ch_id        : channel handle
   1741  *   @start_flag  : flag to indicate start/stop
   1742  *
   1743  * RETURN     : int32_t type of status
   1744  *              0  -- success
   1745  *              -1 -- failure
   1746  *==========================================================================*/
   1747 int32_t mm_camera_channel_advanced_capture(mm_camera_obj_t *my_obj,
   1748                                         mm_camera_advanced_capture_t advanced_capture_type,
   1749                                         uint32_t ch_id,
   1750                                         int32_t start_flag)
   1751 {
   1752     CDBG("%s: E",__func__);
   1753     int32_t rc = -1;
   1754     mm_channel_t * ch_obj =
   1755         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
   1756 
   1757     if (NULL != ch_obj) {
   1758         pthread_mutex_lock(&ch_obj->ch_lock);
   1759         pthread_mutex_unlock(&my_obj->cam_lock);
   1760         switch (advanced_capture_type) {
   1761             case MM_CAMERA_AF_BRACKETING:
   1762                 rc = mm_channel_fsm_fn(ch_obj,
   1763                                        MM_CHANNEL_EVT_AF_BRACKETING,
   1764                                        (void *)start_flag,
   1765                                        NULL);
   1766                 break;
   1767             case MM_CAMERA_AE_BRACKETING:
   1768                 rc = mm_channel_fsm_fn(ch_obj,
   1769                                        MM_CHANNEL_EVT_AE_BRACKETING,
   1770                                        (void *)start_flag,
   1771                                        NULL);
   1772                 break;
   1773             case MM_CAMERA_FLASH_BRACKETING:
   1774                 rc = mm_channel_fsm_fn(ch_obj,
   1775                                        MM_CHANNEL_EVT_FLASH_BRACKETING,
   1776                                        (void *)start_flag,
   1777                                        NULL);
   1778                 break;
   1779             case MM_CAMERA_ZOOM_1X:
   1780                 rc = mm_channel_fsm_fn(ch_obj,
   1781                                        MM_CHANNEL_EVT_ZOOM_1X,
   1782                                        (void *)start_flag,
   1783                                        NULL);
   1784                 break;
   1785             default:
   1786                 break;
   1787         }
   1788 
   1789     } else {
   1790         pthread_mutex_unlock(&my_obj->cam_lock);
   1791     }
   1792 
   1793     CDBG("%s: X",__func__);
   1794     return rc;
   1795 }
   1796