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