Home | History | Annotate | Download | only in src
      1 /* Copyright (c) 2012-2016, 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 // System dependencies
     31 #include <pthread.h>
     32 #include <fcntl.h>
     33 
     34 // Camera dependencies
     35 #include "cam_semaphore.h"
     36 #include "mm_camera_dbg.h"
     37 #include "mm_camera_interface.h"
     38 #include "mm_camera.h"
     39 #include "cam_cond.h"
     40 
     41 extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler);
     42 extern mm_channel_t * mm_camera_util_get_channel_by_handler(mm_camera_obj_t * cam_obj,
     43                                                             uint32_t handler);
     44 /* Static frame sync info used between different camera channels*/
     45 static mm_channel_frame_sync_info_t fs = { .num_cam =0, .pos = 0};
     46 /* Frame sync info access lock */
     47 static pthread_mutex_t fs_lock = PTHREAD_MUTEX_INITIALIZER;
     48 
     49 /* internal function declare goes here */
     50 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
     51                         mm_camera_buf_def_t *buf);
     52 int32_t mm_channel_cancel_buf(mm_channel_t *my_obj,
     53                         uint32_t stream_id, uint32_t buf_idx);
     54 int32_t mm_channel_init(mm_channel_t *my_obj,
     55                         mm_camera_channel_attr_t *attr,
     56                         mm_camera_buf_notify_t channel_cb,
     57                         void *userdata);
     58 void mm_channel_release(mm_channel_t *my_obj);
     59 uint32_t mm_channel_add_stream(mm_channel_t *my_obj);
     60 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
     61                                    uint32_t stream_id);
     62 uint32_t mm_channel_link_stream(mm_channel_t *my_obj,
     63         mm_camera_stream_link_t *stream_link);
     64 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
     65                                  uint32_t stream_id,
     66                                  mm_camera_stream_config_t *config);
     67 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj,
     68                                    cam_bundle_config_t *bundle_info);
     69 int32_t mm_channel_start(mm_channel_t *my_obj);
     70 int32_t mm_channel_stop(mm_channel_t *my_obj);
     71 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj,
     72         mm_camera_req_buf_t *buf);
     73 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj);
     74 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj,
     75                                          uint32_t frame_idx,
     76                                          cam_stream_type_t stream_type);
     77 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj,
     78                                       mm_camera_super_buf_notify_mode_t notify_mode);
     79 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj);
     80 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj);
     81 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj,
     82         mm_channel_queue_t * queue, cam_stream_type_t cam_type);
     83 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
     84                                    mm_evt_paylod_set_get_stream_parms_t *payload);
     85 int32_t mm_channel_get_queued_buf_count(mm_channel_t *my_obj,
     86         uint32_t stream_id);
     87 
     88 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
     89                                    mm_evt_paylod_set_get_stream_parms_t *payload);
     90 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
     91                                     mm_evt_paylod_do_stream_action_t *payload);
     92 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
     93                                   cam_buf_map_type *payload);
     94 int32_t mm_channel_map_stream_bufs(mm_channel_t *my_obj,
     95                                    cam_buf_map_type_list *payload);
     96 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
     97                                     cam_buf_unmap_type *payload);
     98 
     99 /* state machine function declare */
    100 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
    101                           mm_channel_evt_type_t evt,
    102                           void * in_val,
    103                           void * out_val);
    104 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
    105                           mm_channel_evt_type_t evt,
    106                           void * in_val,
    107                           void * out_val);
    108 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
    109                           mm_channel_evt_type_t evt,
    110                           void * in_val,
    111                           void * out_val);
    112 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
    113                           mm_channel_evt_type_t evt,
    114                           void * in_val,
    115                           void * out_val);
    116 
    117 /* channel super queue functions */
    118 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue);
    119 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue);
    120 int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj,
    121                                              mm_channel_queue_t * queue,
    122                                              mm_camera_buf_info_t *buf);
    123 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(
    124         mm_channel_queue_t * queue, mm_channel_t *ch_obj);
    125 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t *my_obj,
    126                                              mm_channel_queue_t *queue);
    127 int32_t mm_channel_superbuf_skip(mm_channel_t *my_obj,
    128                                  mm_channel_queue_t *queue);
    129 
    130 static int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj,
    131                                            mm_camera_generic_cmd_t *p_gen_cmd);
    132 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj,
    133                                           mm_channel_queue_t * queue);
    134 
    135 /* Start of Frame Sync util methods */
    136 void mm_frame_sync_reset();
    137 int32_t mm_frame_sync_register_channel(mm_channel_t *ch_obj);
    138 int32_t mm_frame_sync_unregister_channel(mm_channel_t *ch_obj);
    139 int32_t mm_frame_sync_add(uint32_t frame_id, mm_channel_t *ch_obj);
    140 int32_t mm_frame_sync_remove(uint32_t frame_id);
    141 uint32_t mm_frame_sync_find_matched(uint8_t oldest);
    142 int8_t mm_frame_sync_find_frame_index(uint32_t frame_id);
    143 void mm_frame_sync_lock_queues();
    144 void mm_frame_sync_unlock_queues();
    145 void mm_channel_node_qbuf(mm_channel_t *ch_obj, mm_channel_queue_node_t *node);
    146 /* End of Frame Sync Util methods */
    147 void mm_channel_send_super_buf(mm_channel_node_info_t *info);
    148 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_frame_internal(
    149         mm_channel_queue_t * queue, uint32_t frame_idx);
    150 
    151 /*===========================================================================
    152  * FUNCTION   : mm_channel_util_get_stream_by_handler
    153  *
    154  * DESCRIPTION: utility function to get a stream object from its handle
    155  *
    156  * PARAMETERS :
    157  *   @cam_obj: ptr to a channel object
    158  *   @handler: stream handle
    159  *
    160  * RETURN     : ptr to a stream object.
    161  *              NULL if failed.
    162  *==========================================================================*/
    163 mm_stream_t * mm_channel_util_get_stream_by_handler(
    164                                     mm_channel_t * ch_obj,
    165                                     uint32_t handler)
    166 {
    167     int i;
    168     mm_stream_t *s_obj = NULL;
    169     for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
    170         if ((MM_STREAM_STATE_NOTUSED != ch_obj->streams[i].state) &&
    171             (handler == ch_obj->streams[i].my_hdl)) {
    172             s_obj = &ch_obj->streams[i];
    173             break;
    174         }
    175     }
    176     return s_obj;
    177 }
    178 
    179 /*===========================================================================
    180  * FUNCTION   : mm_channel_dispatch_super_buf
    181  *
    182  * DESCRIPTION: dispatch super buffer of bundle to registered user
    183  *
    184  * PARAMETERS :
    185  *   @cmd_cb  : ptr storing matched super buf information
    186  *   @userdata: user data ptr
    187  *
    188  * RETURN     : none
    189  *==========================================================================*/
    190 static void mm_channel_dispatch_super_buf(mm_camera_cmdcb_t *cmd_cb,
    191                                           void* user_data)
    192 {
    193     mm_channel_t * my_obj = (mm_channel_t *)user_data;
    194 
    195     if (NULL == my_obj) {
    196         return;
    197     }
    198 
    199     if (MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB != cmd_cb->cmd_type) {
    200         LOGE("Wrong cmd_type (%d) for super buf dataCB",
    201                     cmd_cb->cmd_type);
    202         return;
    203     }
    204 
    205     if (my_obj->bundle.super_buf_notify_cb) {
    206         my_obj->bundle.super_buf_notify_cb(&cmd_cb->u.superbuf, my_obj->bundle.user_data);
    207     }
    208 }
    209 
    210 /*===========================================================================
    211  * FUNCTION   : mm_channel_process_stream_buf
    212  *
    213  * DESCRIPTION: handle incoming buffer from stream in a bundle. In this function,
    214  *              matching logic will be performed on incoming stream frames.
    215  *              Will depends on the bundle attribute, either storing matched frames
    216  *              in the superbuf queue, or sending matched superbuf frames to upper
    217  *              layer through registered callback.
    218  *
    219  * PARAMETERS :
    220  *   @cmd_cb  : ptr storing matched super buf information
    221  *   @userdata: user data ptr
    222  *
    223  * RETURN     : none
    224  *==========================================================================*/
    225 static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,
    226                                           void *user_data)
    227 {
    228     mm_camera_super_buf_notify_mode_t notify_mode;
    229     mm_channel_queue_node_t *node = NULL;
    230     mm_channel_t *ch_obj = (mm_channel_t *)user_data;
    231     uint32_t i = 0;
    232     /* Set expected frame id to a future frame idx, large enough to wait
    233     * for good_frame_idx_range, and small enough to still capture an image */
    234     uint8_t needStartZSL = FALSE;
    235 
    236     if (NULL == ch_obj) {
    237         return;
    238     }
    239     if (MM_CAMERA_CMD_TYPE_DATA_CB  == cmd_cb->cmd_type) {
    240         /* comp_and_enqueue */
    241         mm_channel_superbuf_comp_and_enqueue(
    242                         ch_obj,
    243                         &ch_obj->bundle.superbuf_queue,
    244                         &cmd_cb->u.buf);
    245     } else if (MM_CAMERA_CMD_TYPE_REQ_DATA_CB  == cmd_cb->cmd_type) {
    246         /* skip frames if needed */
    247         ch_obj->pending_cnt = cmd_cb->u.req_buf.num_buf_requested;
    248         ch_obj->pending_retro_cnt = cmd_cb->u.req_buf.num_retro_buf_requested;
    249         ch_obj->req_type = cmd_cb->u.req_buf.type;
    250         ch_obj->bWaitForPrepSnapshotDone = 0;
    251 
    252         LOGH("pending cnt (%d), retro count (%d)"
    253                 "req_type (%d) is_primary (%d)",
    254                  ch_obj->pending_cnt, ch_obj->pending_retro_cnt,
    255                 ch_obj->req_type, cmd_cb->u.req_buf.primary_only);
    256         if (!ch_obj->pending_cnt || (ch_obj->pending_retro_cnt > ch_obj->pending_cnt)) {
    257           ch_obj->pending_retro_cnt = ch_obj->pending_cnt;
    258         }
    259         if (ch_obj->pending_retro_cnt > 0) {
    260           LOGL("Resetting need Led Flash!!!");
    261           ch_obj->needLEDFlash = 0;
    262         }
    263         ch_obj->stopZslSnapshot = 0;
    264         ch_obj->unLockAEC = 0;
    265 
    266         mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue);
    267 
    268     } else if (MM_CAMERA_CMD_TYPE_START_ZSL == cmd_cb->cmd_type) {
    269             ch_obj->manualZSLSnapshot = TRUE;
    270             mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
    271     } else if (MM_CAMERA_CMD_TYPE_STOP_ZSL == cmd_cb->cmd_type) {
    272             ch_obj->manualZSLSnapshot = FALSE;
    273             mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
    274     } else if (MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY == cmd_cb->cmd_type) {
    275            ch_obj->bundle.superbuf_queue.attr.notify_mode = cmd_cb->u.notify_mode;
    276     } else if (MM_CAMERA_CMD_TYPE_FLUSH_QUEUE  == cmd_cb->cmd_type) {
    277         ch_obj->bundle.superbuf_queue.expected_frame_id = cmd_cb->u.flush_cmd.frame_idx;
    278         mm_channel_superbuf_flush(ch_obj,
    279                 &ch_obj->bundle.superbuf_queue, cmd_cb->u.flush_cmd.stream_type);
    280         cam_sem_post(&(ch_obj->cmd_thread.sync_sem));
    281         return;
    282     } else if (MM_CAMERA_CMD_TYPE_GENERAL == cmd_cb->cmd_type) {
    283         LOGH("MM_CAMERA_CMD_TYPE_GENERAL");
    284         switch (cmd_cb->u.gen_cmd.type) {
    285             case MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING:
    286             case MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING: {
    287                 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
    288                 LOGI("MM_CAMERA_GENERIC_CMDTYPE_AF_BRACKETING %u",
    289                       start);
    290                 mm_channel_superbuf_flush(ch_obj,
    291                         &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
    292 
    293                 if (start) {
    294                     LOGH("need AE bracketing, start zsl snapshot");
    295                     ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_WAIT_GOOD_FRAME_IDX;
    296                 } else {
    297                     ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF;
    298                 }
    299             }
    300                 break;
    301             case MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING: {
    302                 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
    303                 LOGI("MM_CAMERA_GENERIC_CMDTYPE_FLASH_BRACKETING %u",
    304                       start);
    305                 mm_channel_superbuf_flush(ch_obj,
    306                         &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
    307 
    308                 if (start) {
    309                     LOGH("need flash bracketing");
    310                     ch_obj->isFlashBracketingEnabled = TRUE;
    311                 } else {
    312                     ch_obj->isFlashBracketingEnabled = FALSE;
    313                 }
    314             }
    315                 break;
    316             case MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X: {
    317                 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
    318                 LOGI("MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X %u",
    319                       start);
    320                 mm_channel_superbuf_flush(ch_obj,
    321                         &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
    322 
    323                 if (start) {
    324                     LOGH("need zoom 1x frame");
    325                     ch_obj->isZoom1xFrameRequested = TRUE;
    326                 } else {
    327                     ch_obj->isZoom1xFrameRequested = FALSE;
    328                 }
    329             }
    330                 break;
    331             case MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING: {
    332                 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
    333                 LOGI("MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING %u num_batch = %d",
    334                       start, cmd_cb->u.gen_cmd.frame_config.num_batch);
    335 
    336                 if (start) {
    337                     memset(&ch_obj->frameConfig, 0, sizeof(cam_capture_frame_config_t));
    338                     for (i = 0; i < cmd_cb->u.gen_cmd.frame_config.num_batch; i++) {
    339                         if (cmd_cb->u.gen_cmd.frame_config.configs[i].type
    340                                 != CAM_CAPTURE_RESET) {
    341                             ch_obj->frameConfig.configs[
    342                                     ch_obj->frameConfig.num_batch] =
    343                                     cmd_cb->u.gen_cmd.frame_config.configs[i];
    344                             ch_obj->frameConfig.num_batch++;
    345                             LOGH("capture setting frame = %d type = %d",
    346                                     i,ch_obj->frameConfig.configs[
    347                                     ch_obj->frameConfig.num_batch].type);
    348                         }
    349                     }
    350                     LOGD("Capture setting Batch Count %d",
    351                               ch_obj->frameConfig.num_batch);
    352                     ch_obj->isConfigCapture = TRUE;
    353                 } else {
    354                     ch_obj->isConfigCapture = FALSE;
    355                     memset(&ch_obj->frameConfig, 0, sizeof(cam_capture_frame_config_t));
    356                 }
    357                 ch_obj->cur_capture_idx = 0;
    358                 memset(ch_obj->capture_frame_id, 0, sizeof(uint8_t) * MAX_CAPTURE_BATCH_NUM);
    359                 break;
    360             }
    361             default:
    362                 LOGE("Error: Invalid command");
    363                 break;
    364         }
    365     }
    366     notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode;
    367 
    368     /*Handle use case which does not need start ZSL even in unified case*/
    369     if ((ch_obj->pending_cnt > 0)
    370             && (ch_obj->isConfigCapture)
    371             && (ch_obj->manualZSLSnapshot == FALSE)
    372             && (ch_obj->startZSlSnapshotCalled == FALSE)) {
    373         needStartZSL = TRUE;
    374         for (i = ch_obj->cur_capture_idx;
    375                 i < ch_obj->frameConfig.num_batch;
    376                 i++) {
    377             cam_capture_type type = ch_obj->frameConfig.configs[i].type;
    378             if (((type == CAM_CAPTURE_FLASH) && (!ch_obj->needLEDFlash))
    379                     || ((type == CAM_CAPTURE_LOW_LIGHT) && (!ch_obj->needLowLightZSL))) {
    380                 /*For flash and low light capture, start ZSL is triggered only if needed*/
    381                 needStartZSL = FALSE;
    382                 break;
    383             }
    384         }
    385     }
    386 
    387     if ((ch_obj->isConfigCapture)
    388             && (needStartZSL)) {
    389         for (i = ch_obj->cur_capture_idx;
    390                 i < ch_obj->frameConfig.num_batch;
    391                 i++) {
    392             ch_obj->capture_frame_id[i] =
    393                     ch_obj->bundle.superbuf_queue.expected_frame_id
    394                     + MM_CAMERA_MAX_FUTURE_FRAME_WAIT;
    395         }
    396 
    397         /* Need to Flush the queue and trigger frame config */
    398         mm_channel_superbuf_flush(ch_obj,
    399                 &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
    400         LOGI("TRIGGER Start ZSL");
    401         mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
    402         ch_obj->startZSlSnapshotCalled = TRUE;
    403         ch_obj->burstSnapNum = ch_obj->pending_cnt;
    404         ch_obj->bWaitForPrepSnapshotDone = 0;
    405     } else if ((ch_obj->pending_cnt > 0)
    406         && ((ch_obj->needLEDFlash == TRUE) ||
    407         (MM_CHANNEL_BRACKETING_STATE_OFF != ch_obj->bracketingState))
    408         && (ch_obj->manualZSLSnapshot == FALSE)
    409         && ch_obj->startZSlSnapshotCalled == FALSE) {
    410 
    411         LOGI("TRIGGER Start ZSL for Flash");
    412         mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
    413         ch_obj->startZSlSnapshotCalled = TRUE;
    414         ch_obj->burstSnapNum = ch_obj->pending_cnt;
    415         ch_obj->bWaitForPrepSnapshotDone = 0;
    416     } else if (((ch_obj->pending_cnt == 0) || (ch_obj->stopZslSnapshot == 1))
    417             && (ch_obj->manualZSLSnapshot == FALSE)
    418             && (ch_obj->startZSlSnapshotCalled == TRUE)) {
    419         LOGI("TRIGGER Stop ZSL for cancel picture");
    420         mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
    421         // Unlock AEC
    422         ch_obj->startZSlSnapshotCalled = FALSE;
    423         ch_obj->needLEDFlash = FALSE;
    424         ch_obj->burstSnapNum = 0;
    425         ch_obj->stopZslSnapshot = 0;
    426         ch_obj->bWaitForPrepSnapshotDone = 0;
    427         ch_obj->unLockAEC = 1;
    428         ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF;
    429         ch_obj->isConfigCapture = FALSE;
    430     }
    431     /* bufdone for overflowed bufs */
    432     mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue);
    433 
    434     LOGD("Super Buffer received, pending_cnt=%d queue cnt = %d expected = %d",
    435             ch_obj->pending_cnt, ch_obj->bundle.superbuf_queue.match_cnt,
    436             ch_obj->bundle.superbuf_queue.expected_frame_id);
    437 
    438     /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */
    439     while (((ch_obj->pending_cnt > 0) ||
    440              (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode)) &&
    441              (!ch_obj->bWaitForPrepSnapshotDone)) {
    442 
    443         /* dequeue */
    444         mm_channel_node_info_t info;
    445         memset(&info, 0x0, sizeof(info));
    446 
    447         if (ch_obj->req_type == MM_CAMERA_REQ_FRAME_SYNC_BUF) {
    448             // Lock the Queues
    449             mm_frame_sync_lock_queues();
    450             uint32_t match_frame = mm_frame_sync_find_matched(FALSE);
    451             if (match_frame) {
    452                 uint8_t j = 0;
    453                 for (j = 0; j < MAX_NUM_CAMERA_PER_BUNDLE; j++) {
    454                     if (fs.ch_obj[j]) {
    455                         mm_channel_queue_t *ch_queue =
    456                                 &fs.ch_obj[j]->bundle.superbuf_queue;
    457                         if (ch_queue == NULL) {
    458                             LOGW("Channel queue is NULL");
    459                             break;
    460                         }
    461                         node = mm_channel_superbuf_dequeue_frame_internal(
    462                                 ch_queue, match_frame);
    463                         if (node != NULL) {
    464                             info.ch_obj[info.num_nodes] = fs.ch_obj[j];
    465                             info.node[info.num_nodes] = node;
    466                             info.num_nodes++;
    467                             LOGH("Added ch(%p) to node ,num nodes %d",
    468                                      fs.ch_obj[j], info.num_nodes);
    469                         }
    470                     }
    471                 }
    472                 mm_frame_sync_remove(match_frame);
    473                 LOGI("match frame %d", match_frame);
    474                 if (info.num_nodes != fs.num_cam) {
    475                     LOGI("num node %d != num cam (%d) Debug this",
    476                              info.num_nodes, fs.num_cam);
    477                     uint8_t j = 0;
    478                     // free super buffers from various nodes
    479                     for (j = 0; j < info.num_nodes; j++) {
    480                         if (info.node[j]) {
    481                             mm_channel_node_qbuf(info.ch_obj[j], info.node[j]);
    482                             free(info.node[j]);
    483                         }
    484                     }
    485                     // we should not use it as matched dual camera frames
    486                     info.num_nodes = 0;
    487                 }
    488             }
    489             mm_frame_sync_unlock_queues();
    490         } else {
    491            node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue, ch_obj);
    492            if (node != NULL) {
    493                if (ch_obj->isConfigCapture &&
    494                        ((node->frame_idx <
    495                         ch_obj->capture_frame_id[ch_obj->cur_capture_idx]))) {
    496                    uint8_t i;
    497                    LOGD("Not expected super buffer. frameID = %d expected = %d",
    498                            node->frame_idx, ch_obj->capture_frame_id[ch_obj->cur_capture_idx]);
    499                    for (i = 0; i < node->num_of_bufs; i++) {
    500                        mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    501                    }
    502                    free(node);
    503                } else {
    504                    info.num_nodes = 1;
    505                    info.ch_obj[0] = ch_obj;
    506                    info.node[0] = node;
    507                }
    508             }
    509         }
    510         if (info.num_nodes > 0) {
    511             /* decrease pending_cnt */
    512             if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode) {
    513                 ch_obj->pending_cnt--;
    514                 if (ch_obj->pending_retro_cnt > 0) {
    515                   if (ch_obj->pending_retro_cnt == 1) {
    516                     ch_obj->bWaitForPrepSnapshotDone = 1;
    517                   }
    518                   ch_obj->pending_retro_cnt--;
    519                 }
    520 
    521                 if (((ch_obj->pending_cnt == 0) ||
    522                       (ch_obj->stopZslSnapshot == 1)) &&
    523                       (ch_obj->manualZSLSnapshot == FALSE) &&
    524                        ch_obj->startZSlSnapshotCalled == TRUE) {
    525                     LOGI("TRIGGER Stop ZSL. All frame received");
    526                     mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
    527                     ch_obj->startZSlSnapshotCalled = FALSE;
    528                     ch_obj->burstSnapNum = 0;
    529                     ch_obj->stopZslSnapshot = 0;
    530                     ch_obj->unLockAEC = 1;
    531                     ch_obj->needLEDFlash = FALSE;
    532                     ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF;
    533                     ch_obj->isConfigCapture = FALSE;
    534                 }
    535 
    536                 if (ch_obj->isConfigCapture) {
    537                     if (ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames != 0) {
    538                         ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames--;
    539                     } else {
    540                         LOGW("Invalid frame config batch index %d max batch = %d",
    541                                 ch_obj->cur_capture_idx, ch_obj->frameConfig.num_batch);
    542                     }
    543 
    544                     if (ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames == 0) {
    545                         //Received all frames for current batch
    546                         ch_obj->cur_capture_idx++;
    547                         ch_obj->bundle.superbuf_queue.expected_frame_id =
    548                                 ch_obj->capture_frame_id[ch_obj->cur_capture_idx];
    549                         ch_obj->bundle.superbuf_queue.good_frame_id =
    550                                 ch_obj->capture_frame_id[ch_obj->cur_capture_idx];
    551                     } else {
    552                         LOGH("Need %d frames more for batch %d",
    553                                 ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames,
    554                                 ch_obj->cur_capture_idx);
    555                     }
    556                 }
    557             }
    558             /* dispatch superbuf */
    559             mm_channel_send_super_buf(&info);
    560         } else {
    561             /* no superbuf avail, break the loop */
    562             break;
    563         }
    564     }
    565 }
    566 
    567 /*===========================================================================
    568  * FUNCTION   : mm_channel_send_super_buf
    569  *
    570  * DESCRIPTION: Send super buffers to HAL
    571  *
    572  * PARAMETERS :
    573  *   @info  : Info of super buffers to be sent in callback
    574  *
    575  * RETURN     : None
    576  *==========================================================================*/
    577 void mm_channel_send_super_buf(mm_channel_node_info_t *info)
    578 {
    579     if (!info || !info->num_nodes){
    580         LOGE("X Error!! Info invalid");
    581         return;
    582     }
    583     mm_channel_queue_node_t *node = NULL;
    584 
    585     LOGH("num nodes %d to send", info->num_nodes);
    586     uint32_t idx = 0;
    587     mm_channel_t *ch_obj = NULL;
    588     for (idx = 0; idx < info->num_nodes; idx++) {
    589         node = info->node[idx];
    590         ch_obj = info->ch_obj[idx];
    591         if ((ch_obj) && (NULL != ch_obj->bundle.super_buf_notify_cb) && node) {
    592             mm_camera_cmdcb_t* cb_node = NULL;
    593             LOGD("Send superbuf to HAL, pending_cnt=%d",
    594                      ch_obj->pending_cnt);
    595             /* send cam_sem_post to wake up cb thread to dispatch super buffer */
    596             cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    597             if (NULL != cb_node) {
    598                 memset(cb_node, 0, sizeof(mm_camera_cmdcb_t));
    599                 cb_node->cmd_type = MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB;
    600                 cb_node->u.superbuf.num_bufs = node->num_of_bufs;
    601                 uint8_t i = 0;
    602                 for (i = 0; i < node->num_of_bufs; i++) {
    603                     cb_node->u.superbuf.bufs[i] = node->super_buf[i].buf;
    604                 }
    605                 cb_node->u.superbuf.camera_handle = ch_obj->cam_obj->my_hdl;
    606                 cb_node->u.superbuf.ch_id = ch_obj->my_hdl;
    607                 cb_node->u.superbuf.bReadyForPrepareSnapshot =
    608                         ch_obj->bWaitForPrepSnapshotDone;
    609                 if (ch_obj->unLockAEC == 1) {
    610                     cb_node->u.superbuf.bUnlockAEC = 1;
    611                     LOGH("Unlocking AEC");
    612                     ch_obj->unLockAEC = 0;
    613                 }
    614                 /* enqueue to cb thread */
    615                 cam_queue_enq(&(ch_obj->cb_thread.cmd_queue), cb_node);
    616                 /* wake up cb thread */
    617                 cam_sem_post(&(ch_obj->cb_thread.cmd_sem));
    618                 LOGH("Sent super buf for node[%d] ", idx);
    619 
    620             } else {
    621                 LOGE("No memory for mm_camera_node_t");
    622                 /* buf done with the unused super buf */
    623                 uint8_t i = 0;
    624                 for (i = 0; i < node->num_of_bufs; i++) {
    625                     mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    626                 }
    627             }
    628             free(node);
    629         } else if ((ch_obj != NULL) && (node != NULL)) {
    630             /* buf done with the unused super buf */
    631             uint8_t i;
    632             for (i = 0; i < node->num_of_bufs; i++) {
    633                 mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    634             }
    635             free(node);
    636         } else {
    637             LOGE("node is NULL, debug this");
    638         }
    639     }
    640 }
    641 
    642 /*===========================================================================
    643  * FUNCTION   : mm_channel_reg_stream_buf_cb
    644  *
    645  * DESCRIPTION: Register callback for stream buffer
    646  *
    647  * PARAMETERS :
    648  *   @my_obj     : Channel object
    649  *   @stream_id  : stream that will be linked
    650  *   @buf_cb     : special callback needs to be registered for stream buffer
    651  *
    652  * RETURN     : int32_t type of status
    653  *              0  -- success
    654  *              -1 --  failure
    655  *==========================================================================*/
    656 int32_t mm_channel_reg_stream_buf_cb (mm_channel_t* my_obj,
    657         uint32_t stream_id, mm_stream_data_cb_t buf_cb)
    658 {
    659     int32_t rc = -1;
    660     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
    661             stream_id);
    662 
    663     if (NULL != s_obj) {
    664         if (s_obj->ch_obj != my_obj) {
    665             /* No op. on linked streams */
    666             return 0;
    667         }
    668         rc = mm_stream_reg_buf_cb(s_obj, buf_cb);
    669     }
    670 
    671     return rc;
    672 
    673 }
    674 
    675 /*===========================================================================
    676  * FUNCTION   : mm_channel_fsm_fn
    677  *
    678  * DESCRIPTION: channel finite state machine entry function. Depends on channel
    679  *              state, incoming event will be handled differently.
    680  *
    681  * PARAMETERS :
    682  *   @my_obj   : ptr to a channel object
    683  *   @evt      : channel event to be processed
    684  *   @in_val   : input event payload. Can be NULL if not needed.
    685  *   @out_val  : output payload, Can be NULL if not needed.
    686  *
    687  * RETURN     : int32_t type of status
    688  *              0  -- success
    689  *              -1 -- failure
    690  *==========================================================================*/
    691 int32_t mm_channel_fsm_fn(mm_channel_t *my_obj,
    692                           mm_channel_evt_type_t evt,
    693                           void * in_val,
    694                           void * out_val)
    695 {
    696     int32_t rc = -1;
    697 
    698     LOGD("E state = %d", my_obj->state);
    699     switch (my_obj->state) {
    700     case MM_CHANNEL_STATE_NOTUSED:
    701         rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val);
    702         break;
    703     case MM_CHANNEL_STATE_STOPPED:
    704         rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val);
    705         break;
    706     case MM_CHANNEL_STATE_ACTIVE:
    707         rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val);
    708         break;
    709     case MM_CHANNEL_STATE_PAUSED:
    710         rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val);
    711         break;
    712     default:
    713         LOGD("Not a valid state (%d)", my_obj->state);
    714         break;
    715     }
    716 
    717     /* unlock ch_lock */
    718     pthread_mutex_unlock(&my_obj->ch_lock);
    719     LOGD("X rc = %d", rc);
    720     return rc;
    721 }
    722 
    723 /*===========================================================================
    724  * FUNCTION   : mm_channel_fsm_fn_notused
    725  *
    726  * DESCRIPTION: channel finite state machine function to handle event
    727  *              in NOT_USED state.
    728  *
    729  * PARAMETERS :
    730  *   @my_obj   : ptr to a channel object
    731  *   @evt      : channel event to be processed
    732  *   @in_val   : input event payload. Can be NULL if not needed.
    733  *   @out_val  : output payload, Can be NULL if not needed.
    734  *
    735  * RETURN     : int32_t type of status
    736  *              0  -- success
    737  *              -1 -- failure
    738  *==========================================================================*/
    739 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
    740                                   mm_channel_evt_type_t evt,
    741                                   void * in_val,
    742                                   void * out_val)
    743 {
    744     int32_t rc = -1;
    745 
    746     switch (evt) {
    747     default:
    748         LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)",
    749                     my_obj->state, evt, in_val, out_val);
    750         break;
    751     }
    752 
    753     return rc;
    754 }
    755 
    756 /*===========================================================================
    757  * FUNCTION   : mm_channel_fsm_fn_stopped
    758  *
    759  * DESCRIPTION: channel finite state machine function to handle event
    760  *              in STOPPED state.
    761  *
    762  * PARAMETERS :
    763  *   @my_obj   : ptr to a channel object
    764  *   @evt      : channel event to be processed
    765  *   @in_val   : input event payload. Can be NULL if not needed.
    766  *   @out_val  : output payload, Can be NULL if not needed.
    767  *
    768  * RETURN     : int32_t type of status
    769  *              0  -- success
    770  *              -1 -- failure
    771  *==========================================================================*/
    772 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
    773                                   mm_channel_evt_type_t evt,
    774                                   void * in_val,
    775                                   void * out_val)
    776 {
    777     int32_t rc = 0;
    778     LOGD("E evt = %d", evt);
    779     switch (evt) {
    780     case MM_CHANNEL_EVT_ADD_STREAM:
    781         {
    782             uint32_t s_hdl = 0;
    783             s_hdl = mm_channel_add_stream(my_obj);
    784             *((uint32_t*)out_val) = s_hdl;
    785             rc = 0;
    786         }
    787         break;
    788     case MM_CHANNEL_EVT_LINK_STREAM:
    789         {
    790             mm_camera_stream_link_t *stream_link = NULL;
    791             uint32_t s_hdl = 0;
    792             stream_link = (mm_camera_stream_link_t *) in_val;
    793             s_hdl = mm_channel_link_stream(my_obj, stream_link);
    794             *((uint32_t*)out_val) = s_hdl;
    795             rc = 0;
    796         }
    797         break;
    798     case MM_CHANNEL_EVT_DEL_STREAM:
    799         {
    800             uint32_t s_id = *((uint32_t *)in_val);
    801             rc = mm_channel_del_stream(my_obj, s_id);
    802         }
    803         break;
    804     case MM_CHANNEL_EVT_START:
    805         {
    806             rc = mm_channel_start(my_obj);
    807             /* first stream started in stopped state
    808              * move to active state */
    809             if (0 == rc) {
    810                 my_obj->state = MM_CHANNEL_STATE_ACTIVE;
    811             }
    812         }
    813         break;
    814     case MM_CHANNEL_EVT_CONFIG_STREAM:
    815         {
    816             mm_evt_paylod_config_stream_t *payload =
    817                 (mm_evt_paylod_config_stream_t *)in_val;
    818             rc = mm_channel_config_stream(my_obj,
    819                                           payload->stream_id,
    820                                           payload->config);
    821         }
    822         break;
    823     case MM_CHANNEL_EVT_GET_BUNDLE_INFO:
    824         {
    825             cam_bundle_config_t *payload =
    826                 (cam_bundle_config_t *)in_val;
    827             rc = mm_channel_get_bundle_info(my_obj, payload);
    828         }
    829         break;
    830     case MM_CHANNEL_EVT_DELETE:
    831         {
    832             mm_channel_release(my_obj);
    833             rc = 0;
    834         }
    835         break;
    836     case MM_CHANNEL_EVT_SET_STREAM_PARM:
    837         {
    838             mm_evt_paylod_set_get_stream_parms_t *payload =
    839                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    840             rc = mm_channel_set_stream_parm(my_obj, payload);
    841         }
    842         break;
    843     case MM_CHANNEL_EVT_GET_STREAM_QUEUED_BUF_COUNT:
    844         {
    845             uint32_t stream_id = *((uint32_t *)in_val);
    846             rc = mm_channel_get_queued_buf_count(my_obj, stream_id);
    847         }
    848         break;
    849     case MM_CHANNEL_EVT_GET_STREAM_PARM:
    850         {
    851             mm_evt_paylod_set_get_stream_parms_t *payload =
    852                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    853             rc = mm_channel_get_stream_parm(my_obj, payload);
    854         }
    855         break;
    856     case MM_CHANNEL_EVT_DO_STREAM_ACTION:
    857         {
    858             mm_evt_paylod_do_stream_action_t *payload =
    859                 (mm_evt_paylod_do_stream_action_t *)in_val;
    860             rc = mm_channel_do_stream_action(my_obj, payload);
    861         }
    862         break;
    863     case MM_CHANNEL_EVT_MAP_STREAM_BUF:
    864         {
    865             cam_buf_map_type *payload =
    866                 (cam_buf_map_type *)in_val;
    867             rc = mm_channel_map_stream_buf(my_obj, payload);
    868         }
    869         break;
    870     case MM_CHANNEL_EVT_MAP_STREAM_BUFS:
    871         {
    872             cam_buf_map_type_list *payload =
    873                 (cam_buf_map_type_list *)in_val;
    874             rc = mm_channel_map_stream_bufs(my_obj, payload);
    875         }
    876         break;
    877     case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
    878         {
    879             cam_buf_unmap_type *payload =
    880                 (cam_buf_unmap_type *)in_val;
    881             rc = mm_channel_unmap_stream_buf(my_obj, payload);
    882         }
    883         break;
    884     case MM_CHANNEL_EVT_REG_STREAM_BUF_CB:
    885         {
    886             mm_evt_paylod_reg_stream_buf_cb *payload =
    887                 (mm_evt_paylod_reg_stream_buf_cb *)in_val;
    888             rc = mm_channel_reg_stream_buf_cb (my_obj,
    889                     payload->stream_id, payload->buf_cb);
    890         }
    891         break;
    892     default:
    893         LOGW("invalid state (%d) for evt (%d)",
    894                     my_obj->state, evt);
    895         break;
    896     }
    897     LOGD("E rc = %d", rc);
    898     return rc;
    899 }
    900 
    901 /*===========================================================================
    902  * FUNCTION   : mm_channel_fsm_fn_active
    903  *
    904  * DESCRIPTION: channel finite state machine function to handle event
    905  *              in ACTIVE state.
    906  *
    907  * PARAMETERS :
    908  *   @my_obj   : ptr to a channel object
    909  *   @evt      : channel event to be processed
    910  *   @in_val   : input event payload. Can be NULL if not needed.
    911  *   @out_val  : output payload, Can be NULL if not needed.
    912  *
    913  * RETURN     : int32_t type of status
    914  *              0  -- success
    915  *              -1 -- failure
    916  *==========================================================================*/
    917 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
    918                           mm_channel_evt_type_t evt,
    919                           void * in_val,
    920                           void * out_val)
    921 {
    922     int32_t rc = 0;
    923 
    924     LOGD("E evt = %d", evt);
    925     switch (evt) {
    926     case MM_CHANNEL_EVT_STOP:
    927         {
    928             rc = mm_channel_stop(my_obj);
    929             my_obj->state = MM_CHANNEL_STATE_STOPPED;
    930         }
    931         break;
    932     case MM_CHANNEL_EVT_REQUEST_SUPER_BUF:
    933         {
    934             mm_camera_req_buf_t *payload =
    935                     (mm_camera_req_buf_t *)in_val;
    936             rc = mm_channel_request_super_buf(my_obj, payload);
    937         }
    938         break;
    939     case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF:
    940         {
    941             rc = mm_channel_cancel_super_buf_request(my_obj);
    942         }
    943         break;
    944     case MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE:
    945         {
    946             uint32_t frame_idx = *((uint32_t *)in_val);
    947             rc = mm_channel_flush_super_buf_queue(my_obj, frame_idx, CAM_STREAM_TYPE_DEFAULT);
    948         }
    949         break;
    950     case MM_CHANNEL_EVT_START_ZSL_SNAPSHOT:
    951         {
    952             rc = mm_channel_start_zsl_snapshot(my_obj);
    953         }
    954         break;
    955     case MM_CHANNEL_EVT_STOP_ZSL_SNAPSHOT:
    956         {
    957             rc = mm_channel_stop_zsl_snapshot(my_obj);
    958         }
    959         break;
    960     case MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE:
    961         {
    962             mm_camera_super_buf_notify_mode_t notify_mode =
    963                 *((mm_camera_super_buf_notify_mode_t *)in_val);
    964             rc = mm_channel_config_notify_mode(my_obj, notify_mode);
    965         }
    966         break;
    967     case MM_CHANNEL_EVT_SET_STREAM_PARM:
    968         {
    969             mm_evt_paylod_set_get_stream_parms_t *payload =
    970                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    971             rc = mm_channel_set_stream_parm(my_obj, payload);
    972         }
    973         break;
    974     case MM_CHANNEL_EVT_GET_STREAM_QUEUED_BUF_COUNT:
    975         {
    976             uint32_t stream_id = *((uint32_t *)in_val);
    977             rc = mm_channel_get_queued_buf_count(my_obj, stream_id);
    978         }
    979         break;
    980     case MM_CHANNEL_EVT_GET_STREAM_PARM:
    981         {
    982             mm_evt_paylod_set_get_stream_parms_t *payload =
    983                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    984             rc = mm_channel_get_stream_parm(my_obj, payload);
    985         }
    986         break;
    987     case MM_CHANNEL_EVT_DO_STREAM_ACTION:
    988         {
    989             mm_evt_paylod_do_stream_action_t *payload =
    990                 (mm_evt_paylod_do_stream_action_t *)in_val;
    991             rc = mm_channel_do_stream_action(my_obj, payload);
    992         }
    993         break;
    994     case MM_CHANNEL_EVT_MAP_STREAM_BUF:
    995         {
    996             cam_buf_map_type *payload =
    997                 (cam_buf_map_type *)in_val;
    998             if (payload != NULL) {
    999                 uint8_t type = payload->type;
   1000                 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
   1001                         (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
   1002                     rc = mm_channel_map_stream_buf(my_obj, payload);
   1003                 }
   1004             } else {
   1005                 LOGE("cannot map regualr stream buf in active state");
   1006             }
   1007         }
   1008         break;
   1009     case MM_CHANNEL_EVT_MAP_STREAM_BUFS:
   1010         {
   1011             cam_buf_map_type_list *payload =
   1012                 (cam_buf_map_type_list *)in_val;
   1013             if ((payload != NULL) && (payload->length > 0)) {
   1014                 uint8_t type = payload->buf_maps[0].type;
   1015                 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
   1016                         (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
   1017                     rc = mm_channel_map_stream_bufs(my_obj, payload);
   1018                 }
   1019             } else {
   1020                 LOGE("cannot map regualr stream buf in active state");
   1021             }
   1022         }
   1023         break;
   1024     case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
   1025         {
   1026             cam_buf_unmap_type *payload =
   1027                 (cam_buf_unmap_type *)in_val;
   1028             if (payload != NULL) {
   1029                 uint8_t type = payload->type;
   1030                 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
   1031                         (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
   1032                     rc = mm_channel_unmap_stream_buf(my_obj, payload);
   1033                 }
   1034             } else {
   1035                 LOGE("cannot unmap regualr stream buf in active state");
   1036             }
   1037         }
   1038         break;
   1039     case MM_CHANNEL_EVT_AF_BRACKETING:
   1040         {
   1041             LOGH("MM_CHANNEL_EVT_AF_BRACKETING");
   1042             uint32_t start_flag = *((uint32_t *)in_val);
   1043             mm_camera_generic_cmd_t gen_cmd;
   1044             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING;
   1045             gen_cmd.payload[0] = start_flag;
   1046             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
   1047         }
   1048         break;
   1049     case MM_CHANNEL_EVT_AE_BRACKETING:
   1050         {
   1051             LOGH("MM_CHANNEL_EVT_AE_BRACKETING");
   1052             uint32_t start_flag = *((uint32_t *)in_val);
   1053             mm_camera_generic_cmd_t gen_cmd;
   1054             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING;
   1055             gen_cmd.payload[0] = start_flag;
   1056             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
   1057         }
   1058         break;
   1059     case MM_CHANNEL_EVT_FLASH_BRACKETING:
   1060         {
   1061             LOGH("MM_CHANNEL_EVT_FLASH_BRACKETING");
   1062             uint32_t start_flag = *((uint32_t *)in_val);
   1063             mm_camera_generic_cmd_t gen_cmd;
   1064             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING;
   1065             gen_cmd.payload[0] = start_flag;
   1066             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
   1067         }
   1068         break;
   1069     case MM_CHANNEL_EVT_ZOOM_1X:
   1070         {
   1071             LOGH("MM_CHANNEL_EVT_ZOOM_1X");
   1072             uint32_t start_flag = *((uint32_t *)in_val);
   1073             mm_camera_generic_cmd_t gen_cmd;
   1074             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X;
   1075             gen_cmd.payload[0] = start_flag;
   1076             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
   1077         }
   1078         break;
   1079     case MM_CAMERA_EVT_CAPTURE_SETTING:
   1080         {
   1081             mm_camera_generic_cmd_t gen_cmd;
   1082             cam_capture_frame_config_t *input;
   1083             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING;
   1084             LOGH("MM_CAMERA_EVT_CAPTURE_SETTING");
   1085             if (in_val == NULL) {
   1086                 gen_cmd.payload[0] = 0;
   1087                 memset(&gen_cmd.frame_config, 0, sizeof(cam_capture_frame_config_t));
   1088             } else {
   1089                 gen_cmd.payload[0] = 1;
   1090                 input = (cam_capture_frame_config_t *)in_val;
   1091                 gen_cmd.frame_config = *input;
   1092             }
   1093             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
   1094         }
   1095         break;
   1096     case MM_CHANNEL_EVT_REG_STREAM_BUF_CB:
   1097         {
   1098             mm_evt_paylod_reg_stream_buf_cb *payload =
   1099                 (mm_evt_paylod_reg_stream_buf_cb *)in_val;
   1100             rc = mm_channel_reg_stream_buf_cb (my_obj,
   1101                     payload->stream_id, payload->buf_cb);
   1102         }
   1103         break;
   1104      default:
   1105         LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)",
   1106                     my_obj->state, evt, in_val, out_val);
   1107         break;
   1108     }
   1109     LOGD("X rc = %d", rc);
   1110     return rc;
   1111 }
   1112 
   1113 /*===========================================================================
   1114  * FUNCTION   : mm_channel_fsm_fn_paused
   1115  *
   1116  * DESCRIPTION: channel finite state machine function to handle event
   1117  *              in PAUSED state.
   1118  *
   1119  * PARAMETERS :
   1120  *   @my_obj   : ptr to a channel object
   1121  *   @evt      : channel event to be processed
   1122  *   @in_val   : input event payload. Can be NULL if not needed.
   1123  *   @out_val  : output payload, Can be NULL if not needed.
   1124  *
   1125  * RETURN     : int32_t type of status
   1126  *              0  -- success
   1127  *              -1 -- failure
   1128  *==========================================================================*/
   1129 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
   1130                           mm_channel_evt_type_t evt,
   1131                           void * in_val,
   1132                           void * out_val)
   1133 {
   1134     int32_t rc = 0;
   1135 
   1136     /* currently we are not supporting pause/resume channel */
   1137     LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)",
   1138                 my_obj->state, evt, in_val, out_val);
   1139 
   1140     return rc;
   1141 }
   1142 
   1143 /*===========================================================================
   1144  * FUNCTION   : mm_channel_init
   1145  *
   1146  * DESCRIPTION: initialize a channel
   1147  *
   1148  * PARAMETERS :
   1149  *   @my_obj       : channel object be to initialized
   1150  *   @attr         : bundle attribute of the channel if needed
   1151  *   @channel_cb   : callback function for bundle data notify
   1152  *   @userdata     : user data ptr
   1153  *
   1154  * RETURN     : int32_t type of status
   1155  *              0  -- success
   1156  *              -1 -- failure
   1157  * NOTE       : if no bundle data notify is needed, meaning each stream in the
   1158  *              channel will have its own stream data notify callback, then
   1159  *              attr, channel_cb, and userdata can be NULL. In this case,
   1160  *              no matching logic will be performed in channel for the bundling.
   1161  *==========================================================================*/
   1162 int32_t mm_channel_init(mm_channel_t *my_obj,
   1163                         mm_camera_channel_attr_t *attr,
   1164                         mm_camera_buf_notify_t channel_cb,
   1165                         void *userdata)
   1166 {
   1167     int32_t rc = 0;
   1168 
   1169     my_obj->bundle.super_buf_notify_cb = channel_cb;
   1170     my_obj->bundle.user_data = userdata;
   1171     if (NULL != attr) {
   1172         my_obj->bundle.superbuf_queue.attr = *attr;
   1173     }
   1174 
   1175     LOGD("Launch data poll thread in channel open");
   1176     snprintf(my_obj->poll_thread[0].threadName, THREAD_NAME_SIZE, "CAM_dataPoll");
   1177     mm_camera_poll_thread_launch(&my_obj->poll_thread[0],
   1178                                  MM_CAMERA_POLL_TYPE_DATA);
   1179 
   1180     /* change state to stopped state */
   1181     my_obj->state = MM_CHANNEL_STATE_STOPPED;
   1182     return rc;
   1183 }
   1184 
   1185 /*===========================================================================
   1186  * FUNCTION   : mm_channel_release
   1187  *
   1188  * DESCRIPTION: release a channel resource. Channel state will move to UNUSED
   1189  *              state after this call.
   1190  *
   1191  * PARAMETERS :
   1192  *   @my_obj       : channel object
   1193  *
   1194  * RETURN     : none
   1195  *==========================================================================*/
   1196 void mm_channel_release(mm_channel_t *my_obj)
   1197 {
   1198     /* stop data poll thread */
   1199     mm_camera_poll_thread_release(&my_obj->poll_thread[0]);
   1200 
   1201     /* memset bundle info */
   1202     memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t));
   1203 
   1204     /* change state to notused state */
   1205     my_obj->state = MM_CHANNEL_STATE_NOTUSED;
   1206 }
   1207 
   1208 /*===========================================================================
   1209  * FUNCTION   : mm_channel_link_stream
   1210  *
   1211  * DESCRIPTION: link a stream from external channel into this channel
   1212  *
   1213  * PARAMETERS :
   1214  *   @my_obj  : channel object
   1215  *   @stream_link  : channel and stream to be linked
   1216  *
   1217  * RETURN     : uint32_t type of stream handle
   1218  *              0  -- invalid stream handle, meaning the op failed
   1219  *              >0 -- successfully added a stream with a valid handle
   1220  *==========================================================================*/
   1221 uint32_t mm_channel_link_stream(mm_channel_t *my_obj,
   1222         mm_camera_stream_link_t *stream_link)
   1223 {
   1224     uint8_t idx = 0;
   1225     uint32_t s_hdl = 0;
   1226     mm_stream_t *stream_obj = NULL;
   1227     mm_stream_t *stream = NULL;
   1228 
   1229     if (NULL == stream_link) {
   1230         LOGE("Invalid stream link");
   1231         return 0;
   1232     }
   1233 
   1234     stream = mm_channel_util_get_stream_by_handler(stream_link->ch,
   1235             stream_link->stream_id);
   1236     if (NULL == stream) {
   1237         return 0;
   1238     }
   1239 
   1240     /* check available stream */
   1241     for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) {
   1242         if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
   1243             stream_obj = &my_obj->streams[idx];
   1244             break;
   1245         }
   1246     }
   1247     if (NULL == stream_obj) {
   1248         LOGE("streams reach max, no more stream allowed to add");
   1249         return s_hdl;
   1250     }
   1251 
   1252     /* initialize stream object */
   1253     *stream_obj = *stream;
   1254     stream_obj->linked_stream = stream;
   1255     s_hdl = stream->my_hdl;
   1256 
   1257     LOGD("stream handle = %d", s_hdl);
   1258     return s_hdl;
   1259 }
   1260 
   1261 /*===========================================================================
   1262  * FUNCTION   : mm_channel_add_stream
   1263  *
   1264  * DESCRIPTION: add a stream into the channel
   1265  *
   1266  * PARAMETERS :
   1267  *   @my_obj       : channel object
   1268  *
   1269  * RETURN     : uint32_t type of stream handle
   1270  *              0  -- invalid stream handle, meaning the op failed
   1271  *              >0 -- successfully added a stream with a valid handle
   1272  *==========================================================================*/
   1273 uint32_t mm_channel_add_stream(mm_channel_t *my_obj)
   1274 {
   1275     int32_t rc = 0;
   1276     uint8_t idx = 0;
   1277     uint32_t s_hdl = 0;
   1278     mm_stream_t *stream_obj = NULL;
   1279 
   1280     LOGD("E");
   1281     /* check available stream */
   1282     for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) {
   1283         if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
   1284             stream_obj = &my_obj->streams[idx];
   1285             break;
   1286         }
   1287     }
   1288     if (NULL == stream_obj) {
   1289         LOGE("streams reach max, no more stream allowed to add");
   1290         return s_hdl;
   1291     }
   1292 
   1293     /* initialize stream object */
   1294     memset(stream_obj, 0, sizeof(mm_stream_t));
   1295     stream_obj->fd = -1;
   1296     stream_obj->my_hdl = mm_camera_util_generate_handler(idx);
   1297     stream_obj->ch_obj = my_obj;
   1298     pthread_mutex_init(&stream_obj->buf_lock, NULL);
   1299     pthread_mutex_init(&stream_obj->cb_lock, NULL);
   1300     pthread_mutex_init(&stream_obj->cmd_lock, NULL);
   1301     PTHREAD_COND_INIT(&stream_obj->buf_cond);
   1302     memset(stream_obj->buf_status, 0,
   1303             sizeof(stream_obj->buf_status));
   1304     stream_obj->state = MM_STREAM_STATE_INITED;
   1305 
   1306     /* acquire stream */
   1307     rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL);
   1308     if (0 == rc) {
   1309         s_hdl = stream_obj->my_hdl;
   1310     } else {
   1311         /* error during acquire, de-init */
   1312         pthread_cond_destroy(&stream_obj->buf_cond);
   1313         pthread_mutex_destroy(&stream_obj->buf_lock);
   1314         pthread_mutex_destroy(&stream_obj->cb_lock);
   1315         pthread_mutex_destroy(&stream_obj->cmd_lock);
   1316         memset(stream_obj, 0, sizeof(mm_stream_t));
   1317     }
   1318     LOGD("stream handle = %d", s_hdl);
   1319     return s_hdl;
   1320 }
   1321 
   1322 /*===========================================================================
   1323  * FUNCTION   : mm_channel_del_stream
   1324  *
   1325  * DESCRIPTION: delete a stream from the channel bu its handle
   1326  *
   1327  * PARAMETERS :
   1328  *   @my_obj       : channel object
   1329  *   @stream_id    : stream handle
   1330  *
   1331  * RETURN     : int32_t type of status
   1332  *              0  -- success
   1333  *              -1 -- failure
   1334  * NOTE       : assume steam is stooped before it can be deleted
   1335  *==========================================================================*/
   1336 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
   1337                               uint32_t stream_id)
   1338 {
   1339     int rc = -1;
   1340     mm_stream_t * stream_obj = NULL;
   1341     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
   1342 
   1343     if (NULL == stream_obj) {
   1344         LOGE("Invalid Stream Object for stream_id = %d", stream_id);
   1345         return rc;
   1346     }
   1347 
   1348     if (stream_obj->ch_obj != my_obj) {
   1349         /* Only unlink stream */
   1350         pthread_mutex_lock(&stream_obj->linked_stream->buf_lock);
   1351         stream_obj->linked_stream->is_linked = 0;
   1352         stream_obj->linked_stream->linked_obj = NULL;
   1353         pthread_mutex_unlock(&stream_obj->linked_stream->buf_lock);
   1354         memset(stream_obj, 0, sizeof(mm_stream_t));
   1355 
   1356         return 0;
   1357     }
   1358 
   1359     rc = mm_stream_fsm_fn(stream_obj,
   1360                           MM_STREAM_EVT_RELEASE,
   1361                           NULL,
   1362                           NULL);
   1363 
   1364     return rc;
   1365 }
   1366 
   1367 /*===========================================================================
   1368  * FUNCTION   : mm_channel_config_stream
   1369  *
   1370  * DESCRIPTION: configure a stream
   1371  *
   1372  * PARAMETERS :
   1373  *   @my_obj       : channel object
   1374  *   @stream_id    : stream handle
   1375  *   @config       : stream configuration
   1376  *
   1377  * RETURN     : int32_t type of status
   1378  *              0  -- success
   1379  *              -1 -- failure
   1380  *==========================================================================*/
   1381 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
   1382                                    uint32_t stream_id,
   1383                                    mm_camera_stream_config_t *config)
   1384 {
   1385     int rc = -1;
   1386     mm_stream_t * stream_obj = NULL;
   1387     LOGD("E stream ID = %d", stream_id);
   1388     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
   1389 
   1390     if (NULL == stream_obj) {
   1391         LOGE("Invalid Stream Object for stream_id = %d", stream_id);
   1392         return rc;
   1393     }
   1394 
   1395     if (stream_obj->ch_obj != my_obj) {
   1396         /* No op. on linked streams */
   1397         return 0;
   1398     }
   1399 
   1400     /* set stream fmt */
   1401     rc = mm_stream_fsm_fn(stream_obj,
   1402                           MM_STREAM_EVT_SET_FMT,
   1403                           (void *)config,
   1404                           NULL);
   1405     LOGD("X rc = %d",rc);
   1406     return rc;
   1407 }
   1408 
   1409 /*===========================================================================
   1410  * FUNCTION   : mm_channel_get_bundle_info
   1411  *
   1412  * DESCRIPTION: query bundle info of the channel, which should include all
   1413  *              streams within this channel
   1414  *
   1415  * PARAMETERS :
   1416  *   @my_obj       : channel object
   1417  *   @bundle_info  : bundle info to be filled in
   1418  *
   1419  * RETURN     : int32_t type of status
   1420  *              0  -- success
   1421  *              -1 -- failure
   1422  *==========================================================================*/
   1423 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj,
   1424                                    cam_bundle_config_t *bundle_info)
   1425 {
   1426     int i;
   1427     mm_stream_t *s_obj = NULL;
   1428     cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
   1429     int32_t rc = 0;
   1430 
   1431     memset(bundle_info, 0, sizeof(cam_bundle_config_t));
   1432     bundle_info->bundle_id = my_obj->my_hdl;
   1433     bundle_info->num_of_streams = 0;
   1434     for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
   1435         if (my_obj->streams[i].my_hdl > 0) {
   1436             s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1437                                                           my_obj->streams[i].my_hdl);
   1438             if (NULL != s_obj) {
   1439                 stream_type = s_obj->stream_info->stream_type;
   1440                 if ((CAM_STREAM_TYPE_METADATA != stream_type) &&
   1441                         (s_obj->ch_obj == my_obj)) {
   1442                     bundle_info->stream_ids[bundle_info->num_of_streams++] =
   1443                                                         s_obj->server_stream_id;
   1444                 }
   1445             } else {
   1446                 LOGE("cannot find stream obj (%d) by handler (%d)",
   1447                             i, my_obj->streams[i].my_hdl);
   1448                 rc = -1;
   1449                 break;
   1450             }
   1451         }
   1452     }
   1453     if (rc != 0) {
   1454         /* error, reset to 0 */
   1455         memset(bundle_info, 0, sizeof(cam_bundle_config_t));
   1456     }
   1457     return rc;
   1458 }
   1459 
   1460 /*===========================================================================
   1461  * FUNCTION   : mm_channel_start
   1462  *
   1463  * DESCRIPTION: start a channel, which will start all streams in the channel
   1464  *
   1465  * PARAMETERS :
   1466  *   @my_obj       : channel object
   1467  *
   1468  * RETURN     : int32_t type of status
   1469  *              0  -- success
   1470  *              -1 -- failure
   1471  *==========================================================================*/
   1472 int32_t mm_channel_start(mm_channel_t *my_obj)
   1473 {
   1474     int32_t rc = 0;
   1475     int i = 0, j = 0;
   1476     mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
   1477     uint8_t num_streams_to_start = 0;
   1478     uint8_t num_streams_in_bundle_queue = 0;
   1479     mm_stream_t *s_obj = NULL;
   1480     int meta_stream_idx = 0;
   1481     cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
   1482 
   1483     for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
   1484         if (my_obj->streams[i].my_hdl > 0) {
   1485             s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1486                                                           my_obj->streams[i].my_hdl);
   1487             if (NULL != s_obj) {
   1488                 stream_type = s_obj->stream_info->stream_type;
   1489                 /* remember meta data stream index */
   1490                 if ((stream_type == CAM_STREAM_TYPE_METADATA) &&
   1491                         (s_obj->ch_obj == my_obj)) {
   1492                     meta_stream_idx = num_streams_to_start;
   1493                 }
   1494                 s_objs[num_streams_to_start++] = s_obj;
   1495 
   1496                 if (!s_obj->stream_info->noFrameExpected) {
   1497                     num_streams_in_bundle_queue++;
   1498                 }
   1499             }
   1500         }
   1501     }
   1502 
   1503     if (meta_stream_idx > 0 ) {
   1504         /* always start meta data stream first, so switch the stream object with the first one */
   1505         s_obj = s_objs[0];
   1506         s_objs[0] = s_objs[meta_stream_idx];
   1507         s_objs[meta_stream_idx] = s_obj;
   1508     }
   1509 
   1510     if (NULL != my_obj->bundle.super_buf_notify_cb) {
   1511         /* need to send up cb, therefore launch thread */
   1512         /* init superbuf queue */
   1513         mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue);
   1514         my_obj->bundle.superbuf_queue.num_streams = num_streams_in_bundle_queue;
   1515         my_obj->bundle.superbuf_queue.expected_frame_id =
   1516                 my_obj->bundle.superbuf_queue.attr.user_expected_frame_id;
   1517         my_obj->bundle.superbuf_queue.expected_frame_id_without_led = 0;
   1518         my_obj->bundle.superbuf_queue.led_off_start_frame_id = 0;
   1519         my_obj->bundle.superbuf_queue.led_on_start_frame_id = 0;
   1520         my_obj->bundle.superbuf_queue.led_on_num_frames = 0;
   1521         my_obj->bundle.superbuf_queue.good_frame_id = 0;
   1522 
   1523         for (i = 0; i < num_streams_to_start; i++) {
   1524             /* Only bundle streams that belong to the channel */
   1525             if(!(s_objs[i]->stream_info->noFrameExpected)) {
   1526                 if (s_objs[i]->ch_obj == my_obj) {
   1527                     /* set bundled flag to streams */
   1528                     s_objs[i]->is_bundled = 1;
   1529                 }
   1530                 my_obj->bundle.superbuf_queue.bundled_streams[j++] = s_objs[i]->my_hdl;
   1531             }
   1532         }
   1533 
   1534         /* launch cb thread for dispatching super buf through cb */
   1535         snprintf(my_obj->cb_thread.threadName, THREAD_NAME_SIZE, "CAM_SuperBuf");
   1536         mm_camera_cmd_thread_launch(&my_obj->cb_thread,
   1537                                     mm_channel_dispatch_super_buf,
   1538                                     (void*)my_obj);
   1539 
   1540         /* launch cmd thread for super buf dataCB */
   1541         snprintf(my_obj->cmd_thread.threadName, THREAD_NAME_SIZE, "CAM_SuperBufCB");
   1542         mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
   1543                                     mm_channel_process_stream_buf,
   1544                                     (void*)my_obj);
   1545 
   1546         /* set flag to TRUE */
   1547         my_obj->bundle.is_active = TRUE;
   1548     }
   1549 
   1550     /* link any streams first before starting the rest of the streams */
   1551     for (i = 0; i < num_streams_to_start; i++) {
   1552         if (s_objs[i]->ch_obj != my_obj) {
   1553             pthread_mutex_lock(&s_objs[i]->linked_stream->buf_lock);
   1554             s_objs[i]->linked_stream->linked_obj = my_obj;
   1555             s_objs[i]->linked_stream->is_linked = 1;
   1556             pthread_mutex_unlock(&s_objs[i]->linked_stream->buf_lock);
   1557             continue;
   1558         }
   1559     }
   1560 
   1561     for (i = 0; i < num_streams_to_start; i++) {
   1562         if (s_objs[i]->ch_obj != my_obj) {
   1563             continue;
   1564         }
   1565         /* all streams within a channel should be started at the same time */
   1566         if (s_objs[i]->state == MM_STREAM_STATE_ACTIVE) {
   1567             LOGE("stream already started idx(%d)", i);
   1568             rc = -1;
   1569             break;
   1570         }
   1571 
   1572         /* allocate buf */
   1573         rc = mm_stream_fsm_fn(s_objs[i],
   1574                               MM_STREAM_EVT_GET_BUF,
   1575                               NULL,
   1576                               NULL);
   1577         if (0 != rc) {
   1578             LOGE("get buf failed at idx(%d)", i);
   1579             break;
   1580         }
   1581 
   1582         /* reg buf */
   1583         rc = mm_stream_fsm_fn(s_objs[i],
   1584                               MM_STREAM_EVT_REG_BUF,
   1585                               NULL,
   1586                               NULL);
   1587         if (0 != rc) {
   1588             LOGE("reg buf failed at idx(%d)", i);
   1589             break;
   1590         }
   1591 
   1592         /* start stream */
   1593         rc = mm_stream_fsm_fn(s_objs[i],
   1594                               MM_STREAM_EVT_START,
   1595                               NULL,
   1596                               NULL);
   1597         if (0 != rc) {
   1598             LOGE("start stream failed at idx(%d)", i);
   1599             break;
   1600         }
   1601     }
   1602 
   1603     /* error handling */
   1604     if (0 != rc) {
   1605         /* unlink the streams first */
   1606         for (j = 0; j < num_streams_to_start; j++) {
   1607             if (s_objs[j]->ch_obj != my_obj) {
   1608                 pthread_mutex_lock(&s_objs[j]->linked_stream->buf_lock);
   1609                 s_objs[j]->linked_stream->is_linked = 0;
   1610                 s_objs[j]->linked_stream->linked_obj = NULL;
   1611                 pthread_mutex_unlock(&s_objs[j]->linked_stream->buf_lock);
   1612 
   1613                 if (TRUE == my_obj->bundle.is_active) {
   1614                     mm_channel_flush_super_buf_queue(my_obj, 0,
   1615                             s_objs[i]->stream_info->stream_type);
   1616                 }
   1617                 memset(s_objs[j], 0, sizeof(mm_stream_t));
   1618                 continue;
   1619             }
   1620         }
   1621 
   1622         for (j = 0; j <= i; j++) {
   1623             if ((NULL == s_objs[j]) || (s_objs[j]->ch_obj != my_obj)) {
   1624                 continue;
   1625             }
   1626             /* stop streams*/
   1627             mm_stream_fsm_fn(s_objs[j],
   1628                              MM_STREAM_EVT_STOP,
   1629                              NULL,
   1630                              NULL);
   1631 
   1632             /* unreg buf */
   1633             mm_stream_fsm_fn(s_objs[j],
   1634                              MM_STREAM_EVT_UNREG_BUF,
   1635                              NULL,
   1636                              NULL);
   1637 
   1638             /* put buf back */
   1639             mm_stream_fsm_fn(s_objs[j],
   1640                              MM_STREAM_EVT_PUT_BUF,
   1641                              NULL,
   1642                              NULL);
   1643         }
   1644 
   1645         /* destroy super buf cmd thread */
   1646         if (TRUE == my_obj->bundle.is_active) {
   1647             /* first stop bundle thread */
   1648             mm_camera_cmd_thread_release(&my_obj->cmd_thread);
   1649             mm_camera_cmd_thread_release(&my_obj->cb_thread);
   1650 
   1651             /* deinit superbuf queue */
   1652             mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
   1653 
   1654             /* memset super buffer queue info */
   1655             my_obj->bundle.is_active = 0;
   1656             memset(&my_obj->bundle.superbuf_queue, 0, sizeof(mm_channel_queue_t));
   1657         }
   1658     }
   1659     my_obj->bWaitForPrepSnapshotDone = 0;
   1660     if (my_obj->bundle.superbuf_queue.attr.enable_frame_sync) {
   1661         LOGH("registering Channel obj %p", my_obj);
   1662         mm_frame_sync_register_channel(my_obj);
   1663     }
   1664     return rc;
   1665 }
   1666 
   1667 /*===========================================================================
   1668  * FUNCTION   : mm_channel_stop
   1669  *
   1670  * DESCRIPTION: stop a channel, which will stop all streams in the channel
   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_stop(mm_channel_t *my_obj)
   1680 {
   1681     int32_t rc = 0;
   1682     int i;
   1683     mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
   1684     uint8_t num_streams_to_stop = 0;
   1685     mm_stream_t *s_obj = NULL;
   1686     int meta_stream_idx = 0;
   1687     cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
   1688 
   1689     if (my_obj->bundle.superbuf_queue.attr.enable_frame_sync) {
   1690         mm_frame_sync_unregister_channel(my_obj);
   1691     }
   1692 
   1693     for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
   1694         if (my_obj->streams[i].my_hdl > 0) {
   1695             s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1696                                                           my_obj->streams[i].my_hdl);
   1697             if (NULL != s_obj) {
   1698                 if (s_obj->ch_obj == my_obj) {
   1699                     stream_type = s_obj->stream_info->stream_type;
   1700                     /* remember meta data stream index */
   1701                     if (stream_type == CAM_STREAM_TYPE_METADATA) {
   1702                         meta_stream_idx = num_streams_to_stop;
   1703                     }
   1704                 }
   1705                 s_objs[num_streams_to_stop++] = s_obj;
   1706             }
   1707         }
   1708     }
   1709 
   1710     if (meta_stream_idx < num_streams_to_stop - 1 ) {
   1711         /* always stop meta data stream last, so switch the stream object with the last one */
   1712         s_obj = s_objs[num_streams_to_stop - 1];
   1713         s_objs[num_streams_to_stop - 1] = s_objs[meta_stream_idx];
   1714         s_objs[meta_stream_idx] = s_obj;
   1715     }
   1716 
   1717     for (i = 0; i < num_streams_to_stop; i++) {
   1718         /* stream that are linked to this channel should not be stopped */
   1719         if (s_objs[i]->ch_obj != my_obj) {
   1720             continue;
   1721         }
   1722 
   1723         /* stream off */
   1724         mm_stream_fsm_fn(s_objs[i],
   1725                          MM_STREAM_EVT_STOP,
   1726                          NULL,
   1727                          NULL);
   1728 
   1729         /* unreg buf at kernel */
   1730         mm_stream_fsm_fn(s_objs[i],
   1731                          MM_STREAM_EVT_UNREG_BUF,
   1732                          NULL,
   1733                          NULL);
   1734     }
   1735 
   1736     for (i = 0; i < num_streams_to_stop; i++) {
   1737         if (s_objs[i]->ch_obj != my_obj) {
   1738             /* Only unlink stream */
   1739             pthread_mutex_lock(&s_objs[i]->linked_stream->buf_lock);
   1740             s_objs[i]->linked_stream->is_linked = 0;
   1741             s_objs[i]->linked_stream->linked_obj = NULL;
   1742             pthread_mutex_unlock(&s_objs[i]->linked_stream->buf_lock);
   1743         }
   1744     }
   1745 
   1746     /* destroy super buf cmd thread */
   1747     if (TRUE == my_obj->bundle.is_active) {
   1748         mm_channel_flush_super_buf_queue(my_obj, 0, CAM_STREAM_TYPE_DEFAULT);
   1749         /* first stop bundle thread */
   1750         mm_camera_cmd_thread_release(&my_obj->cmd_thread);
   1751         mm_camera_cmd_thread_release(&my_obj->cb_thread);
   1752 
   1753         /* deinit superbuf queue */
   1754         mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
   1755 
   1756         /* reset few fields in the bundle info */
   1757         my_obj->bundle.is_active = 0;
   1758         my_obj->bundle.superbuf_queue.expected_frame_id = 0;
   1759         my_obj->bundle.superbuf_queue.good_frame_id = 0;
   1760         my_obj->bundle.superbuf_queue.match_cnt = 0;
   1761     }
   1762 
   1763     /* since all streams are stopped, we are safe to
   1764      * release all buffers allocated in stream */
   1765     for (i = 0; i < num_streams_to_stop; i++) {
   1766         if (s_objs[i]->ch_obj != my_obj) {
   1767             continue;
   1768         }
   1769         /* put buf back */
   1770         mm_stream_fsm_fn(s_objs[i],
   1771                          MM_STREAM_EVT_PUT_BUF,
   1772                          NULL,
   1773                          NULL);
   1774     }
   1775 
   1776     for (i = 0; i < num_streams_to_stop; i++) {
   1777         if (s_objs[i]->ch_obj != my_obj) {
   1778             memset(s_objs[i], 0, sizeof(mm_stream_t));
   1779         } else {
   1780             continue;
   1781         }
   1782     }
   1783 
   1784     return rc;
   1785 }
   1786 
   1787 /*===========================================================================
   1788  * FUNCTION   : mm_channel_request_super_buf
   1789  *
   1790  * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched
   1791  *              frames from superbuf queue
   1792  *
   1793  * PARAMETERS :
   1794  *   @my_obj       : channel object
   1795  *   @num_buf_requested : number of matched frames needed
   1796  *   @num_retro_buf_requested : number of retro frames needed
   1797  *
   1798  * RETURN     : int32_t type of status
   1799  *              0  -- success
   1800  *              -1 -- failure
   1801  *==========================================================================*/
   1802 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj,
   1803         mm_camera_req_buf_t *buf)
   1804 {
   1805     int32_t rc = 0;
   1806     mm_camera_cmdcb_t* node = NULL;
   1807 
   1808     if(!buf) {
   1809         LOGE("Request info buf is NULL");
   1810         return -1;
   1811     }
   1812 
   1813     /* set pending_cnt
   1814      * will trigger dispatching super frames if pending_cnt > 0 */
   1815     /* send cam_sem_post to wake up cmd thread to dispatch super buffer */
   1816     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1817     if (NULL != node) {
   1818         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1819         node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB;
   1820         node->u.req_buf = *buf;
   1821 
   1822         /* enqueue to cmd thread */
   1823         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1824 
   1825         /* wake up cmd thread */
   1826         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   1827     } else {
   1828         LOGE("No memory for mm_camera_node_t");
   1829         rc = -1;
   1830     }
   1831 
   1832     return rc;
   1833 }
   1834 
   1835 /*===========================================================================
   1836  * FUNCTION   : mm_channel_cancel_super_buf_request
   1837  *
   1838  * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount
   1839  *              of matched frames from superbuf queue
   1840  *
   1841  * PARAMETERS :
   1842  *   @my_obj       : channel object
   1843  *
   1844  * RETURN     : int32_t type of status
   1845  *              0  -- success
   1846  *              -1 -- failure
   1847  *==========================================================================*/
   1848 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj)
   1849 {
   1850     int32_t rc = 0;
   1851     /* reset pending_cnt */
   1852     mm_camera_req_buf_t buf;
   1853     memset(&buf, 0x0, sizeof(buf));
   1854     buf.type = MM_CAMERA_REQ_SUPER_BUF;
   1855     buf.num_buf_requested = 0;
   1856     rc = mm_channel_request_super_buf(my_obj, &buf);
   1857     return rc;
   1858 }
   1859 
   1860 /*===========================================================================
   1861  * FUNCTION   : mm_channel_flush_super_buf_queue
   1862  *
   1863  * DESCRIPTION: flush superbuf queue
   1864  *
   1865  * PARAMETERS :
   1866  *   @my_obj  : channel object
   1867  *   @frame_idx : frame idx until which to flush all superbufs
   1868  *
   1869  * RETURN     : int32_t type of status
   1870  *              0  -- success
   1871  *              -1 -- failure
   1872  *==========================================================================*/
   1873 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, uint32_t frame_idx,
   1874                                                      cam_stream_type_t stream_type)
   1875 {
   1876     int32_t rc = 0;
   1877     mm_camera_cmdcb_t* node = NULL;
   1878 
   1879     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1880     if (NULL != node) {
   1881         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1882         node->cmd_type = MM_CAMERA_CMD_TYPE_FLUSH_QUEUE;
   1883         node->u.flush_cmd.frame_idx = frame_idx;
   1884         node->u.flush_cmd.stream_type = stream_type;
   1885 
   1886         /* enqueue to cmd thread */
   1887         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1888 
   1889         /* wake up cmd thread */
   1890         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   1891 
   1892         /* wait for ack from cmd thread */
   1893         cam_sem_wait(&(my_obj->cmd_thread.sync_sem));
   1894     } else {
   1895         LOGE("No memory for mm_camera_node_t");
   1896         rc = -1;
   1897     }
   1898 
   1899     return rc;
   1900 }
   1901 
   1902 /*===========================================================================
   1903  * FUNCTION   : mm_channel_config_notify_mode
   1904  *
   1905  * DESCRIPTION: configure notification mode
   1906  *
   1907  * PARAMETERS :
   1908  *   @my_obj  : channel object
   1909  *   @notify_mode : notification mode
   1910  *
   1911  * RETURN     : int32_t type of status
   1912  *              0  -- success
   1913  *              -1 -- failure
   1914  *==========================================================================*/
   1915 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj,
   1916                                       mm_camera_super_buf_notify_mode_t notify_mode)
   1917 {
   1918     int32_t rc = 0;
   1919     mm_camera_cmdcb_t* node = NULL;
   1920 
   1921     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1922     if (NULL != node) {
   1923         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1924         node->u.notify_mode = notify_mode;
   1925         node->cmd_type = MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY;
   1926 
   1927         /* enqueue to cmd thread */
   1928         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1929 
   1930         /* wake up cmd thread */
   1931         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   1932     } else {
   1933         LOGE("No memory for mm_camera_node_t");
   1934         rc = -1;
   1935     }
   1936 
   1937     return rc;
   1938 }
   1939 
   1940 /*===========================================================================
   1941  * FUNCTION   : mm_channel_start_zsl_snapshot
   1942  *
   1943  * DESCRIPTION: start zsl snapshot
   1944  *
   1945  * PARAMETERS :
   1946  *   @my_obj  : channel object
   1947  *
   1948  * RETURN     : int32_t type of status
   1949  *              0  -- success
   1950  *              -1 -- failure
   1951  *==========================================================================*/
   1952 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj)
   1953 {
   1954     int32_t rc = 0;
   1955     mm_camera_cmdcb_t* node = NULL;
   1956 
   1957     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1958     if (NULL != node) {
   1959         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1960         node->cmd_type = MM_CAMERA_CMD_TYPE_START_ZSL;
   1961 
   1962         /* enqueue to cmd thread */
   1963         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1964 
   1965         /* wake up cmd thread */
   1966         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   1967     } else {
   1968         LOGE("No memory for mm_camera_node_t");
   1969         rc = -1;
   1970     }
   1971 
   1972     return rc;
   1973 }
   1974 
   1975 /*===========================================================================
   1976  * FUNCTION   : mm_channel_stop_zsl_snapshot
   1977  *
   1978  * DESCRIPTION: stop zsl snapshot
   1979  *
   1980  * PARAMETERS :
   1981  *   @my_obj  : channel object
   1982  *
   1983  * RETURN     : int32_t type of status
   1984  *              0  -- success
   1985  *              -1 -- failure
   1986  *==========================================================================*/
   1987 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj)
   1988 {
   1989     int32_t rc = 0;
   1990     mm_camera_cmdcb_t* node = NULL;
   1991 
   1992     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1993     if (NULL != node) {
   1994         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1995         node->cmd_type = MM_CAMERA_CMD_TYPE_STOP_ZSL;
   1996 
   1997         /* enqueue to cmd thread */
   1998         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1999 
   2000         /* wake up cmd thread */
   2001         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   2002     } else {
   2003         LOGE("No memory for mm_camera_node_t");
   2004         rc = -1;
   2005     }
   2006 
   2007     return rc;
   2008 }
   2009 
   2010 /*===========================================================================
   2011  * FUNCTION   : mm_channel_qbuf
   2012  *
   2013  * DESCRIPTION: enqueue buffer back to kernel
   2014  *
   2015  * PARAMETERS :
   2016  *   @my_obj       : channel object
   2017  *   @buf          : buf ptr to be enqueued
   2018  *
   2019  * RETURN     : int32_t type of status
   2020  *              0  -- success
   2021  *              -1 -- failure
   2022  *==========================================================================*/
   2023 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
   2024                         mm_camera_buf_def_t *buf)
   2025 {
   2026     int32_t rc = -1;
   2027     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id);
   2028 
   2029     if (NULL != s_obj) {
   2030         if (s_obj->ch_obj != my_obj) {
   2031             /* Redirect to linked stream */
   2032             rc = mm_stream_fsm_fn(s_obj->linked_stream,
   2033                     MM_STREAM_EVT_QBUF,
   2034                     (void *)buf,
   2035                     NULL);
   2036         } else {
   2037             rc = mm_stream_fsm_fn(s_obj,
   2038                     MM_STREAM_EVT_QBUF,
   2039                     (void *)buf,
   2040                     NULL);
   2041         }
   2042     }
   2043 
   2044     return rc;
   2045 }
   2046 
   2047 /*===========================================================================
   2048  * FUNCTION   : mm_channel_cancel_buf
   2049  *
   2050  * DESCRIPTION: Get back buffer already sent to kernel
   2051  *
   2052  * PARAMETERS :
   2053  *   @my_obj       : channel object
   2054  *   @buf          : buf ptr to be enqueued
   2055  *
   2056  * RETURN     : int32_t type of status
   2057  *              0  -- success
   2058  *              -1 -- failure
   2059  *==========================================================================*/
   2060 int32_t mm_channel_cancel_buf(mm_channel_t *my_obj,
   2061                         uint32_t stream_id, uint32_t buf_idx)
   2062 {
   2063     int32_t rc = -1;
   2064     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
   2065 
   2066     if (NULL != s_obj) {
   2067         if (s_obj->ch_obj != my_obj) {
   2068             /* Redirect to linked stream */
   2069             rc = mm_stream_fsm_fn(s_obj->linked_stream,
   2070                     MM_STREAM_EVT_CANCEL_BUF,
   2071                     (void *)&buf_idx,
   2072                     NULL);
   2073         } else {
   2074             rc = mm_stream_fsm_fn(s_obj,
   2075                     MM_STREAM_EVT_CANCEL_BUF,
   2076                     (void *)&buf_idx,
   2077                     NULL);
   2078         }
   2079     }
   2080 
   2081     return rc;
   2082 }
   2083 
   2084 
   2085 /*===========================================================================
   2086  * FUNCTION   : mm_channel_get_queued_buf_count
   2087  *
   2088  * DESCRIPTION: return queued buffer count
   2089  *
   2090  * PARAMETERS :
   2091  *   @my_obj       : channel object
   2092  *   @stream_id    : steam_id
   2093  *
   2094  * RETURN     : queued buffer count
   2095  *==========================================================================*/
   2096 int32_t mm_channel_get_queued_buf_count(mm_channel_t *my_obj, uint32_t stream_id)
   2097 {
   2098     int32_t rc = -1;
   2099     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
   2100 
   2101     if (NULL != s_obj) {
   2102         if (s_obj->ch_obj != my_obj) {
   2103             /* Redirect to linked stream */
   2104             rc = mm_stream_fsm_fn(s_obj->linked_stream,
   2105                     MM_STREAM_EVT_GET_QUEUED_BUF_COUNT,
   2106                     NULL,
   2107                     NULL);
   2108         } else {
   2109             rc = mm_stream_fsm_fn(s_obj,
   2110                     MM_STREAM_EVT_GET_QUEUED_BUF_COUNT,
   2111                     NULL,
   2112                     NULL);
   2113         }
   2114     }
   2115 
   2116     return rc;
   2117 }
   2118 
   2119 /*===========================================================================
   2120  * FUNCTION   : mm_channel_set_stream_parms
   2121  *
   2122  * DESCRIPTION: set parameters per stream
   2123  *
   2124  * PARAMETERS :
   2125  *   @my_obj       : channel object
   2126  *   @s_id         : stream handle
   2127  *   @parms        : ptr to a param struct to be set to server
   2128  *
   2129  * RETURN     : int32_t type of status
   2130  *              0  -- success
   2131  *              -1 -- failure
   2132  * NOTE       : Assume the parms struct buf is already mapped to server via
   2133  *              domain socket. Corresponding fields of parameters to be set
   2134  *              are already filled in by upper layer caller.
   2135  *==========================================================================*/
   2136 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
   2137                                    mm_evt_paylod_set_get_stream_parms_t *payload)
   2138 {
   2139     int32_t rc = -1;
   2140     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2141                                                                payload->stream_id);
   2142     if (NULL != s_obj) {
   2143         if (s_obj->ch_obj != my_obj) {
   2144             /* No op. on linked streams */
   2145             return 0;
   2146         }
   2147 
   2148         rc = mm_stream_fsm_fn(s_obj,
   2149                               MM_STREAM_EVT_SET_PARM,
   2150                               (void *)payload,
   2151                               NULL);
   2152     }
   2153 
   2154     return rc;
   2155 }
   2156 
   2157 /*===========================================================================
   2158  * FUNCTION   : mm_channel_get_stream_parms
   2159  *
   2160  * DESCRIPTION: get parameters per stream
   2161  *
   2162  * PARAMETERS :
   2163  *   @my_obj       : channel object
   2164  *   @s_id         : stream handle
   2165  *   @parms        : ptr to a param struct to be get from server
   2166  *
   2167  * RETURN     : int32_t type of status
   2168  *              0  -- success
   2169  *              -1 -- failure
   2170  * NOTE       : Assume the parms struct buf is already mapped to server via
   2171  *              domain socket. Parameters to be get from server are already
   2172  *              filled in by upper layer caller. After this call, corresponding
   2173  *              fields of requested parameters will be filled in by server with
   2174  *              detailed information.
   2175  *==========================================================================*/
   2176 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
   2177                                    mm_evt_paylod_set_get_stream_parms_t *payload)
   2178 {
   2179     int32_t rc = -1;
   2180     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2181                                                                payload->stream_id);
   2182     if (NULL != s_obj) {
   2183         if (s_obj->ch_obj != my_obj) {
   2184             /* No op. on linked streams */
   2185             return 0;
   2186         }
   2187 
   2188         rc = mm_stream_fsm_fn(s_obj,
   2189                               MM_STREAM_EVT_GET_PARM,
   2190                               (void *)payload,
   2191                               NULL);
   2192     }
   2193 
   2194     return rc;
   2195 }
   2196 
   2197 /*===========================================================================
   2198  * FUNCTION   : mm_channel_do_stream_action
   2199  *
   2200  * DESCRIPTION: request server to perform stream based action. Maybe removed later
   2201  *              if the functionality is included in mm_camera_set_parms
   2202  *
   2203  * PARAMETERS :
   2204  *   @my_obj       : channel object
   2205  *   @s_id         : stream handle
   2206  *   @actions      : ptr to an action struct buf to be performed by server
   2207  *
   2208  * RETURN     : int32_t type of status
   2209  *              0  -- success
   2210  *              -1 -- failure
   2211  * NOTE       : Assume the action struct buf is already mapped to server via
   2212  *              domain socket. Actions to be performed by server are already
   2213  *              filled in by upper layer caller.
   2214  *==========================================================================*/
   2215 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
   2216                                    mm_evt_paylod_do_stream_action_t *payload)
   2217 {
   2218     int32_t rc = -1;
   2219     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2220                                                                payload->stream_id);
   2221     if (NULL != s_obj) {
   2222         if (s_obj->ch_obj != my_obj) {
   2223             /* No op. on linked streams */
   2224             return 0;
   2225         }
   2226 
   2227         rc = mm_stream_fsm_fn(s_obj,
   2228                               MM_STREAM_EVT_DO_ACTION,
   2229                               (void *)payload,
   2230                               NULL);
   2231     }
   2232 
   2233     return rc;
   2234 }
   2235 
   2236 /*===========================================================================
   2237  * FUNCTION   : mm_channel_map_stream_buf
   2238  *
   2239  * DESCRIPTION: mapping stream buffer via domain socket to server
   2240  *
   2241  * PARAMETERS :
   2242  *   @my_obj       : channel object
   2243  *   @payload      : ptr to payload for mapping
   2244  *
   2245  * RETURN     : int32_t type of status
   2246  *              0  -- success
   2247  *              -1 -- failure
   2248  *==========================================================================*/
   2249 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
   2250                                   cam_buf_map_type *payload)
   2251 {
   2252     int32_t rc = -1;
   2253     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2254             payload->stream_id);
   2255     if (NULL != s_obj) {
   2256         if (s_obj->ch_obj != my_obj) {
   2257             /* No op. on linked streams */
   2258             return 0;
   2259         }
   2260         rc = mm_stream_map_buf(s_obj,
   2261                 payload->type, payload->frame_idx,
   2262                 payload->plane_idx, payload->fd,
   2263                 payload->size, payload->buffer);
   2264     }
   2265 
   2266     return rc;
   2267 }
   2268 
   2269 /*===========================================================================
   2270  * FUNCTION   : mm_channel_map_stream_bufs
   2271  *
   2272  * DESCRIPTION: mapping stream buffers via domain socket to server
   2273  *
   2274  * PARAMETERS :
   2275  *   @my_obj       : channel object
   2276  *   @payload      : ptr to payload for mapping
   2277  *
   2278  * RETURN     : int32_t type of status
   2279  *              0  -- success
   2280  *              -1 -- failure
   2281  *==========================================================================*/
   2282 int32_t mm_channel_map_stream_bufs(mm_channel_t *my_obj,
   2283                                    cam_buf_map_type_list *payload)
   2284 {
   2285     int32_t rc = -1;
   2286     if ((payload == NULL) || (payload->length == 0)) {
   2287         return rc;
   2288     }
   2289 
   2290     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2291                                                                payload->buf_maps[0].stream_id);
   2292     if (NULL != s_obj) {
   2293         if (s_obj->ch_obj != my_obj) {
   2294             /* No op. on linked streams */
   2295             return 0;
   2296         }
   2297 
   2298         rc = mm_stream_map_bufs(s_obj, payload);
   2299     }
   2300 
   2301     return rc;
   2302 }
   2303 
   2304 /*===========================================================================
   2305  * FUNCTION   : mm_channel_unmap_stream_buf
   2306  *
   2307  * DESCRIPTION: unmapping stream buffer via domain socket to server
   2308  *
   2309  * PARAMETERS :
   2310  *   @my_obj       : channel object
   2311  *   @payload      : ptr to unmap payload
   2312  *
   2313  * RETURN     : int32_t type of status
   2314  *              0  -- success
   2315  *              -1 -- failure
   2316  *==========================================================================*/
   2317 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
   2318                                     cam_buf_unmap_type *payload)
   2319 {
   2320     int32_t rc = -1;
   2321     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2322                                                                payload->stream_id);
   2323     if (NULL != s_obj) {
   2324         if (s_obj->ch_obj != my_obj) {
   2325             /* No op. on linked streams */
   2326             return 0;
   2327         }
   2328 
   2329         rc = mm_stream_unmap_buf(s_obj, payload->type,
   2330                                  payload->frame_idx, payload->plane_idx);
   2331     }
   2332 
   2333     return rc;
   2334 }
   2335 
   2336 /*===========================================================================
   2337  * FUNCTION   : mm_channel_superbuf_queue_init
   2338  *
   2339  * DESCRIPTION: initialize superbuf queue in the channel
   2340  *
   2341  * PARAMETERS :
   2342  *   @queue   : ptr to superbuf queue to be initialized
   2343  *
   2344  * RETURN     : int32_t type of status
   2345  *              0  -- success
   2346  *              -1 -- failure
   2347  *==========================================================================*/
   2348 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)
   2349 {
   2350     return cam_queue_init(&queue->que);
   2351 }
   2352 
   2353 /*===========================================================================
   2354  * FUNCTION   : mm_channel_superbuf_queue_deinit
   2355  *
   2356  * DESCRIPTION: deinitialize superbuf queue in the channel
   2357  *
   2358  * PARAMETERS :
   2359  *   @queue   : ptr to superbuf queue to be deinitialized
   2360  *
   2361  * RETURN     : int32_t type of status
   2362  *              0  -- success
   2363  *              -1 -- failure
   2364  *==========================================================================*/
   2365 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)
   2366 {
   2367     return cam_queue_deinit(&queue->que);
   2368 }
   2369 
   2370 /*===========================================================================
   2371  * FUNCTION   : mm_channel_util_seq_comp_w_rollover
   2372  *
   2373  * DESCRIPTION: utility function to handle sequence number comparison with rollover
   2374  *
   2375  * PARAMETERS :
   2376  *   @v1      : first value to be compared
   2377  *   @v2      : second value to be compared
   2378  *
   2379  * RETURN     : int8_t type of comparison result
   2380  *              >0  -- v1 larger than v2
   2381  *              =0  -- vi equal to v2
   2382  *              <0  -- v1 smaller than v2
   2383  *==========================================================================*/
   2384 int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1,
   2385                                            uint32_t v2)
   2386 {
   2387     int8_t ret = 0;
   2388 
   2389     /* TODO: need to handle the case if v2 roll over to 0 */
   2390     if (v1 > v2) {
   2391         ret = 1;
   2392     } else if (v1 < v2) {
   2393         ret = -1;
   2394     }
   2395 
   2396     return ret;
   2397 }
   2398 
   2399 /*===========================================================================
   2400  * FUNCTION   : mm_channel_validate_super_buf.
   2401  *
   2402  * DESCRIPTION: Validate incoming buffer with existing super buffer.
   2403  *
   2404  * PARAMETERS :
   2405  *   @ch_obj  : channel object
   2406  *   @queue   : superbuf queue
   2407  *   @buf_info: new buffer from stream
   2408  *
   2409  * RETURN     : int8_t type of validation result
   2410  *              >0  -- Valid frame
   2411  *              =0  -- Cannot validate
   2412  *              <0  -- Invalid frame. Can be freed
   2413  *==========================================================================*/
   2414 int8_t mm_channel_validate_super_buf(__unused mm_channel_t* ch_obj,
   2415         mm_channel_queue_t *queue, mm_camera_buf_info_t *buf_info)
   2416 {
   2417     int8_t ret = 0;
   2418     cam_node_t* node = NULL;
   2419     struct cam_list *head = NULL;
   2420     struct cam_list *pos = NULL;
   2421     mm_channel_queue_node_t* super_buf = NULL;
   2422 
   2423     (void)ch_obj;
   2424 
   2425     /* comp */
   2426     pthread_mutex_lock(&queue->que.lock);
   2427     head = &queue->que.head.list;
   2428     /* get the last one in the queue which is possibly having no matching */
   2429     pos = head->next;
   2430     while (pos != head) {
   2431         node = member_of(pos, cam_node_t, list);
   2432         super_buf = (mm_channel_queue_node_t*)node->data;
   2433         if (NULL != super_buf) {
   2434             if ((super_buf->expected_frame) &&
   2435                     (buf_info->frame_idx == super_buf->frame_idx)) {
   2436                 //This is good frame. Expecting more frames. Keeping this frame.
   2437                 ret = 1;
   2438                 break;
   2439             } else {
   2440                 pos = pos->next;
   2441                 continue;
   2442             }
   2443         }
   2444     }
   2445     pthread_mutex_unlock(&queue->que.lock);
   2446     return ret;
   2447 }
   2448 
   2449 /*===========================================================================
   2450  * FUNCTION   : mm_channel_handle_metadata
   2451  *
   2452  * DESCRIPTION: Handle frame matching logic change due to metadata
   2453  *
   2454  * PARAMETERS :
   2455  *   @ch_obj  : channel object
   2456  *   @queue   : superbuf queue
   2457  *   @buf_info: new buffer from stream
   2458  *
   2459  * RETURN     : int32_t type of status
   2460  *              0  -- success
   2461  *              -1 -- failure
   2462  *==========================================================================*/
   2463 int32_t mm_channel_handle_metadata(
   2464                         mm_channel_t* ch_obj,
   2465                         mm_channel_queue_t * queue,
   2466                         mm_camera_buf_info_t *buf_info)
   2467 {
   2468 
   2469     int rc = 0 ;
   2470     mm_stream_t* stream_obj = NULL;
   2471     stream_obj = mm_channel_util_get_stream_by_handler(ch_obj,
   2472                 buf_info->stream_id);
   2473     uint8_t is_prep_snapshot_done_valid = 0;
   2474     uint8_t is_good_frame_idx_range_valid = 0;
   2475     int32_t prep_snapshot_done_state = 0;
   2476     cam_frame_idx_range_t good_frame_idx_range;
   2477     uint8_t is_crop_1x_found = 0;
   2478     uint32_t snapshot_stream_id = 0;
   2479     uint32_t i;
   2480     /* Set expected frame id to a future frame idx, large enough to wait
   2481     * for good_frame_idx_range, and small enough to still capture an image */
   2482     const uint32_t max_future_frame_offset = MM_CAMERA_MAX_FUTURE_FRAME_WAIT;
   2483 
   2484     memset(&good_frame_idx_range, 0, sizeof(good_frame_idx_range));
   2485 
   2486     if (NULL == stream_obj) {
   2487         LOGE("Invalid Stream Object for stream_id = %d",
   2488                     buf_info->stream_id);
   2489         rc = -1;
   2490         goto end;
   2491     }
   2492     if (NULL == stream_obj->stream_info) {
   2493         LOGE("NULL stream info for stream_id = %d",
   2494                      buf_info->stream_id);
   2495         rc = -1;
   2496         goto end;
   2497     }
   2498 
   2499     if ((CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) &&
   2500             ((stream_obj->ch_obj == ch_obj) ||
   2501             ((stream_obj->linked_stream != NULL) &&
   2502             (stream_obj->linked_stream->linked_obj == ch_obj)))) {
   2503         const metadata_buffer_t *metadata;
   2504         metadata = (const metadata_buffer_t *)buf_info->buf->buffer;
   2505 
   2506         if (NULL == metadata) {
   2507             LOGE("NULL metadata buffer for metadata stream");
   2508             rc = -1;
   2509             goto end;
   2510         }
   2511         LOGL("E , expected frame id: %d", queue->expected_frame_id);
   2512 
   2513         IF_META_AVAILABLE(const int32_t, p_prep_snapshot_done_state,
   2514                 CAM_INTF_META_PREP_SNAPSHOT_DONE, metadata) {
   2515             prep_snapshot_done_state = *p_prep_snapshot_done_state;
   2516             is_prep_snapshot_done_valid = 1;
   2517             LOGH("prepare snapshot done valid ");
   2518         }
   2519         IF_META_AVAILABLE(const cam_frame_idx_range_t, p_good_frame_idx_range,
   2520                 CAM_INTF_META_GOOD_FRAME_IDX_RANGE, metadata) {
   2521             good_frame_idx_range = *p_good_frame_idx_range;
   2522             is_good_frame_idx_range_valid = 1;
   2523             LOGH("good_frame_idx_range : min: %d, max: %d , num frames = %d",
   2524                  good_frame_idx_range.min_frame_idx,
   2525                 good_frame_idx_range.max_frame_idx, good_frame_idx_range.num_led_on_frames);
   2526         }
   2527         IF_META_AVAILABLE(const cam_crop_data_t, p_crop_data,
   2528                 CAM_INTF_META_CROP_DATA, metadata) {
   2529             cam_crop_data_t crop_data = *p_crop_data;
   2530 
   2531             for (i = 0; i < ARRAY_SIZE(ch_obj->streams); i++) {
   2532                 if (MM_STREAM_STATE_NOTUSED == ch_obj->streams[i].state) {
   2533                     continue;
   2534                 }
   2535                 if (CAM_STREAM_TYPE_SNAPSHOT ==
   2536                     ch_obj->streams[i].stream_info->stream_type) {
   2537                     snapshot_stream_id = ch_obj->streams[i].server_stream_id;
   2538                     break;
   2539                 }
   2540             }
   2541 
   2542             for (i=0; i<crop_data.num_of_streams; i++) {
   2543                 if (snapshot_stream_id == crop_data.crop_info[i].stream_id) {
   2544                     if (!crop_data.crop_info[i].crop.left &&
   2545                             !crop_data.crop_info[i].crop.top) {
   2546                         is_crop_1x_found = 1;
   2547                         break;
   2548                     }
   2549                 }
   2550             }
   2551         }
   2552 
   2553         IF_META_AVAILABLE(const cam_buf_divert_info_t, p_divert_info,
   2554                 CAM_INTF_BUF_DIVERT_INFO, metadata) {
   2555             cam_buf_divert_info_t divert_info = *p_divert_info;
   2556             if (divert_info.frame_id >= buf_info->frame_idx) {
   2557                 ch_obj->diverted_frame_id = divert_info.frame_id;
   2558             } else {
   2559                 ch_obj->diverted_frame_id = 0;
   2560             }
   2561         }
   2562 
   2563         if (ch_obj->isZoom1xFrameRequested) {
   2564             if (is_crop_1x_found) {
   2565                 ch_obj->isZoom1xFrameRequested = 0;
   2566                 queue->expected_frame_id = buf_info->frame_idx + 1;
   2567             } else {
   2568                 queue->expected_frame_id += max_future_frame_offset;
   2569                 /* Flush unwanted frames */
   2570                 mm_channel_superbuf_flush_matched(ch_obj, queue);
   2571             }
   2572             goto end;
   2573         }
   2574 
   2575         if (ch_obj->startZSlSnapshotCalled && is_good_frame_idx_range_valid) {
   2576             LOGI("frameID = %d, expected = %d good_frame_idx = %d",
   2577                     buf_info->frame_idx, queue->expected_frame_id,
   2578                     good_frame_idx_range.min_frame_idx);
   2579         }
   2580 
   2581         if (is_prep_snapshot_done_valid) {
   2582             ch_obj->bWaitForPrepSnapshotDone = 0;
   2583             if (prep_snapshot_done_state == NEED_FUTURE_FRAME) {
   2584                 queue->expected_frame_id += max_future_frame_offset;
   2585                 LOGI("PreFlash Done. Need Main Flash");
   2586 
   2587                 mm_channel_superbuf_flush(ch_obj,
   2588                         queue, CAM_STREAM_TYPE_DEFAULT);
   2589 
   2590                 ch_obj->needLEDFlash = TRUE;
   2591             } else {
   2592                 ch_obj->needLEDFlash = FALSE;
   2593             }
   2594         }
   2595         if (is_good_frame_idx_range_valid) {
   2596             queue->expected_frame_id =
   2597                 good_frame_idx_range.min_frame_idx;
   2598             queue->good_frame_id = good_frame_idx_range.min_frame_idx;
   2599             if((ch_obj->needLEDFlash == TRUE) && (ch_obj->burstSnapNum > 1)) {
   2600                 queue->led_on_start_frame_id =
   2601                 good_frame_idx_range.min_frame_idx;
   2602                 queue->led_off_start_frame_id =
   2603                 good_frame_idx_range.max_frame_idx;
   2604                 queue->once = 0;
   2605                 queue->led_on_num_frames =
   2606                   good_frame_idx_range.num_led_on_frames;
   2607                 queue->frame_skip_count = good_frame_idx_range.frame_skip_count;
   2608                 LOGD("Need Flash, expected frame id = %d,"
   2609                         " led_on start = %d, led off start = %d, led on frames = %d ",
   2610                            queue->expected_frame_id, queue->led_on_start_frame_id,
   2611                         queue->led_off_start_frame_id, queue->led_on_num_frames);
   2612             } else {
   2613                 LOGD("No flash, expected frame id = %d ",
   2614                          queue->expected_frame_id);
   2615             }
   2616         } else if ((MM_CHANNEL_BRACKETING_STATE_WAIT_GOOD_FRAME_IDX == ch_obj->bracketingState) &&
   2617                 !is_prep_snapshot_done_valid) {
   2618             /* Flush unwanted frames */
   2619             mm_channel_superbuf_flush_matched(ch_obj, queue);
   2620             queue->expected_frame_id += max_future_frame_offset;
   2621         }
   2622         if (ch_obj->isFlashBracketingEnabled &&
   2623             is_good_frame_idx_range_valid) {
   2624             /* Flash bracketing needs two frames, with & without led flash.
   2625             * in valid range min frame is with led flash and max frame is
   2626             * without led flash */
   2627             queue->expected_frame_id =
   2628                     good_frame_idx_range.min_frame_idx;
   2629             /* max frame is without led flash */
   2630             queue->expected_frame_id_without_led =
   2631                     good_frame_idx_range.max_frame_idx;
   2632             queue->good_frame_id =
   2633                     good_frame_idx_range.min_frame_idx;
   2634         } else if (is_good_frame_idx_range_valid) {
   2635             queue->expected_frame_id =
   2636                     good_frame_idx_range.min_frame_idx;
   2637             ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_ACTIVE;
   2638             queue->good_frame_id =
   2639                     good_frame_idx_range.min_frame_idx;
   2640         }
   2641 
   2642         if (ch_obj->isConfigCapture && is_good_frame_idx_range_valid
   2643                 && (good_frame_idx_range.config_batch_idx < ch_obj->frameConfig.num_batch)) {
   2644 
   2645             LOGI("Frame Config: Expcted ID = %d batch index = %d",
   2646                     good_frame_idx_range.min_frame_idx, good_frame_idx_range.config_batch_idx);
   2647             ch_obj->capture_frame_id[good_frame_idx_range.config_batch_idx] =
   2648                     good_frame_idx_range.min_frame_idx;
   2649 
   2650             if (ch_obj->cur_capture_idx == good_frame_idx_range.config_batch_idx) {
   2651                 queue->expected_frame_id =
   2652                         good_frame_idx_range.min_frame_idx;
   2653             } else {
   2654                 queue->expected_frame_id =
   2655                         ch_obj->capture_frame_id[ch_obj->cur_capture_idx];
   2656             }
   2657             queue->good_frame_id = queue->expected_frame_id;
   2658         }
   2659 
   2660         if ((ch_obj->burstSnapNum > 1) && (ch_obj->needLEDFlash == TRUE)
   2661             && !ch_obj->isFlashBracketingEnabled
   2662             && (MM_CHANNEL_BRACKETING_STATE_OFF == ch_obj->bracketingState)
   2663             && !ch_obj->isConfigCapture) {
   2664             if((buf_info->frame_idx >= queue->led_off_start_frame_id)
   2665                     &&  !queue->once) {
   2666                 LOGD("Burst snap num = %d ",
   2667                          ch_obj->burstSnapNum);
   2668                 // Skip frames from LED OFF frame to get a good frame
   2669                 queue->expected_frame_id = queue->led_off_start_frame_id +
   2670                         queue->frame_skip_count;
   2671                 queue->once = 1;
   2672                 ch_obj->stopZslSnapshot = 1;
   2673                 ch_obj->needLEDFlash = FALSE;
   2674                 LOGD("Reached max led on frames = %d , expected id = %d",
   2675                          buf_info->frame_idx, queue->expected_frame_id);
   2676          }
   2677        }
   2678 
   2679         IF_META_AVAILABLE(const cam_low_light_mode_t, low_light_level,
   2680             CAM_INTF_META_LOW_LIGHT, metadata) {
   2681             ch_obj->needLowLightZSL = *low_light_level;
   2682         }
   2683 
   2684         // For the instant capture case, if AEC settles before expected frame ID from user,
   2685         // reset the expected frame ID to current frame index.
   2686         if (queue->attr.user_expected_frame_id > 0) {
   2687             if (queue->attr.user_expected_frame_id > buf_info->frame_idx) {
   2688                 IF_META_AVAILABLE(const cam_3a_params_t, ae_params,
   2689                     CAM_INTF_META_AEC_INFO, metadata) {
   2690                     if (ae_params->settled) {
   2691                         queue->expected_frame_id = buf_info->frame_idx;
   2692                         // Reset the expected frame ID from HAL to 0
   2693                         queue->attr.user_expected_frame_id = 0;
   2694                         LOGD("AEC settled, reset expected frame ID from user");
   2695                     }
   2696                 }
   2697             } else {
   2698                  // Reset the expected frame ID from HAL to 0 after
   2699                  // current frame index is greater than expected id.
   2700                 queue->attr.user_expected_frame_id = 0;
   2701                 LOGD("reset expected frame ID from user as it reached the bound");
   2702             }
   2703         }
   2704     }
   2705 end:
   2706     return rc;
   2707 }
   2708 
   2709 /*===========================================================================
   2710  * FUNCTION   : mm_channel_superbuf_comp_and_enqueue
   2711  *
   2712  * DESCRIPTION: implementation for matching logic for superbuf
   2713  *
   2714  * PARAMETERS :
   2715  *   @ch_obj  : channel object
   2716  *   @queue   : superbuf queue
   2717  *   @buf_info: new buffer from stream
   2718  *
   2719  * RETURN     : int32_t type of status
   2720  *              0  -- success
   2721  *              -1 -- failure
   2722  *==========================================================================*/
   2723 int32_t mm_channel_superbuf_comp_and_enqueue(
   2724                         mm_channel_t* ch_obj,
   2725                         mm_channel_queue_t *queue,
   2726                         mm_camera_buf_info_t *buf_info)
   2727 {
   2728     cam_node_t* node = NULL;
   2729     struct cam_list *head = NULL;
   2730     struct cam_list *pos = NULL;
   2731     mm_channel_queue_node_t* super_buf = NULL;
   2732     uint8_t buf_s_idx, i, found_super_buf, unmatched_bundles;
   2733     struct cam_list *last_buf, *insert_before_buf, *last_buf_ptr;
   2734 
   2735     LOGD("E");
   2736 
   2737     for (buf_s_idx = 0; buf_s_idx < queue->num_streams; buf_s_idx++) {
   2738         if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) {
   2739             break;
   2740         }
   2741     }
   2742 
   2743     if (buf_s_idx == queue->num_streams) {
   2744         LOGE("buf from stream (%d) not bundled", buf_info->stream_id);
   2745         return -1;
   2746     }
   2747 
   2748     if(buf_info->frame_idx == 0) {
   2749         mm_channel_qbuf(ch_obj, buf_info->buf);
   2750         return 0;
   2751     }
   2752 
   2753     if (mm_channel_handle_metadata(ch_obj, queue, buf_info) < 0) {
   2754         mm_channel_qbuf(ch_obj, buf_info->buf);
   2755         return -1;
   2756     }
   2757 
   2758     if ((mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx,
   2759             queue->expected_frame_id) < 0) &&
   2760             (mm_channel_validate_super_buf(ch_obj, queue, buf_info) <= 0)) {
   2761         LOGH("incoming buf id(%d) is older than expected buf id(%d), will discard it",
   2762                  buf_info->frame_idx, queue->expected_frame_id);
   2763         mm_channel_qbuf(ch_obj, buf_info->buf);
   2764         return 0;
   2765     }
   2766 
   2767     /* comp */
   2768     pthread_mutex_lock(&queue->que.lock);
   2769     head = &queue->que.head.list;
   2770     /* get the last one in the queue which is possibly having no matching */
   2771     pos = head->next;
   2772 
   2773     found_super_buf = 0;
   2774     unmatched_bundles = 0;
   2775     last_buf = NULL;
   2776     insert_before_buf = NULL;
   2777     last_buf_ptr = NULL;
   2778 
   2779     while (pos != head) {
   2780         node = member_of(pos, cam_node_t, list);
   2781         super_buf = (mm_channel_queue_node_t*)node->data;
   2782 
   2783         if (NULL != super_buf) {
   2784             if (super_buf->matched) {
   2785                 /* find a matched super buf, move to next one */
   2786                 pos = pos->next;
   2787                 continue;
   2788             } else if (( buf_info->frame_idx == super_buf->frame_idx )
   2789                     /*Pick metadata greater than available frameID*/
   2790                     || ((queue->attr.priority == MM_CAMERA_SUPER_BUF_PRIORITY_LOW)
   2791                     && (super_buf->super_buf[buf_s_idx].frame_idx == 0)
   2792                     && (buf_info->buf->stream_type == CAM_STREAM_TYPE_METADATA)
   2793                     && (super_buf->frame_idx < buf_info->frame_idx))
   2794                     /*Pick available metadata closest to frameID*/
   2795                     || ((queue->attr.priority == MM_CAMERA_SUPER_BUF_PRIORITY_LOW)
   2796                     && (buf_info->buf->stream_type != CAM_STREAM_TYPE_METADATA)
   2797                     && (super_buf->super_buf[buf_s_idx].frame_idx == 0)
   2798                     && (super_buf->unmatched_meta_idx > buf_info->frame_idx))){
   2799                 /*super buffer frame IDs matching OR In low priority bundling
   2800                 metadata frameID greater than avialbale super buffer frameID  OR
   2801                 metadata frame closest to incoming frameID will be bundled*/
   2802                 found_super_buf = 1;
   2803                 /* If we are filling into a 'meta only' superbuf, make sure to reset
   2804                 the super_buf frame_idx so that missing streams in this superbuf
   2805                 are filled as per matching frame id logic. Note that, in low priority
   2806                 queue, only meta frame id need not match (closest suffices) but
   2807                 the other streams in this superbuf should have same frame id. */
   2808                 if (super_buf->unmatched_meta_idx > 0) {
   2809                     super_buf->unmatched_meta_idx = 0;
   2810                     super_buf->frame_idx = buf_info->frame_idx;
   2811                 }
   2812                 break;
   2813             } else {
   2814                 unmatched_bundles++;
   2815                 if ( NULL == last_buf ) {
   2816                     if ( super_buf->frame_idx < buf_info->frame_idx ) {
   2817                         last_buf = pos;
   2818                     }
   2819                 }
   2820                 if ( NULL == insert_before_buf ) {
   2821                     if ( super_buf->frame_idx > buf_info->frame_idx ) {
   2822                         insert_before_buf = pos;
   2823                     }
   2824                 }
   2825                 pos = pos->next;
   2826             }
   2827         }
   2828     }
   2829 
   2830     if ( found_super_buf ) {
   2831         if(super_buf->super_buf[buf_s_idx].frame_idx != 0) {
   2832             //This can cause frame drop. We are overwriting same memory.
   2833             pthread_mutex_unlock(&queue->que.lock);
   2834             LOGW("Warning: frame is already in camera ZSL queue");
   2835             mm_channel_qbuf(ch_obj, buf_info->buf);
   2836             return 0;
   2837         }
   2838 
   2839         /*Insert incoming buffer to super buffer*/
   2840         super_buf->super_buf[buf_s_idx] = *buf_info;
   2841 
   2842         /* check if superbuf is all matched */
   2843         super_buf->matched = 1;
   2844         for (i=0; i < super_buf->num_of_bufs; i++) {
   2845             if (super_buf->super_buf[i].frame_idx == 0) {
   2846                 super_buf->matched = 0;
   2847                 break;
   2848             }
   2849         }
   2850 
   2851         if (super_buf->matched) {
   2852             if(ch_obj->isFlashBracketingEnabled) {
   2853                queue->expected_frame_id =
   2854                    queue->expected_frame_id_without_led;
   2855                if (buf_info->frame_idx >=
   2856                        queue->expected_frame_id_without_led) {
   2857                    ch_obj->isFlashBracketingEnabled = FALSE;
   2858                }
   2859             } else {
   2860                queue->expected_frame_id = buf_info->frame_idx
   2861                                           + queue->attr.post_frame_skip;
   2862             }
   2863 
   2864             super_buf->expected_frame = FALSE;
   2865 
   2866             LOGD("curr = %d, skip = %d , Expected Frame ID: %d",
   2867                      buf_info->frame_idx,
   2868                     queue->attr.post_frame_skip, queue->expected_frame_id);
   2869 
   2870             queue->match_cnt++;
   2871             if (ch_obj->bundle.superbuf_queue.attr.enable_frame_sync) {
   2872                 pthread_mutex_lock(&fs_lock);
   2873                 mm_frame_sync_add(buf_info->frame_idx, ch_obj);
   2874                 pthread_mutex_unlock(&fs_lock);
   2875             }
   2876             /* Any older unmatched buffer need to be released */
   2877             if ( last_buf ) {
   2878                 while ( last_buf != pos ) {
   2879                     node = member_of(last_buf, cam_node_t, list);
   2880                     super_buf = (mm_channel_queue_node_t*)node->data;
   2881                     if (NULL != super_buf) {
   2882                         for (i=0; i<super_buf->num_of_bufs; i++) {
   2883                             if (super_buf->super_buf[i].frame_idx != 0) {
   2884                                 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   2885                             }
   2886                         }
   2887                         queue->que.size--;
   2888                         last_buf = last_buf->next;
   2889                         cam_list_del_node(&node->list);
   2890                         free(node);
   2891                         free(super_buf);
   2892                     } else {
   2893                         LOGE("Invalid superbuf in queue!");
   2894                         break;
   2895                     }
   2896                 }
   2897             }
   2898         }else {
   2899             if (ch_obj->diverted_frame_id == buf_info->frame_idx) {
   2900                 super_buf->expected_frame = TRUE;
   2901                 ch_obj->diverted_frame_id = 0;
   2902             }
   2903         }
   2904     } else {
   2905         if ((queue->attr.max_unmatched_frames < unmatched_bundles)
   2906                 && ( NULL == last_buf )) {
   2907             /* incoming frame is older than the last bundled one */
   2908             mm_channel_qbuf(ch_obj, buf_info->buf);
   2909         } else {
   2910             last_buf_ptr = last_buf;
   2911 
   2912             /* Loop to remove unmatched frames */
   2913             while ((queue->attr.max_unmatched_frames < unmatched_bundles)
   2914                     && (last_buf_ptr != NULL && last_buf_ptr != pos)) {
   2915                 node = member_of(last_buf_ptr, cam_node_t, list);
   2916                 super_buf = (mm_channel_queue_node_t*)node->data;
   2917                 if (NULL != super_buf && super_buf->expected_frame == FALSE
   2918                         && (&node->list != insert_before_buf)) {
   2919                     for (i=0; i<super_buf->num_of_bufs; i++) {
   2920                         if (super_buf->super_buf[i].frame_idx != 0) {
   2921                             mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   2922                         }
   2923                     }
   2924                     queue->que.size--;
   2925                     cam_list_del_node(&node->list);
   2926                     free(node);
   2927                     free(super_buf);
   2928                     unmatched_bundles--;
   2929                 }
   2930                 last_buf_ptr = last_buf_ptr->next;
   2931             }
   2932 
   2933             if (queue->attr.max_unmatched_frames < unmatched_bundles) {
   2934                 node = member_of(last_buf, cam_node_t, list);
   2935                 super_buf = (mm_channel_queue_node_t*)node->data;
   2936                 for (i=0; i<super_buf->num_of_bufs; i++) {
   2937                     if (super_buf->super_buf[i].frame_idx != 0) {
   2938                         mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   2939                     }
   2940                 }
   2941                 queue->que.size--;
   2942                 cam_list_del_node(&node->list);
   2943                 free(node);
   2944                 free(super_buf);
   2945             }
   2946 
   2947             /* insert the new frame at the appropriate position. */
   2948 
   2949             mm_channel_queue_node_t *new_buf = NULL;
   2950             cam_node_t* new_node = NULL;
   2951 
   2952             new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t));
   2953             new_node = (cam_node_t*)malloc(sizeof(cam_node_t));
   2954             if (NULL != new_buf && NULL != new_node) {
   2955                 memset(new_buf, 0, sizeof(mm_channel_queue_node_t));
   2956                 memset(new_node, 0, sizeof(cam_node_t));
   2957                 new_node->data = (void *)new_buf;
   2958                 new_buf->num_of_bufs = queue->num_streams;
   2959                 new_buf->super_buf[buf_s_idx] = *buf_info;
   2960                 new_buf->frame_idx = buf_info->frame_idx;
   2961 
   2962                 if ((ch_obj->diverted_frame_id == buf_info->frame_idx)
   2963                         || (buf_info->frame_idx == queue->good_frame_id)) {
   2964                     new_buf->expected_frame = TRUE;
   2965                     ch_obj->diverted_frame_id = 0;
   2966                 }
   2967 
   2968                 /* enqueue */
   2969                 if ( insert_before_buf ) {
   2970                     cam_list_insert_before_node(&new_node->list, insert_before_buf);
   2971                 } else {
   2972                     cam_list_add_tail_node(&new_node->list, &queue->que.head.list);
   2973                 }
   2974                 queue->que.size++;
   2975 
   2976                 if(queue->num_streams == 1) {
   2977                     new_buf->matched = 1;
   2978                     new_buf->expected_frame = FALSE;
   2979                     queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
   2980                     queue->match_cnt++;
   2981                     if (ch_obj->bundle.superbuf_queue.attr.enable_frame_sync) {
   2982                         pthread_mutex_lock(&fs_lock);
   2983                         mm_frame_sync_add(buf_info->frame_idx, ch_obj);
   2984                         pthread_mutex_unlock(&fs_lock);
   2985                     }
   2986                 }
   2987                 /* In low priority queue, this will become a 'meta only' superbuf. Set the
   2988                 unmatched_frame_idx so that the upcoming stream buffers (other than meta)
   2989                 can be filled into this which are nearest to this idx. */
   2990                 if ((queue->attr.priority == MM_CAMERA_SUPER_BUF_PRIORITY_LOW)
   2991                     && (buf_info->buf->stream_type == CAM_STREAM_TYPE_METADATA)) {
   2992                     new_buf->unmatched_meta_idx = buf_info->frame_idx;
   2993                 }
   2994             } else {
   2995                 /* No memory */
   2996                 if (NULL != new_buf) {
   2997                     free(new_buf);
   2998                 }
   2999                 if (NULL != new_node) {
   3000                     free(new_node);
   3001                 }
   3002                 /* qbuf the new buf since we cannot enqueue */
   3003                 mm_channel_qbuf(ch_obj, buf_info->buf);
   3004             }
   3005         }
   3006     }
   3007 
   3008     pthread_mutex_unlock(&queue->que.lock);
   3009     LOGD("X");
   3010     return 0;
   3011 }
   3012 
   3013 /*===========================================================================
   3014  * FUNCTION   : mm_channel_superbuf_dequeue_internal
   3015  *
   3016  * DESCRIPTION: internal implementation for dequeue from the superbuf queue
   3017  *
   3018  * PARAMETERS :
   3019  *   @queue   : superbuf queue
   3020  *   @matched_only : if dequeued buf should be matched
   3021  *   @ch_obj  : channel object
   3022  *
   3023  * RETURN     : ptr to a node from superbuf queue
   3024  *==========================================================================*/
   3025 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(
   3026         mm_channel_queue_t * queue,
   3027         uint8_t matched_only, mm_channel_t *ch_obj)
   3028 {
   3029     cam_node_t* node = NULL;
   3030     struct cam_list *head = NULL;
   3031     struct cam_list *pos = NULL;
   3032     mm_channel_queue_node_t* super_buf = NULL;
   3033 
   3034     head = &queue->que.head.list;
   3035     pos = head->next;
   3036     if (pos != head) {
   3037         /* get the first node */
   3038         node = member_of(pos, cam_node_t, list);
   3039         super_buf = (mm_channel_queue_node_t*)node->data;
   3040         if ( (NULL != super_buf) &&
   3041              (matched_only == TRUE) &&
   3042              (super_buf->matched == FALSE) ) {
   3043             /* require to dequeue matched frame only, but this superbuf is not matched,
   3044                simply set return ptr to NULL */
   3045             super_buf = NULL;
   3046         }
   3047         if (NULL != super_buf) {
   3048             /* remove from the queue */
   3049             cam_list_del_node(&node->list);
   3050             queue->que.size--;
   3051             if (super_buf->matched == TRUE) {
   3052                 queue->match_cnt--;
   3053                 if (ch_obj->bundle.superbuf_queue.attr.enable_frame_sync) {
   3054                     pthread_mutex_lock(&fs_lock);
   3055                     mm_frame_sync_remove(super_buf->frame_idx);
   3056                     pthread_mutex_unlock(&fs_lock);
   3057                 }
   3058             }
   3059             free(node);
   3060         }
   3061     }
   3062 
   3063     return super_buf;
   3064 }
   3065 
   3066 /*===========================================================================
   3067  * FUNCTION   : mm_channel_superbuf_dequeue_frame_internal
   3068  *
   3069  * DESCRIPTION: internal implementation for dequeue based on frame index
   3070  *                     from the superbuf queue
   3071  *
   3072  * PARAMETERS :
   3073  *   @queue       : superbuf queue
   3074  *   @frame_idx  : frame index to be dequeued
   3075  *
   3076  * RETURN     : ptr to a node from superbuf queue with matched frame index
   3077  *                : NULL if not found
   3078  *==========================================================================*/
   3079 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_frame_internal(
   3080         mm_channel_queue_t * queue, uint32_t frame_idx)
   3081 {
   3082     cam_node_t* node = NULL;
   3083     struct cam_list *head = NULL;
   3084     struct cam_list *pos = NULL;
   3085     mm_channel_queue_node_t* super_buf = NULL;
   3086 
   3087     if (!queue) {
   3088         LOGE("queue is NULL");
   3089         return NULL;
   3090     }
   3091 
   3092     head = &queue->que.head.list;
   3093     pos = head->next;
   3094     LOGL("Searching for match frame %d", frame_idx);
   3095     while ((pos != head) && (pos != NULL)) {
   3096         /* get the first node */
   3097         node = member_of(pos, cam_node_t, list);
   3098         super_buf = (mm_channel_queue_node_t*)node->data;
   3099         if (super_buf && super_buf->matched &&
   3100                 (super_buf->frame_idx == frame_idx)) {
   3101             /* remove from the queue */
   3102             cam_list_del_node(&node->list);
   3103             queue->que.size--;
   3104             queue->match_cnt--;
   3105             LOGH("Found match frame %d", frame_idx);
   3106             free(node);
   3107             break;
   3108         }
   3109         else {
   3110             LOGH("match frame not found %d", frame_idx);
   3111             super_buf = NULL;
   3112         }
   3113         pos = pos->next;
   3114     }
   3115     return super_buf;
   3116 }
   3117 
   3118 
   3119 /*===========================================================================
   3120  * FUNCTION   : mm_channel_superbuf_dequeue
   3121  *
   3122  * DESCRIPTION: dequeue from the superbuf queue
   3123  *
   3124  * PARAMETERS :
   3125  *   @queue   : superbuf queue
   3126  *   @ch_obj  : channel object
   3127  *
   3128  * RETURN     : ptr to a node from superbuf queue
   3129  *==========================================================================*/
   3130 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(
   3131         mm_channel_queue_t * queue, mm_channel_t *ch_obj)
   3132 {
   3133     mm_channel_queue_node_t* super_buf = NULL;
   3134 
   3135     pthread_mutex_lock(&queue->que.lock);
   3136     super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, ch_obj);
   3137     pthread_mutex_unlock(&queue->que.lock);
   3138 
   3139     return super_buf;
   3140 }
   3141 
   3142 /*===========================================================================
   3143  * FUNCTION   : mm_channel_superbuf_bufdone_overflow
   3144  *
   3145  * DESCRIPTION: keep superbuf queue no larger than watermark set by upper layer
   3146  *              via channel attribute
   3147  *
   3148  * PARAMETERS :
   3149  *   @my_obj  : channel object
   3150  *   @queue   : superbuf queue
   3151  *
   3152  * RETURN     : int32_t type of status
   3153  *              0  -- success
   3154  *              -1 -- failure
   3155  *==========================================================================*/
   3156 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
   3157                                              mm_channel_queue_t * queue)
   3158 {
   3159     int32_t rc = 0, i;
   3160     mm_channel_queue_node_t* super_buf = NULL;
   3161     if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
   3162         /* for continuous streaming mode, no overflow is needed */
   3163         return 0;
   3164     }
   3165 
   3166     LOGD("before match_cnt=%d, water_mark=%d",
   3167           queue->match_cnt, queue->attr.water_mark);
   3168     /* bufdone overflowed bufs */
   3169     pthread_mutex_lock(&queue->que.lock);
   3170     while (queue->match_cnt > queue->attr.water_mark) {
   3171         super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj);
   3172         if (NULL != super_buf) {
   3173             for (i=0; i<super_buf->num_of_bufs; i++) {
   3174                 if (NULL != super_buf->super_buf[i].buf) {
   3175                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   3176                 }
   3177             }
   3178             free(super_buf);
   3179         }
   3180     }
   3181     pthread_mutex_unlock(&queue->que.lock);
   3182     LOGD("after match_cnt=%d, water_mark=%d",
   3183           queue->match_cnt, queue->attr.water_mark);
   3184 
   3185     return rc;
   3186 }
   3187 
   3188 /*===========================================================================
   3189  * FUNCTION   : mm_channel_superbuf_skip
   3190  *
   3191  * DESCRIPTION: depends on the lookback configuration of the channel attribute,
   3192  *              unwanted superbufs will be removed from the superbuf queue.
   3193  *
   3194  * PARAMETERS :
   3195  *   @my_obj  : channel object
   3196  *   @queue   : superbuf queue
   3197  *
   3198  * RETURN     : int32_t type of status
   3199  *              0  -- success
   3200  *              -1 -- failure
   3201  *==========================================================================*/
   3202 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
   3203                                  mm_channel_queue_t * queue)
   3204 {
   3205     int32_t rc = 0, i;
   3206     mm_channel_queue_node_t* super_buf = NULL;
   3207     if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
   3208         /* for continuous streaming mode, no skip is needed */
   3209         return 0;
   3210     }
   3211 
   3212     /* bufdone overflowed bufs */
   3213     pthread_mutex_lock(&queue->que.lock);
   3214     while (queue->match_cnt > queue->attr.look_back) {
   3215         super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj);
   3216         if (NULL != super_buf) {
   3217             for (i=0; i<super_buf->num_of_bufs; i++) {
   3218                 if (NULL != super_buf->super_buf[i].buf) {
   3219                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   3220                 }
   3221             }
   3222             free(super_buf);
   3223         }
   3224     }
   3225     pthread_mutex_unlock(&queue->que.lock);
   3226 
   3227     return rc;
   3228 }
   3229 
   3230 /*===========================================================================
   3231  * FUNCTION   : mm_channel_superbuf_flush
   3232  *
   3233  * DESCRIPTION: flush the superbuf queue.
   3234  *
   3235  * PARAMETERS :
   3236  *   @my_obj  : channel object
   3237  *   @queue   : superbuf queue
   3238  *   @cam_type: flush only particular type (default flushes all)
   3239  *
   3240  * RETURN     : int32_t type of status
   3241  *              0  -- success
   3242  *              -1 -- failure
   3243  *==========================================================================*/
   3244 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj,
   3245         mm_channel_queue_t * queue, cam_stream_type_t cam_type)
   3246 {
   3247     int32_t rc = 0, i;
   3248     mm_channel_queue_node_t* super_buf = NULL;
   3249     cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
   3250 
   3251     /* bufdone bufs */
   3252     pthread_mutex_lock(&queue->que.lock);
   3253     super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE, my_obj);
   3254     while (super_buf != NULL) {
   3255         for (i=0; i<super_buf->num_of_bufs; i++) {
   3256             if (NULL != super_buf->super_buf[i].buf) {
   3257                 stream_type = super_buf->super_buf[i].buf->stream_type;
   3258                 if ((CAM_STREAM_TYPE_DEFAULT == cam_type) ||
   3259                         (cam_type == stream_type)) {
   3260                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   3261                 }
   3262             }
   3263         }
   3264         free(super_buf);
   3265         super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE, my_obj);
   3266     }
   3267     pthread_mutex_unlock(&queue->que.lock);
   3268 
   3269     return rc;
   3270 }
   3271 
   3272 /*===========================================================================
   3273  * FUNCTION   : mm_channel_proc_general_cmd
   3274  *
   3275  * DESCRIPTION: process general command
   3276  *
   3277  * PARAMETERS :
   3278  *   @my_obj  : channel object
   3279  *   @notify_mode : notification mode
   3280  *
   3281  * RETURN     : int32_t type of status
   3282  *              0  -- success
   3283  *              -1 -- failure
   3284  *==========================================================================*/
   3285 int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj,
   3286                                       mm_camera_generic_cmd_t *p_gen_cmd)
   3287 {
   3288     LOGD("E");
   3289     int32_t rc = 0;
   3290     mm_camera_cmdcb_t* node = NULL;
   3291 
   3292     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   3293     if (NULL != node) {
   3294         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   3295         node->u.gen_cmd = *p_gen_cmd;
   3296         node->cmd_type = MM_CAMERA_CMD_TYPE_GENERAL;
   3297 
   3298         /* enqueue to cmd thread */
   3299         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   3300 
   3301         /* wake up cmd thread */
   3302         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   3303     } else {
   3304         LOGE("No memory for mm_camera_node_t");
   3305         rc = -1;
   3306     }
   3307     LOGD("X");
   3308 
   3309     return rc;
   3310 }
   3311 
   3312 /*===========================================================================
   3313  * FUNCTION   : mm_channel_superbuf_flush_matched
   3314  *
   3315  * DESCRIPTION: flush matched buffers from the superbuf queue.
   3316  *
   3317  * PARAMETERS :
   3318  *   @my_obj  : channel object
   3319  *   @queue   : superbuf queue
   3320  *
   3321  * RETURN     : int32_t type of status
   3322  *              0  -- success
   3323  *              -1 -- failure
   3324  *==========================================================================*/
   3325 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj,
   3326                                   mm_channel_queue_t * queue)
   3327 {
   3328     int32_t rc = 0, i;
   3329     mm_channel_queue_node_t* super_buf = NULL;
   3330 
   3331     /* bufdone bufs */
   3332     pthread_mutex_lock(&queue->que.lock);
   3333     super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj);
   3334     while (super_buf != NULL) {
   3335         for (i=0; i<super_buf->num_of_bufs; i++) {
   3336             if (NULL != super_buf->super_buf[i].buf) {
   3337                 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   3338             }
   3339         }
   3340         free(super_buf);
   3341         super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj);
   3342     }
   3343     pthread_mutex_unlock(&queue->que.lock);
   3344 
   3345     return rc;
   3346 }
   3347 
   3348 
   3349 /*===========================================================================
   3350  * FUNCTION   : mm_frame_sync_reset
   3351  *
   3352  * DESCRIPTION: Reset Frame sync info
   3353  *
   3354  * RETURN     : None
   3355  *==========================================================================*/
   3356 void mm_frame_sync_reset() {
   3357     memset(&fs, 0x0, sizeof(fs));
   3358     LOGD("Reset Done");
   3359 }
   3360 
   3361 /*===========================================================================
   3362  * FUNCTION   : mm_frame_sync_register_channel
   3363  *
   3364  * DESCRIPTION: Register Channel for frame sync
   3365  *
   3366  * PARAMETERS :
   3367  *   @ch_obj  : channel object
   3368  *
   3369  * RETURN     : int32_t type of status
   3370  *              0  -- success
   3371  *              -1 -- failure
   3372  *==========================================================================*/
   3373 int32_t mm_frame_sync_register_channel(mm_channel_t *ch_obj) {
   3374     // Lock frame sync info
   3375     pthread_mutex_lock(&fs_lock);
   3376     if ((fs.num_cam >= MAX_NUM_CAMERA_PER_BUNDLE) || (!ch_obj)) {
   3377         LOGE("Error!! num cam(%d) is out of range ",
   3378                  fs.num_cam);
   3379         pthread_mutex_unlock(&fs_lock);
   3380         return -1;
   3381     }
   3382     if (fs.num_cam == 0) {
   3383         LOGH("First channel registering!!");
   3384         mm_frame_sync_reset();
   3385     }
   3386     uint8_t i = 0;
   3387     for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) {
   3388         if (fs.ch_obj[i] == NULL) {
   3389             fs.ch_obj[i] = ch_obj;
   3390             fs.cb[i] = ch_obj->bundle.super_buf_notify_cb;
   3391             fs.num_cam++;
   3392             LOGD("DBG_FS index %d", i);
   3393             break;
   3394         }
   3395     }
   3396     if (i >= MAX_NUM_CAMERA_PER_BUNDLE) {
   3397         LOGH("X, DBG_FS Cannot register channel!!");
   3398         pthread_mutex_unlock(&fs_lock);
   3399         return -1;
   3400     }
   3401     LOGH("num_cam %d ", fs.num_cam);
   3402     pthread_mutex_unlock(&fs_lock);
   3403     return 0;
   3404 }
   3405 
   3406 /*===========================================================================
   3407  * FUNCTION   : mm_frame_sync_unregister_channel
   3408  *
   3409  * DESCRIPTION: un-register Channel for frame sync
   3410  *
   3411  * PARAMETERS :
   3412  *   @ch_obj  : channel object
   3413  *
   3414  * RETURN     : int32_t type of status
   3415  *              0  -- success
   3416  *              -1 -- failure
   3417  *==========================================================================*/
   3418 int32_t mm_frame_sync_unregister_channel(mm_channel_t *ch_obj) {
   3419     uint8_t i = 0;
   3420     // Lock frame sync info
   3421     pthread_mutex_lock(&fs_lock);
   3422     if (!fs.num_cam || !ch_obj) {
   3423         LOGH("X, DBG_FS: channel not found  !!");
   3424         // Lock frame sync info
   3425         pthread_mutex_unlock(&fs_lock);
   3426         return -1;
   3427     }
   3428     for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) {
   3429         if (fs.ch_obj[i] == ch_obj) {
   3430             LOGD("found ch_obj at i (%d) ", i);
   3431             break;
   3432         }
   3433     }
   3434     if (i < MAX_NUM_CAMERA_PER_BUNDLE) {
   3435         LOGD("remove channel info ");
   3436         fs.ch_obj[i] = NULL;
   3437         fs.cb[i] = NULL;
   3438         fs.num_cam--;
   3439     } else {
   3440         LOGD("DBG_FS Channel not found ");
   3441     }
   3442     if (fs.num_cam == 0) {
   3443         mm_frame_sync_reset();
   3444     }
   3445     LOGH("X, fs.num_cam %d", fs.num_cam);
   3446     pthread_mutex_unlock(&fs_lock);
   3447     return 0;
   3448 }
   3449 
   3450 
   3451 /*===========================================================================
   3452  * FUNCTION   : mm_frame_sync_add
   3453  *
   3454  * DESCRIPTION: Add frame info into frame sync nodes
   3455  *
   3456  * PARAMETERS :
   3457  *   @frame_id  : frame id to be added
   3458  *   @ch_obj  : channel object
   3459  *
   3460  * RETURN     : int32_t type of status
   3461  *              0  -- success
   3462  *              -1 -- failure
   3463  *==========================================================================*/
   3464 int32_t mm_frame_sync_add(uint32_t frame_id, mm_channel_t *ch_obj) {
   3465 
   3466     LOGD("E, frame id %d ch_obj %p", frame_id, ch_obj);
   3467     if (!frame_id || !ch_obj) {
   3468         LOGH("X : Error, cannot add sync frame !!");
   3469         return -1;
   3470     }
   3471 
   3472     int8_t ch_idx = -1;
   3473     uint8_t i = 0;
   3474     for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) {
   3475         if (fs.ch_obj[i] == ch_obj) {
   3476             ch_idx = i;
   3477             LOGD("ch id %d ", ch_idx);
   3478             break;
   3479         }
   3480     }
   3481     if (ch_idx < 0) {
   3482         LOGH("X : DBG_FS ch not found!!");
   3483         return -1;
   3484     }
   3485     int8_t index = mm_frame_sync_find_frame_index(frame_id);
   3486     if ((index >= 0) && (index < MM_CAMERA_FRAME_SYNC_NODES)) {
   3487         fs.node[index].frame_valid[ch_idx] = 1;
   3488     } else if (index < 0) {
   3489         if (fs.pos >= MM_CAMERA_FRAME_SYNC_NODES) {
   3490             fs.pos = 0;
   3491         }
   3492         index = fs.pos;
   3493         memset(&fs.node[index], 0x00, sizeof(mm_channel_sync_node_t));
   3494         fs.pos++;
   3495         fs.node[index].frame_idx = frame_id;
   3496         fs.node[index].frame_valid[ch_idx] = 1;
   3497         if (fs.num_cam == 1) {
   3498             LOGD("Single camera frame %d , matched ", frame_id);
   3499             fs.node[index].matched = 1;
   3500         }
   3501     }
   3502     uint8_t frames_valid = 0;
   3503     if (!fs.node[index].matched) {
   3504         for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) {
   3505             if (fs.node[index].frame_valid[i]) {
   3506                 frames_valid++;
   3507             }
   3508         }
   3509         if (frames_valid == fs.num_cam) {
   3510             fs.node[index].matched = 1;
   3511             LOGD("dual camera frame %d , matched ",
   3512                      frame_id);
   3513         }
   3514     }
   3515     return 0;
   3516 }
   3517 
   3518 /*===========================================================================
   3519  * FUNCTION   : mm_frame_sync_remove
   3520  *
   3521  * DESCRIPTION: Remove frame info from frame sync nodes
   3522  *
   3523  * PARAMETERS :
   3524  *   @frame_id  : frame id to be removed
   3525  *
   3526  * RETURN     : int32_t type of status
   3527  *              0  -- success
   3528  *              -1 -- failure
   3529  *==========================================================================*/
   3530 int32_t mm_frame_sync_remove(uint32_t frame_id) {
   3531     int8_t index = -1;
   3532 
   3533     LOGD("E, frame_id %d", frame_id);
   3534     if (!frame_id) {
   3535         LOGE("X, DBG_FS frame id invalid");
   3536         return -1;
   3537     }
   3538 
   3539     index = mm_frame_sync_find_frame_index(frame_id);
   3540     if ((index >= 0) && (index < MM_CAMERA_FRAME_SYNC_NODES)) {
   3541         LOGD("Removing sync frame %d", frame_id);
   3542         memset(&fs.node[index], 0x00, sizeof(mm_channel_sync_node_t));
   3543     }
   3544     LOGD("X ");
   3545     return 0;
   3546 }
   3547 
   3548 /*===========================================================================
   3549  * FUNCTION   : mm_frame_sync_find_matched
   3550  *
   3551  * DESCRIPTION: Find  a matched sync frame from the node array
   3552  *
   3553  * PARAMETERS :
   3554  *   @oldest  : If enabled, find oldest matched frame.,
   3555  *                  If not enabled, get the first matched frame found
   3556  *
   3557  * RETURN     : unt32_t type of status
   3558  *              0  -- If no matched frames found
   3559  *              frame index: inf matched frame found
   3560  *==========================================================================*/
   3561 uint32_t mm_frame_sync_find_matched(uint8_t oldest) {
   3562     LOGH("E, oldest %d ", oldest);
   3563     uint8_t i = 0;
   3564     uint32_t frame_idx = 0;
   3565     uint32_t curr_frame_idx = 0;
   3566     for (i = 0; i < MM_CAMERA_FRAME_SYNC_NODES; i++) {
   3567         if (fs.node[i].matched) {
   3568             curr_frame_idx = fs.node[i].frame_idx;
   3569             if (!frame_idx) {
   3570                 frame_idx = curr_frame_idx;
   3571             }
   3572             if (!oldest) {
   3573                 break;
   3574             } else if (frame_idx > curr_frame_idx) {
   3575                 frame_idx = curr_frame_idx;
   3576             }
   3577         }
   3578     }
   3579     LOGH("X, oldest %d frame idx %d", oldest, frame_idx);
   3580     return frame_idx;
   3581 }
   3582 
   3583 /*===========================================================================
   3584  * FUNCTION   : mm_frame_sync_find_frame_index
   3585  *
   3586  * DESCRIPTION: Find sync frame index if present
   3587  *
   3588  * PARAMETERS :
   3589  *   @frame_id  : frame id to be searched
   3590  *
   3591  * RETURN     : int8_t type of status
   3592  *              -1  -- If desired frame not found
   3593  *              index: node array index if frame is found
   3594  *==========================================================================*/
   3595 int8_t mm_frame_sync_find_frame_index(uint32_t frame_id) {
   3596 
   3597     LOGD("E, frame_id %d", frame_id);
   3598     int8_t index = -1, i = 0;
   3599     for (i = 0; i < MM_CAMERA_FRAME_SYNC_NODES; i++) {
   3600         if (fs.node[i].frame_idx == frame_id) {
   3601             index = i;
   3602             break;
   3603         }
   3604     }
   3605     LOGD("X index :%d", index);
   3606     return index;
   3607 }
   3608 
   3609 /*===========================================================================
   3610  * FUNCTION   : mm_frame_sync_lock_queues
   3611  *
   3612  * DESCRIPTION: Lock all channel queues present in node info
   3613  *
   3614  * RETURN     : None
   3615  *==========================================================================*/
   3616 void mm_frame_sync_lock_queues() {
   3617     uint8_t j = 0;
   3618     LOGD("E ");
   3619     for (j = 0; j < MAX_NUM_CAMERA_PER_BUNDLE; j++) {
   3620         if (fs.ch_obj[j]) {
   3621             mm_channel_queue_t *ch_queue =
   3622                     &fs.ch_obj[j]->bundle.superbuf_queue;
   3623             if (ch_queue) {
   3624                 pthread_mutex_lock(&ch_queue->que.lock);
   3625                 LOGL("Done locking fs.ch_obj[%d] ", j);
   3626             }
   3627         }
   3628     }
   3629     pthread_mutex_lock(&fs_lock);
   3630     LOGD("X ");
   3631 }
   3632 
   3633 /*===========================================================================
   3634  * FUNCTION   : mm_frame_sync_unlock_queues
   3635  *
   3636  * DESCRIPTION: Unlock all channel queues
   3637  *
   3638  * RETURN     : None
   3639  *==========================================================================*/
   3640 void mm_frame_sync_unlock_queues() {
   3641     // Unlock all queues
   3642     uint8_t j = 0;
   3643     LOGD("E ");
   3644     pthread_mutex_unlock(&fs_lock);
   3645     LOGL("Done unlocking fs ");
   3646     for (j = 0; j < MAX_NUM_CAMERA_PER_BUNDLE; j++) {
   3647         if (fs.ch_obj[j]) {
   3648             mm_channel_queue_t *ch_queue =
   3649                     &fs.ch_obj[j]->bundle.superbuf_queue;
   3650             if (ch_queue) {
   3651                 pthread_mutex_unlock(&ch_queue->que.lock);
   3652                 LOGL("Done unlocking fs.ch_obj[%d] ", j);
   3653             }
   3654         }
   3655     }
   3656     LOGD("X ");
   3657 }
   3658 
   3659 /*===========================================================================
   3660  * FUNCTION   : mm_channel_node_qbuf
   3661  *
   3662  * DESCRIPTION: qbuf all buffers in a node
   3663  *
   3664  * PARAMETERS :
   3665  *   @ch_obj  : Channel info
   3666  *   @node    : node to qbuf
   3667  *
   3668  * RETURN     : None
   3669  *==========================================================================*/
   3670 void mm_channel_node_qbuf(mm_channel_t *ch_obj, mm_channel_queue_node_t *node) {
   3671     uint8_t i;
   3672     if (!ch_obj || !node) {
   3673         return;
   3674     }
   3675     for (i = 0; i < node->num_of_bufs; i++) {
   3676         mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
   3677     }
   3678     return;
   3679 }
   3680