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