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 #include <cam_semaphore.h>
     38 
     39 #include "mm_camera_dbg.h"
     40 #include "mm_camera_interface.h"
     41 #include "mm_camera.h"
     42 
     43 extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler);
     44 extern mm_channel_t * mm_camera_util_get_channel_by_handler(mm_camera_obj_t * cam_obj,
     45                                                             uint32_t handler);
     46 
     47 /* internal function declare goes here */
     48 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
     49                         mm_camera_buf_def_t *buf);
     50 int32_t mm_channel_init(mm_channel_t *my_obj,
     51                         mm_camera_channel_attr_t *attr,
     52                         mm_camera_buf_notify_t channel_cb,
     53                         void *userdata);
     54 void mm_channel_release(mm_channel_t *my_obj);
     55 uint32_t mm_channel_add_stream(mm_channel_t *my_obj);
     56 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
     57                                    uint32_t stream_id);
     58 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
     59                                  uint32_t stream_id,
     60                                  mm_camera_stream_config_t *config);
     61 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj,
     62                                    cam_bundle_config_t *bundle_info);
     63 int32_t mm_channel_start(mm_channel_t *my_obj);
     64 int32_t mm_channel_stop(mm_channel_t *my_obj);
     65 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj,
     66                 uint32_t num_buf_requested, uint32_t num_reto_buf_requested);
     67 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj);
     68 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj,
     69                                          uint32_t frame_idx);
     70 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj,
     71                                       mm_camera_super_buf_notify_mode_t notify_mode);
     72 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj);
     73 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj);
     74 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj, mm_channel_queue_t * queue);
     75 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
     76                                    mm_evt_paylod_set_get_stream_parms_t *payload);
     77 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
     78                                    mm_evt_paylod_set_get_stream_parms_t *payload);
     79 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
     80                                     mm_evt_paylod_do_stream_action_t *payload);
     81 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
     82                                   mm_evt_paylod_map_stream_buf_t *payload);
     83 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
     84                                     mm_evt_paylod_unmap_stream_buf_t *payload);
     85 
     86 /* state machine function declare */
     87 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
     88                           mm_channel_evt_type_t evt,
     89                           void * in_val,
     90                           void * out_val);
     91 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
     92                           mm_channel_evt_type_t evt,
     93                           void * in_val,
     94                           void * out_val);
     95 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
     96                           mm_channel_evt_type_t evt,
     97                           void * in_val,
     98                           void * out_val);
     99 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
    100                           mm_channel_evt_type_t evt,
    101                           void * in_val,
    102                           void * out_val);
    103 
    104 /* channel super queue functions */
    105 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue);
    106 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue);
    107 int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj,
    108                                              mm_channel_queue_t * queue,
    109                                              mm_camera_buf_info_t *buf);
    110 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue);
    111 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t *my_obj,
    112                                              mm_channel_queue_t *queue);
    113 int32_t mm_channel_superbuf_skip(mm_channel_t *my_obj,
    114                                  mm_channel_queue_t *queue);
    115 
    116 static int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj,
    117                                            mm_camera_generic_cmd_t *p_gen_cmd);
    118 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj,
    119                                           mm_channel_queue_t * queue);
    120 /*===========================================================================
    121  * FUNCTION   : mm_channel_util_get_stream_by_handler
    122  *
    123  * DESCRIPTION: utility function to get a stream object from its handle
    124  *
    125  * PARAMETERS :
    126  *   @cam_obj: ptr to a channel object
    127  *   @handler: stream handle
    128  *
    129  * RETURN     : ptr to a stream object.
    130  *              NULL if failed.
    131  *==========================================================================*/
    132 mm_stream_t * mm_channel_util_get_stream_by_handler(
    133                                     mm_channel_t * ch_obj,
    134                                     uint32_t handler)
    135 {
    136     int i;
    137     mm_stream_t *s_obj = NULL;
    138     for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
    139         if ((MM_STREAM_STATE_NOTUSED != ch_obj->streams[i].state) &&
    140             (handler == ch_obj->streams[i].my_hdl)) {
    141             s_obj = &ch_obj->streams[i];
    142             break;
    143         }
    144     }
    145     return s_obj;
    146 }
    147 
    148 /*===========================================================================
    149  * FUNCTION   : mm_channel_dispatch_super_buf
    150  *
    151  * DESCRIPTION: dispatch super buffer of bundle to registered user
    152  *
    153  * PARAMETERS :
    154  *   @cmd_cb  : ptr storing matched super buf information
    155  *   @userdata: user data ptr
    156  *
    157  * RETURN     : none
    158  *==========================================================================*/
    159 static void mm_channel_dispatch_super_buf(mm_camera_cmdcb_t *cmd_cb,
    160                                           void* user_data)
    161 {
    162     mm_camera_cmd_thread_name("mm_cam_cb");
    163     mm_channel_t * my_obj = (mm_channel_t *)user_data;
    164 
    165     if (NULL == my_obj) {
    166         return;
    167     }
    168 
    169     if (MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB != cmd_cb->cmd_type) {
    170         CDBG_ERROR("%s: Wrong cmd_type (%d) for super buf dataCB",
    171                    __func__, cmd_cb->cmd_type);
    172         return;
    173     }
    174 
    175     if (my_obj->bundle.super_buf_notify_cb) {
    176         my_obj->bundle.super_buf_notify_cb(&cmd_cb->u.superbuf, my_obj->bundle.user_data);
    177     }
    178 }
    179 
    180 /*===========================================================================
    181  * FUNCTION   : mm_channel_process_stream_buf
    182  *
    183  * DESCRIPTION: handle incoming buffer from stream in a bundle. In this function,
    184  *              matching logic will be performed on incoming stream frames.
    185  *              Will depends on the bundle attribute, either storing matched frames
    186  *              in the superbuf queue, or sending matched superbuf frames to upper
    187  *              layer through registered callback.
    188  *
    189  * PARAMETERS :
    190  *   @cmd_cb  : ptr storing matched super buf information
    191  *   @userdata: user data ptr
    192  *
    193  * RETURN     : none
    194  *==========================================================================*/
    195 static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,
    196                                           void *user_data)
    197 {
    198     mm_camera_cmd_thread_name("mm_cam_cmd");
    199     mm_camera_super_buf_notify_mode_t notify_mode;
    200     mm_channel_queue_node_t *node = NULL;
    201     mm_channel_t *ch_obj = (mm_channel_t *)user_data;
    202     if (NULL == ch_obj) {
    203         return;
    204     }
    205     if (MM_CAMERA_CMD_TYPE_DATA_CB  == cmd_cb->cmd_type) {
    206         /* comp_and_enqueue */
    207         mm_channel_superbuf_comp_and_enqueue(
    208                         ch_obj,
    209                         &ch_obj->bundle.superbuf_queue,
    210                         &cmd_cb->u.buf);
    211     } else if (MM_CAMERA_CMD_TYPE_REQ_DATA_CB  == cmd_cb->cmd_type) {
    212         /* skip frames if needed */
    213         ch_obj->pending_cnt = cmd_cb->u.req_buf.num_buf_requested;
    214         ch_obj->pending_retro_cnt = cmd_cb->u.req_buf.num_retro_buf_requested;
    215         ch_obj->bWaitForPrepSnapshotDone = 0;
    216 
    217         ALOGV("%s:[ZSL Retro] pending cnt (%d), retro count (%d)",
    218               __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt);
    219         if (!ch_obj->pending_cnt || (ch_obj->pending_retro_cnt > ch_obj->pending_cnt)) {
    220           ch_obj->pending_retro_cnt = ch_obj->pending_cnt;
    221         }
    222         if (ch_obj->pending_retro_cnt > 0) {
    223           ALOGV("%s: [ZSL Retro] Resetting need Led Flash!!!",
    224               __func__);
    225           ch_obj->needLEDFlash = 0;
    226         }
    227         ch_obj->stopZslSnapshot = 0;
    228         ch_obj->unLockAEC = 0;
    229 
    230         mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue);
    231 
    232     } else if (MM_CAMERA_CMD_TYPE_START_ZSL == cmd_cb->cmd_type) {
    233             ch_obj->manualZSLSnapshot = TRUE;
    234             mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
    235     } else if (MM_CAMERA_CMD_TYPE_STOP_ZSL == cmd_cb->cmd_type) {
    236             ch_obj->manualZSLSnapshot = FALSE;
    237             mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
    238     } else if (MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY == cmd_cb->cmd_type) {
    239            ch_obj->bundle.superbuf_queue.attr.notify_mode = cmd_cb->u.notify_mode;
    240     } else if (MM_CAMERA_CMD_TYPE_FLUSH_QUEUE  == cmd_cb->cmd_type) {
    241         ch_obj->bundle.superbuf_queue.expected_frame_id = cmd_cb->u.frame_idx;
    242         mm_channel_superbuf_flush(ch_obj, &ch_obj->bundle.superbuf_queue);
    243         return;
    244     } else if (MM_CAMERA_CMD_TYPE_GENERAL == cmd_cb->cmd_type) {
    245         CDBG_HIGH("%s:%d] MM_CAMERA_CMD_TYPE_GENERAL", __func__, __LINE__);
    246         switch (cmd_cb->u.gen_cmd.type) {
    247             case MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING:
    248             case MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING: {
    249                 int8_t start = cmd_cb->u.gen_cmd.payload[0];
    250                 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMDTYPE_AF_BRACKETING %d",
    251                     __func__, __LINE__, start);
    252                 mm_channel_superbuf_flush(ch_obj,
    253                                          &ch_obj->bundle.superbuf_queue);
    254 
    255                 if (start) {
    256                     CDBG_HIGH("%s:%d] need AE bracketing, start zsl snapshot",
    257                         __func__, __LINE__);
    258                     ch_obj->need3ABracketing = TRUE;
    259                 } else {
    260                     ch_obj->need3ABracketing = FALSE;
    261                 }
    262             }
    263                 break;
    264             case MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING: {
    265                 int8_t start = cmd_cb->u.gen_cmd.payload[0];
    266                 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMDTYPE_FLASH_BRACKETING %d",
    267                     __func__, __LINE__, start);
    268                 if (start) {
    269                     CDBG_HIGH("%s:%d] need flash bracketing",
    270                         __func__, __LINE__);
    271                     ch_obj->isFlashBracketingEnabled = TRUE;
    272                 } else {
    273                     ch_obj->isFlashBracketingEnabled = FALSE;
    274                 }
    275             }
    276                 break;
    277             case MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X: {
    278                 int8_t start = cmd_cb->u.gen_cmd.payload[0];
    279                 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X %d",
    280                     __func__, __LINE__, start);
    281                 if (start) {
    282                     CDBG_HIGH("%s:%d] need zoom 1x frame",
    283                         __func__, __LINE__);
    284                     ch_obj->isZoom1xFrameRequested = TRUE;
    285                 } else {
    286                     ch_obj->isZoom1xFrameRequested = FALSE;
    287                 }
    288             }
    289                 break;
    290             default:
    291                 CDBG_ERROR("%s:%d] Error: Invalid command", __func__, __LINE__);
    292                 break;
    293         }
    294     }
    295     notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode;
    296 
    297     if ((ch_obj->pending_cnt > 0)
    298         && (ch_obj->needLEDFlash == TRUE || ch_obj->need3ABracketing == TRUE)
    299         && (ch_obj->manualZSLSnapshot == FALSE)
    300         && ch_obj->startZSlSnapshotCalled == FALSE) {
    301 
    302       CDBG_HIGH("%s: need flash, start zsl snapshot", __func__);
    303       mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
    304       ch_obj->startZSlSnapshotCalled = TRUE;
    305       ch_obj->burstSnapNum = ch_obj->pending_cnt;
    306       ch_obj->bWaitForPrepSnapshotDone = 0;
    307       ch_obj->needLEDFlash = FALSE;
    308     } else if (((ch_obj->pending_cnt == 0) || (ch_obj->stopZslSnapshot == 1))
    309             && (ch_obj->manualZSLSnapshot == FALSE)
    310             && (ch_obj->startZSlSnapshotCalled == TRUE)) {
    311       CDBG_HIGH("%s: Got picture cancelled, stop zsl snapshot", __func__);
    312       mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
    313       // Unlock AEC
    314       ch_obj->startZSlSnapshotCalled = FALSE;
    315       ch_obj->needLEDFlash = FALSE;
    316       ch_obj->burstSnapNum = 0;
    317       ch_obj->stopZslSnapshot = 0;
    318       ch_obj->bWaitForPrepSnapshotDone = 0;
    319       ch_obj->unLockAEC = 1;
    320       ch_obj->need3ABracketing = FALSE;
    321     }
    322     /* bufdone for overflowed bufs */
    323     mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue);
    324 
    325     CDBG("%s: Super Buffer received, pending_cnt=%d",
    326         __func__, ch_obj->pending_cnt);
    327     /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */
    328 
    329     CDBG("%s: [ZSL Retro] Out loop pending cnt (%d), retro count (%d)",
    330           __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt);
    331     while (((ch_obj->pending_cnt > 0) ||
    332              (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode)) &&
    333              (!ch_obj->bWaitForPrepSnapshotDone)) {
    334 
    335       CDBG("%s: [ZSL Retro] In loop pending cnt (%d), retro count (%d)",
    336             __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt);
    337         /* dequeue */
    338         node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue);
    339         if (NULL != node) {
    340              uint32_t bReady = 0;
    341             /* decrease pending_cnt */
    342             if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode) {
    343                 ch_obj->pending_cnt--;
    344                 if (ch_obj->pending_retro_cnt > 0) {
    345                   if (ch_obj->pending_retro_cnt == 1) {
    346                     ch_obj->bWaitForPrepSnapshotDone = 1;
    347                     // Retro Snaps are done..
    348                     bReady = 1;
    349                   }
    350                   ch_obj->pending_retro_cnt--;
    351                 }
    352                 CDBG("%s: [ZSL Retro] Super Buffer received, Call client callback,"
    353                     "pending_cnt=%d", __func__, ch_obj->pending_cnt);
    354 
    355                 if (((ch_obj->pending_cnt == 0) ||
    356                       (ch_obj->stopZslSnapshot == 1)) &&
    357                       (ch_obj->manualZSLSnapshot == FALSE) &&
    358                        ch_obj->startZSlSnapshotCalled == TRUE) {
    359                     CDBG("%s: [ZSL Retro] Received all frames requested, stop zsl snapshot", __func__);
    360                     mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
    361                     ch_obj->startZSlSnapshotCalled = FALSE;
    362                     ch_obj->burstSnapNum = 0;
    363                     ch_obj->stopZslSnapshot = 0;
    364                     ch_obj->unLockAEC = 1;
    365 
    366                 }
    367             }
    368             /* dispatch superbuf */
    369             if (NULL != ch_obj->bundle.super_buf_notify_cb) {
    370                 uint8_t i;
    371                 mm_camera_cmdcb_t* cb_node = NULL;
    372 
    373                 CDBG("%s: Send superbuf to HAL, pending_cnt=%d",
    374                      __func__, ch_obj->pending_cnt);
    375 
    376                 /* send cam_sem_post to wake up cb thread to dispatch super buffer */
    377                 cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    378                 if (NULL != cb_node) {
    379                     memset(cb_node, 0, sizeof(mm_camera_cmdcb_t));
    380                     cb_node->cmd_type = MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB;
    381                     cb_node->u.superbuf.num_bufs = node->num_of_bufs;
    382                     for (i=0; i<node->num_of_bufs; i++) {
    383                         cb_node->u.superbuf.bufs[i] = node->super_buf[i].buf;
    384                     }
    385                     cb_node->u.superbuf.camera_handle = ch_obj->cam_obj->my_hdl;
    386                     cb_node->u.superbuf.ch_id = ch_obj->my_hdl;
    387                     cb_node->u.superbuf.bReadyForPrepareSnapshot = bReady;
    388                     if (ch_obj->unLockAEC == 1) {
    389                       cb_node->u.superbuf.bUnlockAEC = 1;
    390                       ALOGE("%s:[ZSL Retro] Unlocking AEC", __func__);
    391                       ch_obj->unLockAEC = 0;
    392                     }
    393 
    394                     /* enqueue to cb thread */
    395                     cam_queue_enq(&(ch_obj->cb_thread.cmd_queue), cb_node);
    396                     /* wake up cb thread */
    397                     cam_sem_post(&(ch_obj->cb_thread.cmd_sem));
    398                 } else {
    399                     CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
    400                     /* buf done with the nonuse super buf */
    401                     for (i=0; i<node->num_of_bufs; i++) {
    402                         mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    403                     }
    404                 }
    405             } else {
    406                 /* buf done with the nonuse super buf */
    407                 uint8_t i;
    408                 for (i=0; i<node->num_of_bufs; i++) {
    409                     mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    410                 }
    411             }
    412             free(node);
    413         } else {
    414             /* no superbuf avail, break the loop */
    415             break;
    416         }
    417     }
    418 }
    419 
    420 /*===========================================================================
    421  * FUNCTION   : mm_channel_fsm_fn
    422  *
    423  * DESCRIPTION: channel finite state machine entry function. Depends on channel
    424  *              state, incoming event will be handled differently.
    425  *
    426  * PARAMETERS :
    427  *   @my_obj   : ptr to a channel object
    428  *   @evt      : channel event to be processed
    429  *   @in_val   : input event payload. Can be NULL if not needed.
    430  *   @out_val  : output payload, Can be NULL if not needed.
    431  *
    432  * RETURN     : int32_t type of status
    433  *              0  -- success
    434  *              -1 -- failure
    435  *==========================================================================*/
    436 int32_t mm_channel_fsm_fn(mm_channel_t *my_obj,
    437                           mm_channel_evt_type_t evt,
    438                           void * in_val,
    439                           void * out_val)
    440 {
    441     int32_t rc = -1;
    442 
    443     CDBG("%s : E state = %d", __func__, my_obj->state);
    444     switch (my_obj->state) {
    445     case MM_CHANNEL_STATE_NOTUSED:
    446         rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val);
    447         break;
    448     case MM_CHANNEL_STATE_STOPPED:
    449         rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val);
    450         break;
    451     case MM_CHANNEL_STATE_ACTIVE:
    452         rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val);
    453         break;
    454     case MM_CHANNEL_STATE_PAUSED:
    455         rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val);
    456         break;
    457     default:
    458         CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
    459         break;
    460     }
    461 
    462     /* unlock ch_lock */
    463     pthread_mutex_unlock(&my_obj->ch_lock);
    464     CDBG("%s : X rc = %d", __func__, rc);
    465     return rc;
    466 }
    467 
    468 /*===========================================================================
    469  * FUNCTION   : mm_channel_fsm_fn_notused
    470  *
    471  * DESCRIPTION: channel finite state machine function to handle event
    472  *              in NOT_USED state.
    473  *
    474  * PARAMETERS :
    475  *   @my_obj   : ptr to a channel object
    476  *   @evt      : channel event to be processed
    477  *   @in_val   : input event payload. Can be NULL if not needed.
    478  *   @out_val  : output payload, Can be NULL if not needed.
    479  *
    480  * RETURN     : int32_t type of status
    481  *              0  -- success
    482  *              -1 -- failure
    483  *==========================================================================*/
    484 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
    485                                   mm_channel_evt_type_t evt,
    486                                   void * in_val,
    487                                   void * out_val)
    488 {
    489     int32_t rc = -1;
    490 
    491     switch (evt) {
    492     default:
    493         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
    494                    __func__, my_obj->state, evt, in_val, out_val);
    495         break;
    496     }
    497 
    498     return rc;
    499 }
    500 
    501 /*===========================================================================
    502  * FUNCTION   : mm_channel_fsm_fn_stopped
    503  *
    504  * DESCRIPTION: channel finite state machine function to handle event
    505  *              in STOPPED state.
    506  *
    507  * PARAMETERS :
    508  *   @my_obj   : ptr to a channel object
    509  *   @evt      : channel event to be processed
    510  *   @in_val   : input event payload. Can be NULL if not needed.
    511  *   @out_val  : output payload, Can be NULL if not needed.
    512  *
    513  * RETURN     : int32_t type of status
    514  *              0  -- success
    515  *              -1 -- failure
    516  *==========================================================================*/
    517 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
    518                                   mm_channel_evt_type_t evt,
    519                                   void * in_val,
    520                                   void * out_val)
    521 {
    522     int32_t rc = 0;
    523     CDBG("%s : E evt = %d", __func__, evt);
    524     switch (evt) {
    525     case MM_CHANNEL_EVT_ADD_STREAM:
    526         {
    527             uint32_t s_hdl = 0;
    528             s_hdl = mm_channel_add_stream(my_obj);
    529             *((uint32_t*)out_val) = s_hdl;
    530             rc = 0;
    531         }
    532         break;
    533     case MM_CHANNEL_EVT_DEL_STREAM:
    534         {
    535             uint32_t s_id = (uint32_t)in_val;
    536             rc = mm_channel_del_stream(my_obj, s_id);
    537         }
    538         break;
    539     case MM_CHANNEL_EVT_START:
    540         {
    541             rc = mm_channel_start(my_obj);
    542             /* first stream started in stopped state
    543              * move to active state */
    544             if (0 == rc) {
    545                 my_obj->state = MM_CHANNEL_STATE_ACTIVE;
    546             }
    547         }
    548         break;
    549     case MM_CHANNEL_EVT_CONFIG_STREAM:
    550         {
    551             mm_evt_paylod_config_stream_t *payload =
    552                 (mm_evt_paylod_config_stream_t *)in_val;
    553             rc = mm_channel_config_stream(my_obj,
    554                                           payload->stream_id,
    555                                           payload->config);
    556         }
    557         break;
    558     case MM_CHANNEL_EVT_GET_BUNDLE_INFO:
    559         {
    560             cam_bundle_config_t *payload =
    561                 (cam_bundle_config_t *)in_val;
    562             rc = mm_channel_get_bundle_info(my_obj, payload);
    563         }
    564         break;
    565     case MM_CHANNEL_EVT_DELETE:
    566         {
    567             mm_channel_release(my_obj);
    568             rc = 0;
    569         }
    570         break;
    571     case MM_CHANNEL_EVT_SET_STREAM_PARM:
    572         {
    573             mm_evt_paylod_set_get_stream_parms_t *payload =
    574                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    575             rc = mm_channel_set_stream_parm(my_obj, payload);
    576         }
    577         break;
    578     case MM_CHANNEL_EVT_GET_STREAM_PARM:
    579         {
    580             mm_evt_paylod_set_get_stream_parms_t *payload =
    581                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    582             rc = mm_channel_get_stream_parm(my_obj, payload);
    583         }
    584         break;
    585     case MM_CHANNEL_EVT_DO_STREAM_ACTION:
    586         {
    587             mm_evt_paylod_do_stream_action_t *payload =
    588                 (mm_evt_paylod_do_stream_action_t *)in_val;
    589             rc = mm_channel_do_stream_action(my_obj, payload);
    590         }
    591         break;
    592     case MM_CHANNEL_EVT_MAP_STREAM_BUF:
    593         {
    594             mm_evt_paylod_map_stream_buf_t *payload =
    595                 (mm_evt_paylod_map_stream_buf_t *)in_val;
    596             rc = mm_channel_map_stream_buf(my_obj, payload);
    597         }
    598         break;
    599     case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
    600         {
    601             mm_evt_paylod_unmap_stream_buf_t *payload =
    602                 (mm_evt_paylod_unmap_stream_buf_t *)in_val;
    603             rc = mm_channel_unmap_stream_buf(my_obj, payload);
    604         }
    605         break;
    606     default:
    607         CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
    608                    __func__, my_obj->state, evt);
    609         break;
    610     }
    611     CDBG("%s : E rc = %d", __func__, rc);
    612     return rc;
    613 }
    614 
    615 /*===========================================================================
    616  * FUNCTION   : mm_channel_fsm_fn_active
    617  *
    618  * DESCRIPTION: channel finite state machine function to handle event
    619  *              in ACTIVE state.
    620  *
    621  * PARAMETERS :
    622  *   @my_obj   : ptr to a channel object
    623  *   @evt      : channel event to be processed
    624  *   @in_val   : input event payload. Can be NULL if not needed.
    625  *   @out_val  : output payload, Can be NULL if not needed.
    626  *
    627  * RETURN     : int32_t type of status
    628  *              0  -- success
    629  *              -1 -- failure
    630  *==========================================================================*/
    631 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
    632                           mm_channel_evt_type_t evt,
    633                           void * in_val,
    634                           void * out_val)
    635 {
    636     int32_t rc = 0;
    637 
    638     CDBG("%s : E evt = %d", __func__, evt);
    639     switch (evt) {
    640     case MM_CHANNEL_EVT_STOP:
    641         {
    642             rc = mm_channel_stop(my_obj);
    643             my_obj->state = MM_CHANNEL_STATE_STOPPED;
    644         }
    645         break;
    646     case MM_CHANNEL_EVT_REQUEST_SUPER_BUF:
    647         {
    648             uint32_t num_buf_requested = (uint32_t)in_val;
    649             uint32_t num_retro_buf_requested = (uint32_t)out_val;
    650             rc = mm_channel_request_super_buf(my_obj,
    651               num_buf_requested, num_retro_buf_requested);
    652         }
    653         break;
    654     case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF:
    655         {
    656             rc = mm_channel_cancel_super_buf_request(my_obj);
    657         }
    658         break;
    659     case MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE:
    660         {
    661             uint32_t frame_idx = (uint32_t)in_val;
    662             rc = mm_channel_flush_super_buf_queue(my_obj, frame_idx);
    663         }
    664         break;
    665     case MM_CHANNEL_EVT_START_ZSL_SNAPSHOT:
    666         {
    667             rc = mm_channel_start_zsl_snapshot(my_obj);
    668         }
    669         break;
    670     case MM_CHANNEL_EVT_STOP_ZSL_SNAPSHOT:
    671         {
    672             rc = mm_channel_stop_zsl_snapshot(my_obj);
    673         }
    674         break;
    675     case MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE:
    676         {
    677             mm_camera_super_buf_notify_mode_t notify_mode = ( mm_camera_super_buf_notify_mode_t ) in_val;
    678             rc = mm_channel_config_notify_mode(my_obj, notify_mode);
    679         }
    680         break;
    681     case MM_CHANNEL_EVT_SET_STREAM_PARM:
    682         {
    683             mm_evt_paylod_set_get_stream_parms_t *payload =
    684                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    685             rc = mm_channel_set_stream_parm(my_obj, payload);
    686         }
    687         break;
    688     case MM_CHANNEL_EVT_GET_STREAM_PARM:
    689         {
    690             mm_evt_paylod_set_get_stream_parms_t *payload =
    691                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    692             rc = mm_channel_get_stream_parm(my_obj, payload);
    693         }
    694         break;
    695     case MM_CHANNEL_EVT_DO_STREAM_ACTION:
    696         {
    697             mm_evt_paylod_do_stream_action_t *payload =
    698                 (mm_evt_paylod_do_stream_action_t *)in_val;
    699             rc = mm_channel_do_stream_action(my_obj, payload);
    700         }
    701         break;
    702     case MM_CHANNEL_EVT_MAP_STREAM_BUF:
    703         {
    704             mm_evt_paylod_map_stream_buf_t *payload =
    705                 (mm_evt_paylod_map_stream_buf_t *)in_val;
    706             if (payload != NULL) {
    707                 uint8_t type = payload->buf_type;
    708                 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
    709                         (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
    710                     rc = mm_channel_map_stream_buf(my_obj, payload);
    711                 }
    712             } else {
    713                 CDBG_ERROR("%s: cannot map regualr stream buf in active state", __func__);
    714             }
    715         }
    716         break;
    717     case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
    718         {
    719             mm_evt_paylod_unmap_stream_buf_t *payload =
    720                 (mm_evt_paylod_unmap_stream_buf_t *)in_val;
    721             if (payload != NULL) {
    722                 uint8_t type = payload->buf_type;
    723                 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
    724                         (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
    725                     rc = mm_channel_unmap_stream_buf(my_obj, payload);
    726                 }
    727             } else {
    728                 CDBG_ERROR("%s: cannot unmap regualr stream buf in active state", __func__);
    729             }
    730         }
    731         break;
    732     case MM_CHANNEL_EVT_AF_BRACKETING:
    733         {
    734             CDBG_HIGH("MM_CHANNEL_EVT_AF_BRACKETING");
    735             int32_t start_flag = ( int32_t ) in_val;
    736             mm_camera_generic_cmd_t gen_cmd;
    737             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING;
    738             gen_cmd.payload[0] = start_flag;
    739             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
    740         }
    741         break;
    742     case MM_CHANNEL_EVT_AE_BRACKETING:
    743         {
    744             CDBG_HIGH("MM_CHANNEL_EVT_AE_BRACKETING");
    745             int32_t start_flag = ( int32_t ) in_val;
    746             mm_camera_generic_cmd_t gen_cmd;
    747             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING;
    748             gen_cmd.payload[0] = start_flag;
    749             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
    750         }
    751         break;
    752     case MM_CHANNEL_EVT_FLASH_BRACKETING:
    753         {
    754             CDBG_HIGH("MM_CHANNEL_EVT_FLASH_BRACKETING");
    755             int32_t start_flag = ( int32_t ) in_val;
    756             mm_camera_generic_cmd_t gen_cmd;
    757             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING;
    758             gen_cmd.payload[0] = start_flag;
    759             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
    760         }
    761         break;
    762     case MM_CHANNEL_EVT_ZOOM_1X:
    763         {
    764             CDBG_HIGH("MM_CHANNEL_EVT_ZOOM_1X");
    765             int32_t start_flag = ( int32_t ) in_val;
    766             mm_camera_generic_cmd_t gen_cmd;
    767             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X;
    768             gen_cmd.payload[0] = start_flag;
    769             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
    770         }
    771         break;
    772      default:
    773         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
    774                    __func__, my_obj->state, evt, in_val, out_val);
    775         break;
    776     }
    777     CDBG("%s : X rc = %d", __func__, rc);
    778     return rc;
    779 }
    780 
    781 /*===========================================================================
    782  * FUNCTION   : mm_channel_fsm_fn_paused
    783  *
    784  * DESCRIPTION: channel finite state machine function to handle event
    785  *              in PAUSED state.
    786  *
    787  * PARAMETERS :
    788  *   @my_obj   : ptr to a channel object
    789  *   @evt      : channel event to be processed
    790  *   @in_val   : input event payload. Can be NULL if not needed.
    791  *   @out_val  : output payload, Can be NULL if not needed.
    792  *
    793  * RETURN     : int32_t type of status
    794  *              0  -- success
    795  *              -1 -- failure
    796  *==========================================================================*/
    797 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
    798                           mm_channel_evt_type_t evt,
    799                           void * in_val,
    800                           void * out_val)
    801 {
    802     int32_t rc = 0;
    803 
    804     /* currently we are not supporting pause/resume channel */
    805     CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
    806                __func__, my_obj->state, evt, in_val, out_val);
    807 
    808     return rc;
    809 }
    810 
    811 /*===========================================================================
    812  * FUNCTION   : mm_channel_init
    813  *
    814  * DESCRIPTION: initialize a channel
    815  *
    816  * PARAMETERS :
    817  *   @my_obj       : channel object be to initialized
    818  *   @attr         : bundle attribute of the channel if needed
    819  *   @channel_cb   : callback function for bundle data notify
    820  *   @userdata     : user data ptr
    821  *
    822  * RETURN     : int32_t type of status
    823  *              0  -- success
    824  *              -1 -- failure
    825  * NOTE       : if no bundle data notify is needed, meaning each stream in the
    826  *              channel will have its own stream data notify callback, then
    827  *              attr, channel_cb, and userdata can be NULL. In this case,
    828  *              no matching logic will be performed in channel for the bundling.
    829  *==========================================================================*/
    830 int32_t mm_channel_init(mm_channel_t *my_obj,
    831                         mm_camera_channel_attr_t *attr,
    832                         mm_camera_buf_notify_t channel_cb,
    833                         void *userdata)
    834 {
    835     int32_t rc = 0;
    836 
    837     my_obj->bundle.super_buf_notify_cb = channel_cb;
    838     my_obj->bundle.user_data = userdata;
    839     if (NULL != attr) {
    840         my_obj->bundle.superbuf_queue.attr = *attr;
    841     }
    842 
    843     CDBG("%s : Launch data poll thread in channel open", __func__);
    844     mm_camera_poll_thread_launch(&my_obj->poll_thread[0],
    845                                  MM_CAMERA_POLL_TYPE_DATA);
    846 
    847     /* change state to stopped state */
    848     my_obj->state = MM_CHANNEL_STATE_STOPPED;
    849     return rc;
    850 }
    851 
    852 /*===========================================================================
    853  * FUNCTION   : mm_channel_release
    854  *
    855  * DESCRIPTION: release a channel resource. Channel state will move to UNUSED
    856  *              state after this call.
    857  *
    858  * PARAMETERS :
    859  *   @my_obj       : channel object
    860  *
    861  * RETURN     : none
    862  *==========================================================================*/
    863 void mm_channel_release(mm_channel_t *my_obj)
    864 {
    865     /* stop data poll thread */
    866     mm_camera_poll_thread_release(&my_obj->poll_thread[0]);
    867 
    868     /* change state to notused state */
    869     my_obj->state = MM_CHANNEL_STATE_NOTUSED;
    870 }
    871 
    872 /*===========================================================================
    873  * FUNCTION   : mm_channel_add_stream
    874  *
    875  * DESCRIPTION: add a stream into the channel
    876  *
    877  * PARAMETERS :
    878  *   @my_obj       : channel object
    879  *
    880  * RETURN     : uint32_t type of stream handle
    881  *              0  -- invalid stream handle, meaning the op failed
    882  *              >0 -- successfully added a stream with a valid handle
    883  *==========================================================================*/
    884 uint32_t mm_channel_add_stream(mm_channel_t *my_obj)
    885 {
    886     int32_t rc = 0;
    887     uint8_t idx = 0;
    888     uint32_t s_hdl = 0;
    889     mm_stream_t *stream_obj = NULL;
    890 
    891     CDBG("%s : E", __func__);
    892     /* check available stream */
    893     for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) {
    894         if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
    895             stream_obj = &my_obj->streams[idx];
    896             break;
    897         }
    898     }
    899     if (NULL == stream_obj) {
    900         CDBG_ERROR("%s: streams reach max, no more stream allowed to add", __func__);
    901         return s_hdl;
    902     }
    903 
    904     /* initialize stream object */
    905     memset(stream_obj, 0, sizeof(mm_stream_t));
    906     stream_obj->fd = -1;
    907     stream_obj->my_hdl = mm_camera_util_generate_handler(idx);
    908     stream_obj->ch_obj = my_obj;
    909     pthread_mutex_init(&stream_obj->buf_lock, NULL);
    910     pthread_mutex_init(&stream_obj->cb_lock, NULL);
    911     stream_obj->state = MM_STREAM_STATE_INITED;
    912 
    913     /* acquire stream */
    914     rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL);
    915     if (0 == rc) {
    916         s_hdl = stream_obj->my_hdl;
    917     } else {
    918         /* error during acquire, de-init */
    919         pthread_mutex_destroy(&stream_obj->buf_lock);
    920         pthread_mutex_destroy(&stream_obj->cb_lock);
    921         memset(stream_obj, 0, sizeof(mm_stream_t));
    922     }
    923     CDBG("%s : stream handle = %d", __func__, s_hdl);
    924     return s_hdl;
    925 }
    926 
    927 /*===========================================================================
    928  * FUNCTION   : mm_channel_del_stream
    929  *
    930  * DESCRIPTION: delete a stream from the channel bu its handle
    931  *
    932  * PARAMETERS :
    933  *   @my_obj       : channel object
    934  *   @stream_id    : stream handle
    935  *
    936  * RETURN     : int32_t type of status
    937  *              0  -- success
    938  *              -1 -- failure
    939  * NOTE       : assume steam is stooped before it can be deleted
    940  *==========================================================================*/
    941 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
    942                               uint32_t stream_id)
    943 {
    944     int rc = -1;
    945     mm_stream_t * stream_obj = NULL;
    946     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
    947 
    948     if (NULL == stream_obj) {
    949         CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d",
    950                    __func__, stream_id);
    951         return rc;
    952     }
    953 
    954     rc = mm_stream_fsm_fn(stream_obj,
    955                           MM_STREAM_EVT_RELEASE,
    956                           NULL,
    957                           NULL);
    958 
    959     return rc;
    960 }
    961 
    962 /*===========================================================================
    963  * FUNCTION   : mm_channel_config_stream
    964  *
    965  * DESCRIPTION: configure a stream
    966  *
    967  * PARAMETERS :
    968  *   @my_obj       : channel object
    969  *   @stream_id    : stream handle
    970  *   @config       : stream configuration
    971  *
    972  * RETURN     : int32_t type of status
    973  *              0  -- success
    974  *              -1 -- failure
    975  *==========================================================================*/
    976 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
    977                                    uint32_t stream_id,
    978                                    mm_camera_stream_config_t *config)
    979 {
    980     int rc = -1;
    981     mm_stream_t * stream_obj = NULL;
    982     CDBG("%s : E stream ID = %d", __func__, stream_id);
    983     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
    984 
    985     if (NULL == stream_obj) {
    986         CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d", __func__, stream_id);
    987         return rc;
    988     }
    989 
    990     /* set stream fmt */
    991     rc = mm_stream_fsm_fn(stream_obj,
    992                           MM_STREAM_EVT_SET_FMT,
    993                           (void *)config,
    994                           NULL);
    995     CDBG("%s : X rc = %d",__func__,rc);
    996     return rc;
    997 }
    998 
    999 /*===========================================================================
   1000  * FUNCTION   : mm_channel_get_bundle_info
   1001  *
   1002  * DESCRIPTION: query bundle info of the channel, which should include all
   1003  *              streams within this channel
   1004  *
   1005  * PARAMETERS :
   1006  *   @my_obj       : channel object
   1007  *   @bundle_info  : bundle info to be filled in
   1008  *
   1009  * RETURN     : int32_t type of status
   1010  *              0  -- success
   1011  *              -1 -- failure
   1012  *==========================================================================*/
   1013 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj,
   1014                                    cam_bundle_config_t *bundle_info)
   1015 {
   1016     int i;
   1017     mm_stream_t *s_obj = NULL;
   1018     int32_t rc = 0;
   1019 
   1020     memset(bundle_info, 0, sizeof(cam_bundle_config_t));
   1021     bundle_info->bundle_id = my_obj->my_hdl;
   1022     bundle_info->num_of_streams = 0;
   1023     for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
   1024         if (my_obj->streams[i].my_hdl > 0) {
   1025             s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1026                                                           my_obj->streams[i].my_hdl);
   1027             if (NULL != s_obj) {
   1028                 if (CAM_STREAM_TYPE_METADATA != s_obj->stream_info->stream_type) {
   1029                     bundle_info->stream_ids[bundle_info->num_of_streams++] =
   1030                                                         s_obj->server_stream_id;
   1031                 }
   1032             } else {
   1033                 CDBG_ERROR("%s: cannot find stream obj (%d) by handler (%d)",
   1034                            __func__, i, my_obj->streams[i].my_hdl);
   1035                 rc = -1;
   1036                 break;
   1037             }
   1038         }
   1039     }
   1040     if (rc != 0) {
   1041         /* error, reset to 0 */
   1042         memset(bundle_info, 0, sizeof(cam_bundle_config_t));
   1043     }
   1044     return rc;
   1045 }
   1046 
   1047 /*===========================================================================
   1048  * FUNCTION   : mm_channel_start
   1049  *
   1050  * DESCRIPTION: start a channel, which will start all streams in the channel
   1051  *
   1052  * PARAMETERS :
   1053  *   @my_obj       : channel object
   1054  *
   1055  * RETURN     : int32_t type of status
   1056  *              0  -- success
   1057  *              -1 -- failure
   1058  *==========================================================================*/
   1059 int32_t mm_channel_start(mm_channel_t *my_obj)
   1060 {
   1061     int32_t rc = 0;
   1062     int i, j;
   1063     mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
   1064     uint8_t num_streams_to_start = 0;
   1065     mm_stream_t *s_obj = NULL;
   1066     int meta_stream_idx = 0;
   1067 
   1068     for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
   1069         if (my_obj->streams[i].my_hdl > 0) {
   1070             s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1071                                                           my_obj->streams[i].my_hdl);
   1072             if (NULL != s_obj) {
   1073                 /* remember meta data stream index */
   1074                 if (s_obj->stream_info->stream_type == CAM_STREAM_TYPE_METADATA) {
   1075                     meta_stream_idx = num_streams_to_start;
   1076                 }
   1077                 s_objs[num_streams_to_start++] = s_obj;
   1078             }
   1079         }
   1080     }
   1081 
   1082     if (meta_stream_idx > 0 ) {
   1083         /* always start meta data stream first, so switch the stream object with the first one */
   1084         s_obj = s_objs[0];
   1085         s_objs[0] = s_objs[meta_stream_idx];
   1086         s_objs[meta_stream_idx] = s_obj;
   1087     }
   1088 
   1089     if (NULL != my_obj->bundle.super_buf_notify_cb) {
   1090         /* need to send up cb, therefore launch thread */
   1091         /* init superbuf queue */
   1092         mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue);
   1093         my_obj->bundle.superbuf_queue.num_streams = num_streams_to_start;
   1094         my_obj->bundle.superbuf_queue.expected_frame_id = 0;
   1095         my_obj->bundle.superbuf_queue.expected_frame_id_without_led = 0;
   1096         my_obj->bundle.superbuf_queue.led_off_start_frame_id = 0;
   1097         my_obj->bundle.superbuf_queue.led_on_start_frame_id = 0;
   1098         my_obj->bundle.superbuf_queue.led_on_num_frames = 0;
   1099 
   1100         for (i = 0; i < num_streams_to_start; i++) {
   1101             /* set bundled flag to streams */
   1102             s_objs[i]->is_bundled = 1;
   1103             /* init bundled streams to invalid value -1 */
   1104             my_obj->bundle.superbuf_queue.bundled_streams[i] = s_objs[i]->my_hdl;
   1105         }
   1106 
   1107         /* launch cb thread for dispatching super buf through cb */
   1108         mm_camera_cmd_thread_launch(&my_obj->cb_thread,
   1109                                     mm_channel_dispatch_super_buf,
   1110                                     (void*)my_obj);
   1111 
   1112         /* launch cmd thread for super buf dataCB */
   1113         mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
   1114                                     mm_channel_process_stream_buf,
   1115                                     (void*)my_obj);
   1116 
   1117         /* set flag to TRUE */
   1118         my_obj->bundle.is_active = TRUE;
   1119     }
   1120 
   1121     for (i = 0; i < num_streams_to_start; i++) {
   1122         /* all streams within a channel should be started at the same time */
   1123         if (s_objs[i]->state == MM_STREAM_STATE_ACTIVE) {
   1124             CDBG_ERROR("%s: stream already started idx(%d)", __func__, i);
   1125             rc = -1;
   1126             break;
   1127         }
   1128 
   1129         /* allocate buf */
   1130         rc = mm_stream_fsm_fn(s_objs[i],
   1131                               MM_STREAM_EVT_GET_BUF,
   1132                               NULL,
   1133                               NULL);
   1134         if (0 != rc) {
   1135             CDBG_ERROR("%s: get buf failed at idx(%d)", __func__, i);
   1136             break;
   1137         }
   1138 
   1139         /* reg buf */
   1140         rc = mm_stream_fsm_fn(s_objs[i],
   1141                               MM_STREAM_EVT_REG_BUF,
   1142                               NULL,
   1143                               NULL);
   1144         if (0 != rc) {
   1145             CDBG_ERROR("%s: reg buf failed at idx(%d)", __func__, i);
   1146             break;
   1147         }
   1148 
   1149         /* start stream */
   1150         rc = mm_stream_fsm_fn(s_objs[i],
   1151                               MM_STREAM_EVT_START,
   1152                               NULL,
   1153                               NULL);
   1154         if (0 != rc) {
   1155             CDBG_ERROR("%s: start stream failed at idx(%d)", __func__, i);
   1156             break;
   1157         }
   1158     }
   1159 
   1160     /* error handling */
   1161     if (0 != rc) {
   1162         for (j=0; j<=i; j++) {
   1163             /* stop streams*/
   1164             mm_stream_fsm_fn(s_objs[j],
   1165                              MM_STREAM_EVT_STOP,
   1166                              NULL,
   1167                              NULL);
   1168 
   1169             /* unreg buf */
   1170             mm_stream_fsm_fn(s_objs[j],
   1171                              MM_STREAM_EVT_UNREG_BUF,
   1172                              NULL,
   1173                              NULL);
   1174 
   1175             /* put buf back */
   1176             mm_stream_fsm_fn(s_objs[j],
   1177                              MM_STREAM_EVT_PUT_BUF,
   1178                              NULL,
   1179                              NULL);
   1180         }
   1181 
   1182         /* destroy super buf cmd thread */
   1183         if (TRUE == my_obj->bundle.is_active) {
   1184             /* first stop bundle thread */
   1185             mm_camera_cmd_thread_release(&my_obj->cmd_thread);
   1186             mm_camera_cmd_thread_release(&my_obj->cb_thread);
   1187 
   1188             /* deinit superbuf queue */
   1189             mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
   1190 
   1191             /* memset bundle info */
   1192             memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t));
   1193         }
   1194     }
   1195     my_obj->bWaitForPrepSnapshotDone = 0;
   1196 
   1197     return rc;
   1198 }
   1199 
   1200 /*===========================================================================
   1201  * FUNCTION   : mm_channel_stop
   1202  *
   1203  * DESCRIPTION: stop a channel, which will stop all streams in the channel
   1204  *
   1205  * PARAMETERS :
   1206  *   @my_obj       : channel object
   1207  *
   1208  * RETURN     : int32_t type of status
   1209  *              0  -- success
   1210  *              -1 -- failure
   1211  *==========================================================================*/
   1212 int32_t mm_channel_stop(mm_channel_t *my_obj)
   1213 {
   1214     int32_t rc = 0;
   1215     int i;
   1216     mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
   1217     uint8_t num_streams_to_stop = 0;
   1218     mm_stream_t *s_obj = NULL;
   1219     int meta_stream_idx = 0;
   1220 
   1221     for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
   1222         if (my_obj->streams[i].my_hdl > 0) {
   1223             s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1224                                                           my_obj->streams[i].my_hdl);
   1225             if (NULL != s_obj) {
   1226                 /* remember meta data stream index */
   1227                 if (s_obj->stream_info->stream_type == CAM_STREAM_TYPE_METADATA) {
   1228                     meta_stream_idx = num_streams_to_stop;
   1229                 }
   1230                 s_objs[num_streams_to_stop++] = s_obj;
   1231             }
   1232         }
   1233     }
   1234 
   1235     if (meta_stream_idx < num_streams_to_stop - 1 ) {
   1236         /* always stop meta data stream last, so switch the stream object with the last one */
   1237         s_obj = s_objs[num_streams_to_stop - 1];
   1238         s_objs[num_streams_to_stop - 1] = s_objs[meta_stream_idx];
   1239         s_objs[meta_stream_idx] = s_obj;
   1240     }
   1241 
   1242     for (i = 0; i < num_streams_to_stop; i++) {
   1243         /* stream off */
   1244         mm_stream_fsm_fn(s_objs[i],
   1245                          MM_STREAM_EVT_STOP,
   1246                          NULL,
   1247                          NULL);
   1248 
   1249         /* unreg buf at kernel */
   1250         mm_stream_fsm_fn(s_objs[i],
   1251                          MM_STREAM_EVT_UNREG_BUF,
   1252                          NULL,
   1253                          NULL);
   1254     }
   1255 
   1256     /* destroy super buf cmd thread */
   1257     if (TRUE == my_obj->bundle.is_active) {
   1258         /* first stop bundle thread */
   1259         mm_camera_cmd_thread_release(&my_obj->cmd_thread);
   1260         mm_camera_cmd_thread_release(&my_obj->cb_thread);
   1261 
   1262         /* deinit superbuf queue */
   1263         mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
   1264 
   1265         /* memset bundle info */
   1266         memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t));
   1267     }
   1268 
   1269     /* since all streams are stopped, we are safe to
   1270      * release all buffers allocated in stream */
   1271     for (i = 0; i < num_streams_to_stop; i++) {
   1272         /* put buf back */
   1273         mm_stream_fsm_fn(s_objs[i],
   1274                          MM_STREAM_EVT_PUT_BUF,
   1275                          NULL,
   1276                          NULL);
   1277     }
   1278 
   1279     return rc;
   1280 }
   1281 
   1282 /*===========================================================================
   1283  * FUNCTION   : mm_channel_request_super_buf
   1284  *
   1285  * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched
   1286  *              frames from superbuf queue
   1287  *
   1288  * PARAMETERS :
   1289  *   @my_obj       : channel object
   1290  *   @num_buf_requested : number of matched frames needed
   1291  *   @num_retro_buf_requested : number of retro frames needed
   1292  *
   1293  * RETURN     : int32_t type of status
   1294  *              0  -- success
   1295  *              -1 -- failure
   1296  *==========================================================================*/
   1297 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj,
   1298                uint32_t num_buf_requested, uint32_t num_retro_buf_requested)
   1299 {
   1300     int32_t rc = 0;
   1301     mm_camera_cmdcb_t* node = NULL;
   1302 
   1303     /* set pending_cnt
   1304      * will trigger dispatching super frames if pending_cnt > 0 */
   1305     /* send cam_sem_post to wake up cmd thread to dispatch super buffer */
   1306     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1307     if (NULL != node) {
   1308         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1309         node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB;
   1310         node->u.req_buf.num_buf_requested = num_buf_requested;
   1311         node->u.req_buf.num_retro_buf_requested = num_retro_buf_requested;
   1312 
   1313         /* enqueue to cmd thread */
   1314         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1315 
   1316         /* wake up cmd thread */
   1317         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   1318     } else {
   1319         CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
   1320         rc = -1;
   1321     }
   1322 
   1323     return rc;
   1324 }
   1325 
   1326 /*===========================================================================
   1327  * FUNCTION   : mm_channel_cancel_super_buf_request
   1328  *
   1329  * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount
   1330  *              of matched frames from superbuf queue
   1331  *
   1332  * PARAMETERS :
   1333  *   @my_obj       : channel object
   1334  *
   1335  * RETURN     : int32_t type of status
   1336  *              0  -- success
   1337  *              -1 -- failure
   1338  *==========================================================================*/
   1339 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj)
   1340 {
   1341     int32_t rc = 0;
   1342     /* reset pending_cnt */
   1343     rc = mm_channel_request_super_buf(my_obj, 0, 0);
   1344     return rc;
   1345 }
   1346 
   1347 /*===========================================================================
   1348  * FUNCTION   : mm_channel_flush_super_buf_queue
   1349  *
   1350  * DESCRIPTION: flush superbuf queue
   1351  *
   1352  * PARAMETERS :
   1353  *   @my_obj  : channel object
   1354  *   @frame_idx : frame idx until which to flush all superbufs
   1355  *
   1356  * RETURN     : int32_t type of status
   1357  *              0  -- success
   1358  *              -1 -- failure
   1359  *==========================================================================*/
   1360 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, uint32_t frame_idx)
   1361 {
   1362     int32_t rc = 0;
   1363     mm_camera_cmdcb_t* node = NULL;
   1364 
   1365     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1366     if (NULL != node) {
   1367         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1368         node->cmd_type = MM_CAMERA_CMD_TYPE_FLUSH_QUEUE;
   1369         node->u.frame_idx = frame_idx;
   1370 
   1371         /* enqueue to cmd thread */
   1372         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1373 
   1374         /* wake up cmd thread */
   1375         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   1376     } else {
   1377         CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
   1378         rc = -1;
   1379     }
   1380 
   1381     return rc;
   1382 }
   1383 
   1384 /*===========================================================================
   1385  * FUNCTION   : mm_channel_config_notify_mode
   1386  *
   1387  * DESCRIPTION: configure notification mode
   1388  *
   1389  * PARAMETERS :
   1390  *   @my_obj  : channel object
   1391  *   @notify_mode : notification mode
   1392  *
   1393  * RETURN     : int32_t type of status
   1394  *              0  -- success
   1395  *              -1 -- failure
   1396  *==========================================================================*/
   1397 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj,
   1398                                       mm_camera_super_buf_notify_mode_t notify_mode)
   1399 {
   1400     int32_t rc = 0;
   1401     mm_camera_cmdcb_t* node = NULL;
   1402 
   1403     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1404     if (NULL != node) {
   1405         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1406         node->u.notify_mode = notify_mode;
   1407         node->cmd_type = MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY;
   1408 
   1409         /* enqueue to cmd thread */
   1410         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1411 
   1412         /* wake up cmd thread */
   1413         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   1414     } else {
   1415         CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
   1416         rc = -1;
   1417     }
   1418 
   1419     return rc;
   1420 }
   1421 
   1422 /*===========================================================================
   1423  * FUNCTION   : mm_channel_start_zsl_snapshot
   1424  *
   1425  * DESCRIPTION: start zsl snapshot
   1426  *
   1427  * PARAMETERS :
   1428  *   @my_obj  : channel object
   1429  *
   1430  * RETURN     : int32_t type of status
   1431  *              0  -- success
   1432  *              -1 -- failure
   1433  *==========================================================================*/
   1434 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj)
   1435 {
   1436     int32_t rc = 0;
   1437     mm_camera_cmdcb_t* node = NULL;
   1438 
   1439     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1440     if (NULL != node) {
   1441         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1442         node->cmd_type = MM_CAMERA_CMD_TYPE_START_ZSL;
   1443 
   1444         /* enqueue to cmd thread */
   1445         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1446 
   1447         /* wake up cmd thread */
   1448         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   1449     } else {
   1450         CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
   1451         rc = -1;
   1452     }
   1453 
   1454     return rc;
   1455 }
   1456 
   1457 /*===========================================================================
   1458  * FUNCTION   : mm_channel_stop_zsl_snapshot
   1459  *
   1460  * DESCRIPTION: stop zsl snapshot
   1461  *
   1462  * PARAMETERS :
   1463  *   @my_obj  : channel object
   1464  *
   1465  * RETURN     : int32_t type of status
   1466  *              0  -- success
   1467  *              -1 -- failure
   1468  *==========================================================================*/
   1469 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj)
   1470 {
   1471     int32_t rc = 0;
   1472     mm_camera_cmdcb_t* node = NULL;
   1473 
   1474     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1475     if (NULL != node) {
   1476         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1477         node->cmd_type = MM_CAMERA_CMD_TYPE_STOP_ZSL;
   1478 
   1479         /* enqueue to cmd thread */
   1480         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1481 
   1482         /* wake up cmd thread */
   1483         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   1484     } else {
   1485         CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
   1486         rc = -1;
   1487     }
   1488 
   1489     return rc;
   1490 }
   1491 
   1492 /*===========================================================================
   1493  * FUNCTION   : mm_channel_qbuf
   1494  *
   1495  * DESCRIPTION: enqueue buffer back to kernel
   1496  *
   1497  * PARAMETERS :
   1498  *   @my_obj       : channel object
   1499  *   @buf          : buf ptr to be enqueued
   1500  *
   1501  * RETURN     : int32_t type of status
   1502  *              0  -- success
   1503  *              -1 -- failure
   1504  *==========================================================================*/
   1505 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
   1506                         mm_camera_buf_def_t *buf)
   1507 {
   1508     int32_t rc = -1;
   1509     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id);
   1510 
   1511     if (NULL != s_obj) {
   1512         rc = mm_stream_fsm_fn(s_obj,
   1513                               MM_STREAM_EVT_QBUF,
   1514                               (void *)buf,
   1515                               NULL);
   1516     }
   1517 
   1518     return rc;
   1519 }
   1520 
   1521 /*===========================================================================
   1522  * FUNCTION   : mm_channel_set_stream_parms
   1523  *
   1524  * DESCRIPTION: set parameters per stream
   1525  *
   1526  * PARAMETERS :
   1527  *   @my_obj       : channel object
   1528  *   @s_id         : stream handle
   1529  *   @parms        : ptr to a param struct to be set to server
   1530  *
   1531  * RETURN     : int32_t type of status
   1532  *              0  -- success
   1533  *              -1 -- failure
   1534  * NOTE       : Assume the parms struct buf is already mapped to server via
   1535  *              domain socket. Corresponding fields of parameters to be set
   1536  *              are already filled in by upper layer caller.
   1537  *==========================================================================*/
   1538 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
   1539                                    mm_evt_paylod_set_get_stream_parms_t *payload)
   1540 {
   1541     int32_t rc = -1;
   1542     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1543                                                                payload->stream_id);
   1544     if (NULL != s_obj) {
   1545         rc = mm_stream_fsm_fn(s_obj,
   1546                               MM_STREAM_EVT_SET_PARM,
   1547                               (void *)payload,
   1548                               NULL);
   1549     }
   1550 
   1551     return rc;
   1552 }
   1553 
   1554 /*===========================================================================
   1555  * FUNCTION   : mm_channel_get_stream_parms
   1556  *
   1557  * DESCRIPTION: get parameters per stream
   1558  *
   1559  * PARAMETERS :
   1560  *   @my_obj       : channel object
   1561  *   @s_id         : stream handle
   1562  *   @parms        : ptr to a param struct to be get from server
   1563  *
   1564  * RETURN     : int32_t type of status
   1565  *              0  -- success
   1566  *              -1 -- failure
   1567  * NOTE       : Assume the parms struct buf is already mapped to server via
   1568  *              domain socket. Parameters to be get from server are already
   1569  *              filled in by upper layer caller. After this call, corresponding
   1570  *              fields of requested parameters will be filled in by server with
   1571  *              detailed information.
   1572  *==========================================================================*/
   1573 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
   1574                                    mm_evt_paylod_set_get_stream_parms_t *payload)
   1575 {
   1576     int32_t rc = -1;
   1577     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1578                                                                payload->stream_id);
   1579     if (NULL != s_obj) {
   1580         rc = mm_stream_fsm_fn(s_obj,
   1581                               MM_STREAM_EVT_GET_PARM,
   1582                               (void *)payload,
   1583                               NULL);
   1584     }
   1585 
   1586     return rc;
   1587 }
   1588 
   1589 /*===========================================================================
   1590  * FUNCTION   : mm_channel_do_stream_action
   1591  *
   1592  * DESCRIPTION: request server to perform stream based action. Maybe removed later
   1593  *              if the functionality is included in mm_camera_set_parms
   1594  *
   1595  * PARAMETERS :
   1596  *   @my_obj       : channel object
   1597  *   @s_id         : stream handle
   1598  *   @actions      : ptr to an action struct buf to be performed by server
   1599  *
   1600  * RETURN     : int32_t type of status
   1601  *              0  -- success
   1602  *              -1 -- failure
   1603  * NOTE       : Assume the action struct buf is already mapped to server via
   1604  *              domain socket. Actions to be performed by server are already
   1605  *              filled in by upper layer caller.
   1606  *==========================================================================*/
   1607 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
   1608                                    mm_evt_paylod_do_stream_action_t *payload)
   1609 {
   1610     int32_t rc = -1;
   1611     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1612                                                                payload->stream_id);
   1613     if (NULL != s_obj) {
   1614         rc = mm_stream_fsm_fn(s_obj,
   1615                               MM_STREAM_EVT_DO_ACTION,
   1616                               (void *)payload,
   1617                               NULL);
   1618     }
   1619 
   1620     return rc;
   1621 }
   1622 
   1623 /*===========================================================================
   1624  * FUNCTION   : mm_channel_map_stream_buf
   1625  *
   1626  * DESCRIPTION: mapping stream buffer via domain socket to server
   1627  *
   1628  * PARAMETERS :
   1629  *   @my_obj       : channel object
   1630  *   @payload      : ptr to payload for mapping
   1631  *
   1632  * RETURN     : int32_t type of status
   1633  *              0  -- success
   1634  *              -1 -- failure
   1635  *==========================================================================*/
   1636 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
   1637                                   mm_evt_paylod_map_stream_buf_t *payload)
   1638 {
   1639     int32_t rc = -1;
   1640     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1641                                                                payload->stream_id);
   1642     if (NULL != s_obj) {
   1643         rc = mm_stream_map_buf(s_obj,
   1644                                payload->buf_type,
   1645                                payload->buf_idx,
   1646                                payload->plane_idx,
   1647                                payload->fd,
   1648                                payload->size);
   1649     }
   1650 
   1651     return rc;
   1652 }
   1653 
   1654 /*===========================================================================
   1655  * FUNCTION   : mm_channel_unmap_stream_buf
   1656  *
   1657  * DESCRIPTION: unmapping stream buffer via domain socket to server
   1658  *
   1659  * PARAMETERS :
   1660  *   @my_obj       : channel object
   1661  *   @payload      : ptr to unmap payload
   1662  *
   1663  * RETURN     : int32_t type of status
   1664  *              0  -- success
   1665  *              -1 -- failure
   1666  *==========================================================================*/
   1667 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
   1668                                     mm_evt_paylod_unmap_stream_buf_t *payload)
   1669 {
   1670     int32_t rc = -1;
   1671     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1672                                                                payload->stream_id);
   1673     if (NULL != s_obj) {
   1674         rc = mm_stream_unmap_buf(s_obj, payload->buf_type,
   1675                                  payload->buf_idx, payload->plane_idx);
   1676     }
   1677 
   1678     return rc;
   1679 }
   1680 
   1681 /*===========================================================================
   1682  * FUNCTION   : mm_channel_superbuf_queue_init
   1683  *
   1684  * DESCRIPTION: initialize superbuf queue in the channel
   1685  *
   1686  * PARAMETERS :
   1687  *   @queue   : ptr to superbuf queue to be initialized
   1688  *
   1689  * RETURN     : int32_t type of status
   1690  *              0  -- success
   1691  *              -1 -- failure
   1692  *==========================================================================*/
   1693 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)
   1694 {
   1695     return cam_queue_init(&queue->que);
   1696 }
   1697 
   1698 /*===========================================================================
   1699  * FUNCTION   : mm_channel_superbuf_queue_deinit
   1700  *
   1701  * DESCRIPTION: deinitialize superbuf queue in the channel
   1702  *
   1703  * PARAMETERS :
   1704  *   @queue   : ptr to superbuf queue to be deinitialized
   1705  *
   1706  * RETURN     : int32_t type of status
   1707  *              0  -- success
   1708  *              -1 -- failure
   1709  *==========================================================================*/
   1710 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)
   1711 {
   1712     return cam_queue_deinit(&queue->que);
   1713 }
   1714 
   1715 /*===========================================================================
   1716  * FUNCTION   : mm_channel_util_seq_comp_w_rollover
   1717  *
   1718  * DESCRIPTION: utility function to handle sequence number comparison with rollover
   1719  *
   1720  * PARAMETERS :
   1721  *   @v1      : first value to be compared
   1722  *   @v2      : second value to be compared
   1723  *
   1724  * RETURN     : int8_t type of comparison result
   1725  *              >0  -- v1 larger than v2
   1726  *              =0  -- vi equal to v2
   1727  *              <0  -- v1 smaller than v2
   1728  *==========================================================================*/
   1729 int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1,
   1730                                            uint32_t v2)
   1731 {
   1732     int8_t ret = 0;
   1733 
   1734     /* TODO: need to handle the case if v2 roll over to 0 */
   1735     if (v1 > v2) {
   1736         ret = 1;
   1737     } else if (v1 < v2) {
   1738         ret = -1;
   1739     }
   1740 
   1741     return ret;
   1742 }
   1743 
   1744 /*===========================================================================
   1745  * FUNCTION   : mm_channel_handle_metadata
   1746  *
   1747  * DESCRIPTION: Handle frame matching logic change due to metadata
   1748  *
   1749  * PARAMETERS :
   1750  *   @ch_obj  : channel object
   1751  *   @queue   : superbuf queue
   1752  *   @buf_info: new buffer from stream
   1753  *
   1754  * RETURN     : int32_t type of status
   1755  *              0  -- success
   1756  *              -1 -- failure
   1757  *==========================================================================*/
   1758 int32_t mm_channel_handle_metadata(
   1759                         mm_channel_t* ch_obj,
   1760                         mm_channel_queue_t * queue,
   1761                         mm_camera_buf_info_t *buf_info)
   1762 {
   1763 
   1764     int rc = 0 ;
   1765     mm_stream_t* stream_obj = NULL;
   1766     stream_obj = mm_channel_util_get_stream_by_handler(ch_obj,
   1767                 buf_info->stream_id);
   1768     uint8_t is_prep_snapshot_done_valid = 0;
   1769     uint8_t is_good_frame_idx_range_valid = 0;
   1770     int32_t prep_snapshot_done_state;
   1771     cam_frame_idx_range_t good_frame_idx_range;
   1772     uint8_t is_crop_1x_found = 0;
   1773     uint32_t snapshot_stream_id = 0;
   1774     uint32_t i;
   1775     /* Set expected frame id to a future frame idx, large enough to wait
   1776     * for good_frame_idx_range, and small enough to still capture an image */
   1777     const int max_future_frame_offset = 100;
   1778 
   1779     memset(&good_frame_idx_range, 0, sizeof(good_frame_idx_range));
   1780 
   1781     if (NULL == stream_obj) {
   1782         CDBG_ERROR("%s: Invalid Stream Object for stream_id = %d",
   1783                    __func__, buf_info->stream_id);
   1784         rc = -1;
   1785         goto end;
   1786     }
   1787     if (NULL == stream_obj->stream_info) {
   1788         CDBG_ERROR("%s: NULL stream info for stream_id = %d",
   1789                     __func__, buf_info->stream_id);
   1790         rc = -1;
   1791         goto end;
   1792     }
   1793 
   1794     if (CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) {
   1795         const metadata_buffer_t *metadata;
   1796         metadata = (const metadata_buffer_t *)buf_info->buf->buffer;
   1797 
   1798         if (NULL == metadata) {
   1799             CDBG_ERROR("%s: NULL metadata buffer for metadata stream",
   1800                        __func__);
   1801             rc = -1;
   1802             goto end;
   1803         }
   1804         CDBG("%s: E , expected frame id: %d", __func__, queue->expected_frame_id);
   1805 
   1806         if (IS_META_AVAILABLE(CAM_INTF_META_PREP_SNAPSHOT_DONE, metadata)) {
   1807             prep_snapshot_done_state = *((int32_t*)
   1808                 POINTER_OF_META(CAM_INTF_META_PREP_SNAPSHOT_DONE, metadata));
   1809             is_prep_snapshot_done_valid = 1;
   1810             CDBG("%s: prepare snapshot done valid ", __func__);
   1811         }
   1812         if (IS_META_AVAILABLE(CAM_INTF_META_GOOD_FRAME_IDX_RANGE, metadata)){
   1813             good_frame_idx_range = *((cam_frame_idx_range_t*)
   1814                 POINTER_OF_META(CAM_INTF_META_GOOD_FRAME_IDX_RANGE, metadata));
   1815             is_good_frame_idx_range_valid = 1;
   1816             CDBG("%s: good_frame_idx_range : min: %d, max: %d , num frames = %d",
   1817                 __func__, good_frame_idx_range.min_frame_idx,
   1818                 good_frame_idx_range.max_frame_idx, good_frame_idx_range.num_led_on_frames);
   1819         }
   1820         if (IS_META_AVAILABLE(CAM_INTF_META_CROP_DATA, metadata)) {
   1821             cam_crop_data_t crop_data = *((cam_crop_data_t *)
   1822                 POINTER_OF_META(CAM_INTF_META_CROP_DATA, metadata));
   1823 
   1824             for (i=0; i<ARRAY_SIZE(ch_obj->streams); i++) {
   1825                 if (CAM_STREAM_TYPE_SNAPSHOT ==
   1826                     ch_obj->streams[i].stream_info->stream_type) {
   1827                     snapshot_stream_id = ch_obj->streams[i].server_stream_id;
   1828                     break;
   1829                 }
   1830             }
   1831 
   1832             for (i=0; i<crop_data.num_of_streams; i++) {
   1833                 if (snapshot_stream_id == crop_data.crop_info[i].stream_id) {
   1834                     if (!crop_data.crop_info[i].crop.left &&
   1835                             !crop_data.crop_info[i].crop.top) {
   1836                         is_crop_1x_found = 1;
   1837                         break;
   1838                     }
   1839                 }
   1840             }
   1841         }
   1842 
   1843         if (is_prep_snapshot_done_valid &&
   1844                 is_good_frame_idx_range_valid) {
   1845             CDBG_ERROR("%s: prep_snapshot_done and good_idx_range shouldn't be "
   1846                 "valid at the same time", __func__);
   1847             rc = -1;
   1848             goto end;
   1849         }
   1850 
   1851         if (ch_obj->isZoom1xFrameRequested) {
   1852             if (is_crop_1x_found) {
   1853                 ch_obj->isZoom1xFrameRequested = 0;
   1854                 queue->expected_frame_id = buf_info->frame_idx + 1;
   1855             } else {
   1856                 queue->expected_frame_id += max_future_frame_offset;
   1857                 /* Flush unwanted frames */
   1858                 mm_channel_superbuf_flush_matched(ch_obj, queue);
   1859             }
   1860             goto end;
   1861         }
   1862 
   1863         if (is_prep_snapshot_done_valid) {
   1864             ch_obj->bWaitForPrepSnapshotDone = 0;
   1865             if (prep_snapshot_done_state == NEED_FUTURE_FRAME) {
   1866                 queue->expected_frame_id += max_future_frame_offset;
   1867                 CDBG("%s: [ZSL Retro] NEED_FUTURE_FRAME, expected frame id = %d ",
   1868                         __func__,  queue->expected_frame_id);
   1869 
   1870                 mm_channel_superbuf_flush(ch_obj, queue);
   1871                 ch_obj->needLEDFlash = TRUE;
   1872             } else {
   1873                 ch_obj->needLEDFlash = FALSE;
   1874             }
   1875         } else if (is_good_frame_idx_range_valid) {
   1876             if (good_frame_idx_range.min_frame_idx >
   1877                 queue->expected_frame_id) {
   1878                 CDBG_HIGH("%s: [ZSL Retro] min_frame_idx %d is greater than expected_frame_id %d",
   1879                     __func__, good_frame_idx_range.min_frame_idx,
   1880                     queue->expected_frame_id);
   1881             }
   1882             queue->expected_frame_id =
   1883                 good_frame_idx_range.min_frame_idx;
   1884              if((ch_obj->needLEDFlash == TRUE) && (ch_obj->burstSnapNum > 1)) {
   1885                 queue->expected_frame_id =
   1886                 good_frame_idx_range.min_frame_idx;
   1887                 queue->led_on_start_frame_id =
   1888                 good_frame_idx_range.min_frame_idx;
   1889                 queue->led_off_start_frame_id =
   1890                 good_frame_idx_range.max_frame_idx;
   1891                 queue->once = 0;
   1892                 queue->led_on_num_frames =
   1893                   good_frame_idx_range.num_led_on_frames;
   1894                 queue->frame_skip_count = good_frame_idx_range.frame_skip_count;
   1895                 CDBG("%s: [ZSL Retro] Need Flash, expected frame id = %d,"
   1896                         " led_on start = %d, led off start = %d, led on frames = %d ",
   1897                         __func__,   queue->expected_frame_id, queue->led_on_start_frame_id,
   1898                         queue->led_off_start_frame_id, queue->led_on_num_frames);
   1899             } else {
   1900                 queue->expected_frame_id =
   1901                 good_frame_idx_range.min_frame_idx;
   1902                 CDBG("%s: [ZSL Retro]No flash, expected frame id = %d ",
   1903                         __func__, queue->expected_frame_id);
   1904             }
   1905         } else if (ch_obj->need3ABracketing && !is_good_frame_idx_range_valid) {
   1906                /* Flush unwanted frames */
   1907                mm_channel_superbuf_flush_matched(ch_obj, queue);
   1908                queue->expected_frame_id += max_future_frame_offset;
   1909         }
   1910         if (ch_obj->isFlashBracketingEnabled &&
   1911             is_good_frame_idx_range_valid) {
   1912             /* Flash bracketing needs two frames, with & without led flash.
   1913             * in valid range min frame is with led flash and max frame is
   1914             * without led flash */
   1915             queue->expected_frame_id =
   1916                 good_frame_idx_range.min_frame_idx;
   1917             /* max frame is without led flash */
   1918             queue->expected_frame_id_without_led =
   1919                 good_frame_idx_range.max_frame_idx;
   1920 
   1921         } else if (is_good_frame_idx_range_valid) {
   1922              if (good_frame_idx_range.min_frame_idx >
   1923                  queue->expected_frame_id) {
   1924                  CDBG_HIGH("%s: min_frame_idx %d is greater than expected_frame_id %d",
   1925                      __func__, good_frame_idx_range.min_frame_idx,
   1926                      queue->expected_frame_id);
   1927              }
   1928              queue->expected_frame_id =
   1929                  good_frame_idx_range.min_frame_idx;
   1930              ch_obj->need3ABracketing = FALSE;
   1931         }
   1932 
   1933        if((ch_obj->burstSnapNum > 1) && (ch_obj->needLEDFlash == TRUE) &&
   1934                !ch_obj->isFlashBracketingEnabled) {
   1935          if((buf_info->frame_idx >= queue->led_off_start_frame_id)
   1936             &&  !queue->once) {
   1937             CDBG("%s: [ZSL Retro]Burst snap num = %d ",
   1938             __func__,  ch_obj->burstSnapNum);
   1939             // Skip frames from LED OFF frame to get a good frame
   1940             queue->expected_frame_id = queue->led_off_start_frame_id + queue->frame_skip_count;
   1941             queue->once = 1;
   1942             ch_obj->stopZslSnapshot = 1;
   1943             CDBG("%s:[ZSL Retro]Reached max led on frames = %d , expected id = %d",
   1944             __func__,  buf_info->frame_idx, queue->expected_frame_id);
   1945          }
   1946        }
   1947     }
   1948 end:
   1949     return rc;
   1950 }
   1951 
   1952 /*===========================================================================
   1953  * FUNCTION   : mm_channel_superbuf_comp_and_enqueue
   1954  *
   1955  * DESCRIPTION: implementation for matching logic for superbuf
   1956  *
   1957  * PARAMETERS :
   1958  *   @ch_obj  : channel object
   1959  *   @queue   : superbuf queue
   1960  *   @buf_info: new buffer from stream
   1961  *
   1962  * RETURN     : int32_t type of status
   1963  *              0  -- success
   1964  *              -1 -- failure
   1965  *==========================================================================*/
   1966 int32_t mm_channel_superbuf_comp_and_enqueue(
   1967                         mm_channel_t* ch_obj,
   1968                         mm_channel_queue_t *queue,
   1969                         mm_camera_buf_info_t *buf_info)
   1970 {
   1971     cam_node_t* node = NULL;
   1972     struct cam_list *head = NULL;
   1973     struct cam_list *pos = NULL;
   1974     mm_channel_queue_node_t* super_buf = NULL;
   1975     uint8_t buf_s_idx, i, found_super_buf, unmatched_bundles;
   1976     struct cam_list *last_buf, *insert_before_buf;
   1977 
   1978     CDBG("%s: E", __func__);
   1979     for (buf_s_idx = 0; buf_s_idx < queue->num_streams; buf_s_idx++) {
   1980         if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) {
   1981             break;
   1982         }
   1983     }
   1984     if (buf_s_idx == queue->num_streams) {
   1985         CDBG_ERROR("%s: buf from stream (%d) not bundled", __func__, buf_info->stream_id);
   1986         return -1;
   1987     }
   1988 
   1989     if (mm_channel_handle_metadata(ch_obj, queue, buf_info) < 0) {
   1990         mm_channel_qbuf(ch_obj, buf_info->buf);
   1991         return -1;
   1992     }
   1993    #if 0
   1994    mm_stream_t* stream_obj = mm_channel_util_get_stream_by_handler(ch_obj,
   1995                buf_info->stream_id);
   1996 
   1997    if (CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) {
   1998     const metadata_buffer_t *metadata;
   1999     metadata = (const metadata_buffer_t *)buf_info->buf->buffer;
   2000     int32_t is_meta_valid = *((int32_t*)POINTER_OF(CAM_INTF_META_VALID, metadata));
   2001     CDBG("%s: meta_valid: %d\n", __func__, is_meta_valid);
   2002     if (!is_meta_valid) {
   2003       mm_channel_qbuf(ch_obj, buf_info->buf);
   2004       return 0;
   2005     }
   2006    }
   2007    #endif
   2008     if (mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx,
   2009                                             queue->expected_frame_id) < 0) {
   2010         /* incoming buf is older than expected buf id, will discard it */
   2011         mm_channel_qbuf(ch_obj, buf_info->buf);
   2012         return 0;
   2013     }
   2014 
   2015     if (MM_CAMERA_SUPER_BUF_PRIORITY_NORMAL != queue->attr.priority) {
   2016         /* TODO */
   2017         /* need to decide if we want to queue the frame based on focus or exposure
   2018          * if frame not to be queued, we need to qbuf it back */
   2019     }
   2020 
   2021     /* comp */
   2022     pthread_mutex_lock(&queue->que.lock);
   2023     head = &queue->que.head.list;
   2024     /* get the last one in the queue which is possibly having no matching */
   2025     pos = head->next;
   2026 
   2027     found_super_buf = 0;
   2028     unmatched_bundles = 0;
   2029     last_buf = NULL;
   2030     insert_before_buf = NULL;
   2031     while (pos != head) {
   2032         node = member_of(pos, cam_node_t, list);
   2033         super_buf = (mm_channel_queue_node_t*)node->data;
   2034         if (NULL != super_buf) {
   2035             if (super_buf->matched) {
   2036                 /* find a matched super buf, move to next one */
   2037                 pos = pos->next;
   2038                 continue;
   2039             } else if ( buf_info->frame_idx == super_buf->frame_idx ) {
   2040                 /* have an unmatched super buf that matches our frame idx,
   2041                  *  break the loop */
   2042                 found_super_buf = 1;
   2043                 break;
   2044             } else {
   2045                 unmatched_bundles++;
   2046                 if ( NULL == last_buf ) {
   2047                     if ( super_buf->frame_idx < buf_info->frame_idx ) {
   2048                         last_buf = pos;
   2049                     }
   2050                 }
   2051                 if ( NULL == insert_before_buf ) {
   2052                     if ( super_buf->frame_idx > buf_info->frame_idx ) {
   2053                         insert_before_buf = pos;
   2054                     }
   2055                 }
   2056                 pos = pos->next;
   2057             }
   2058         }
   2059     }
   2060     if ( found_super_buf ) {
   2061             super_buf->super_buf[buf_s_idx] = *buf_info;
   2062 
   2063             /* check if superbuf is all matched */
   2064             super_buf->matched = 1;
   2065             for (i=0; i < super_buf->num_of_bufs; i++) {
   2066                 if (super_buf->super_buf[i].frame_idx == 0) {
   2067                     super_buf->matched = 0;
   2068                     break;
   2069                 }
   2070             }
   2071 
   2072             if (super_buf->matched) {
   2073                 if(ch_obj->isFlashBracketingEnabled) {
   2074                    queue->expected_frame_id =
   2075                        queue->expected_frame_id_without_led;
   2076                    if (buf_info->frame_idx >=
   2077                            queue->expected_frame_id_without_led) {
   2078                        ch_obj->isFlashBracketingEnabled = FALSE;
   2079                    }
   2080                 } else {
   2081                    queue->expected_frame_id = buf_info->frame_idx
   2082                                               + queue->attr.post_frame_skip;
   2083                 }
   2084                 CDBG("%s: curr = %d, skip = %d , Expected Frame ID: %d",
   2085                         __func__, buf_info->frame_idx,
   2086                         queue->attr.post_frame_skip, queue->expected_frame_id);
   2087 
   2088                 queue->match_cnt++;
   2089                 /* Any older unmatched buffer need to be released */
   2090                 if ( last_buf ) {
   2091                     while ( last_buf != pos ) {
   2092                         node = member_of(last_buf, cam_node_t, list);
   2093                         super_buf = (mm_channel_queue_node_t*)node->data;
   2094                         if (NULL != super_buf) {
   2095                             for (i=0; i<super_buf->num_of_bufs; i++) {
   2096                                 if (super_buf->super_buf[i].frame_idx != 0) {
   2097                                         mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   2098                                 }
   2099                             }
   2100                             queue->que.size--;
   2101                             last_buf = last_buf->next;
   2102                             cam_list_del_node(&node->list);
   2103                             free(node);
   2104                             free(super_buf);
   2105                         } else {
   2106                             CDBG_ERROR(" %s : Invalid superbuf in queue!", __func__);
   2107                             break;
   2108                         }
   2109                     }
   2110                 }
   2111             }
   2112     } else {
   2113         if (  ( queue->attr.max_unmatched_frames < unmatched_bundles ) &&
   2114               ( NULL == last_buf ) ) {
   2115             /* incoming frame is older than the last bundled one */
   2116             mm_channel_qbuf(ch_obj, buf_info->buf);
   2117         } else {
   2118             if ( queue->attr.max_unmatched_frames < unmatched_bundles ) {
   2119                 /* release the oldest bundled superbuf */
   2120                 node = member_of(last_buf, cam_node_t, list);
   2121                 super_buf = (mm_channel_queue_node_t*)node->data;
   2122                 for (i=0; i<super_buf->num_of_bufs; i++) {
   2123                     if (super_buf->super_buf[i].frame_idx != 0) {
   2124                             mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   2125                     }
   2126                 }
   2127                 queue->que.size--;
   2128                 node = member_of(last_buf, cam_node_t, list);
   2129                 cam_list_del_node(&node->list);
   2130                 free(node);
   2131                 free(super_buf);
   2132             }
   2133             /* insert the new frame at the appropriate position. */
   2134 
   2135             mm_channel_queue_node_t *new_buf = NULL;
   2136             cam_node_t* new_node = NULL;
   2137 
   2138             new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t));
   2139             new_node = (cam_node_t*)malloc(sizeof(cam_node_t));
   2140             if (NULL != new_buf && NULL != new_node) {
   2141                 memset(new_buf, 0, sizeof(mm_channel_queue_node_t));
   2142                 memset(new_node, 0, sizeof(cam_node_t));
   2143                 new_node->data = (void *)new_buf;
   2144                 new_buf->num_of_bufs = queue->num_streams;
   2145                 new_buf->super_buf[buf_s_idx] = *buf_info;
   2146                 new_buf->frame_idx = buf_info->frame_idx;
   2147                 /* enqueue */
   2148                 if ( insert_before_buf ) {
   2149                     cam_list_insert_before_node(&new_node->list, insert_before_buf);
   2150                 } else {
   2151                     cam_list_add_tail_node(&new_node->list, &queue->que.head.list);
   2152                 }
   2153                 queue->que.size++;
   2154 
   2155                 if(queue->num_streams == 1) {
   2156                     new_buf->matched = 1;
   2157 
   2158                     queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
   2159                     queue->match_cnt++;
   2160                 }
   2161             } else {
   2162                 /* No memory */
   2163                 if (NULL != new_buf) {
   2164                     free(new_buf);
   2165                 }
   2166                 if (NULL != new_node) {
   2167                     free(new_node);
   2168                 }
   2169                 /* qbuf the new buf since we cannot enqueue */
   2170                 mm_channel_qbuf(ch_obj, buf_info->buf);
   2171             }
   2172         }
   2173     }
   2174 
   2175     pthread_mutex_unlock(&queue->que.lock);
   2176     CDBG("%s: X", __func__);
   2177     return 0;
   2178 }
   2179 
   2180 /*===========================================================================
   2181  * FUNCTION   : mm_channel_superbuf_dequeue_internal
   2182  *
   2183  * DESCRIPTION: internal implementation for dequeue from the superbuf queue
   2184  *
   2185  * PARAMETERS :
   2186  *   @queue   : superbuf queue
   2187  *   @matched_only : if dequeued buf should be matched
   2188  *
   2189  * RETURN     : ptr to a node from superbuf queue
   2190  *==========================================================================*/
   2191 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue,
   2192                                                               uint8_t matched_only)
   2193 {
   2194     cam_node_t* node = NULL;
   2195     struct cam_list *head = NULL;
   2196     struct cam_list *pos = NULL;
   2197     mm_channel_queue_node_t* super_buf = NULL;
   2198 
   2199     head = &queue->que.head.list;
   2200     pos = head->next;
   2201     if (pos != head) {
   2202         /* get the first node */
   2203         node = member_of(pos, cam_node_t, list);
   2204         super_buf = (mm_channel_queue_node_t*)node->data;
   2205         if ( (NULL != super_buf) &&
   2206              (matched_only == TRUE) &&
   2207              (super_buf->matched == FALSE) ) {
   2208             /* require to dequeue matched frame only, but this superbuf is not matched,
   2209                simply set return ptr to NULL */
   2210             super_buf = NULL;
   2211         }
   2212         if (NULL != super_buf) {
   2213             /* remove from the queue */
   2214             cam_list_del_node(&node->list);
   2215             queue->que.size--;
   2216             if (super_buf->matched == TRUE) {
   2217                 queue->match_cnt--;
   2218             }
   2219             free(node);
   2220         }
   2221     }
   2222 
   2223     return super_buf;
   2224 }
   2225 
   2226 /*===========================================================================
   2227  * FUNCTION   : mm_channel_superbuf_dequeue
   2228  *
   2229  * DESCRIPTION: dequeue from the superbuf queue
   2230  *
   2231  * PARAMETERS :
   2232  *   @queue   : superbuf queue
   2233  *
   2234  * RETURN     : ptr to a node from superbuf queue
   2235  *==========================================================================*/
   2236 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue)
   2237 {
   2238     mm_channel_queue_node_t* super_buf = NULL;
   2239 
   2240     pthread_mutex_lock(&queue->que.lock);
   2241     super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
   2242     pthread_mutex_unlock(&queue->que.lock);
   2243 
   2244     return super_buf;
   2245 }
   2246 
   2247 /*===========================================================================
   2248  * FUNCTION   : mm_channel_superbuf_bufdone_overflow
   2249  *
   2250  * DESCRIPTION: keep superbuf queue no larger than watermark set by upper layer
   2251  *              via channel attribute
   2252  *
   2253  * PARAMETERS :
   2254  *   @my_obj  : channel object
   2255  *   @queue   : superbuf queue
   2256  *
   2257  * RETURN     : int32_t type of status
   2258  *              0  -- success
   2259  *              -1 -- failure
   2260  *==========================================================================*/
   2261 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
   2262                                              mm_channel_queue_t * queue)
   2263 {
   2264     int32_t rc = 0, i;
   2265     mm_channel_queue_node_t* super_buf = NULL;
   2266     if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
   2267         /* for continuous streaming mode, no overflow is needed */
   2268         return 0;
   2269     }
   2270 
   2271     CDBG("%s: before match_cnt=%d, water_mark=%d",
   2272          __func__, queue->match_cnt, queue->attr.water_mark);
   2273     /* bufdone overflowed bufs */
   2274     pthread_mutex_lock(&queue->que.lock);
   2275     while (queue->match_cnt > queue->attr.water_mark) {
   2276         super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
   2277         if (NULL != super_buf) {
   2278             for (i=0; i<super_buf->num_of_bufs; i++) {
   2279                 if (NULL != super_buf->super_buf[i].buf) {
   2280                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   2281                 }
   2282             }
   2283             free(super_buf);
   2284         }
   2285     }
   2286     pthread_mutex_unlock(&queue->que.lock);
   2287     CDBG("%s: after match_cnt=%d, water_mark=%d",
   2288          __func__, queue->match_cnt, queue->attr.water_mark);
   2289 
   2290     return rc;
   2291 }
   2292 
   2293 /*===========================================================================
   2294  * FUNCTION   : mm_channel_superbuf_skip
   2295  *
   2296  * DESCRIPTION: depends on the lookback configuration of the channel attribute,
   2297  *              unwanted superbufs will be removed from the superbuf queue.
   2298  *
   2299  * PARAMETERS :
   2300  *   @my_obj  : channel object
   2301  *   @queue   : superbuf queue
   2302  *
   2303  * RETURN     : int32_t type of status
   2304  *              0  -- success
   2305  *              -1 -- failure
   2306  *==========================================================================*/
   2307 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
   2308                                  mm_channel_queue_t * queue)
   2309 {
   2310     int32_t rc = 0, i;
   2311     mm_channel_queue_node_t* super_buf = NULL;
   2312     if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
   2313         /* for continuous streaming mode, no skip is needed */
   2314         return 0;
   2315     }
   2316 
   2317     /* bufdone overflowed bufs */
   2318     pthread_mutex_lock(&queue->que.lock);
   2319     while (queue->match_cnt > queue->attr.look_back) {
   2320         super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
   2321         if (NULL != super_buf) {
   2322             for (i=0; i<super_buf->num_of_bufs; i++) {
   2323                 if (NULL != super_buf->super_buf[i].buf) {
   2324                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   2325                 }
   2326             }
   2327             free(super_buf);
   2328         }
   2329     }
   2330     pthread_mutex_unlock(&queue->que.lock);
   2331 
   2332     return rc;
   2333 }
   2334 
   2335 /*===========================================================================
   2336  * FUNCTION   : mm_channel_superbuf_flush
   2337  *
   2338  * DESCRIPTION: flush the superbuf queue.
   2339  *
   2340  * PARAMETERS :
   2341  *   @my_obj  : channel object
   2342  *   @queue   : superbuf queue
   2343  *
   2344  * RETURN     : int32_t type of status
   2345  *              0  -- success
   2346  *              -1 -- failure
   2347  *==========================================================================*/
   2348 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj,
   2349                                   mm_channel_queue_t * queue)
   2350 {
   2351     int32_t rc = 0, i;
   2352     mm_channel_queue_node_t* super_buf = NULL;
   2353 
   2354     /* bufdone bufs */
   2355     pthread_mutex_lock(&queue->que.lock);
   2356     super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE);
   2357     while (super_buf != NULL) {
   2358         for (i=0; i<super_buf->num_of_bufs; i++) {
   2359             if (NULL != super_buf->super_buf[i].buf) {
   2360                 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   2361             }
   2362         }
   2363         free(super_buf);
   2364         super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE);
   2365     }
   2366     pthread_mutex_unlock(&queue->que.lock);
   2367 
   2368     return rc;
   2369 }
   2370 
   2371 /*===========================================================================
   2372  * FUNCTION   : mm_channel_proc_general_cmd
   2373  *
   2374  * DESCRIPTION: process general command
   2375  *
   2376  * PARAMETERS :
   2377  *   @my_obj  : channel object
   2378  *   @notify_mode : notification mode
   2379  *
   2380  * RETURN     : int32_t type of status
   2381  *              0  -- success
   2382  *              -1 -- failure
   2383  *==========================================================================*/
   2384 int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj,
   2385                                       mm_camera_generic_cmd_t *p_gen_cmd)
   2386 {
   2387     CDBG("%s: E",__func__);
   2388     int32_t rc = 0;
   2389     mm_camera_cmdcb_t* node = NULL;
   2390 
   2391     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   2392     if (NULL != node) {
   2393         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   2394         node->u.gen_cmd = *p_gen_cmd;
   2395         node->cmd_type = MM_CAMERA_CMD_TYPE_GENERAL;
   2396 
   2397         /* enqueue to cmd thread */
   2398         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   2399 
   2400         /* wake up cmd thread */
   2401         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   2402     } else {
   2403         CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
   2404         rc = -1;
   2405     }
   2406     CDBG("%s: X",__func__);
   2407 
   2408     return rc;
   2409 }
   2410 
   2411 /*===========================================================================
   2412  * FUNCTION   : mm_channel_superbuf_flush_matched
   2413  *
   2414  * DESCRIPTION: flush matched buffers from the superbuf queue.
   2415  *
   2416  * PARAMETERS :
   2417  *   @my_obj  : channel object
   2418  *   @queue   : superbuf queue
   2419  *
   2420  * RETURN     : int32_t type of status
   2421  *              0  -- success
   2422  *              -1 -- failure
   2423  *==========================================================================*/
   2424 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj,
   2425                                   mm_channel_queue_t * queue)
   2426 {
   2427     int32_t rc = 0, i;
   2428     mm_channel_queue_node_t* super_buf = NULL;
   2429 
   2430     /* bufdone bufs */
   2431     pthread_mutex_lock(&queue->que.lock);
   2432     super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
   2433     while (super_buf != NULL) {
   2434         for (i=0; i<super_buf->num_of_bufs; i++) {
   2435             if (NULL != super_buf->super_buf[i].buf) {
   2436                 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   2437             }
   2438         }
   2439         free(super_buf);
   2440         super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
   2441     }
   2442     pthread_mutex_unlock(&queue->que.lock);
   2443 
   2444     return rc;
   2445 }
   2446