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