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