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