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