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