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