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