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