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