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 
38 #include <cam_semaphore.h>
39 
40 #include "mm_camera_dbg.h"
41 #include "mm_camera_sock.h"
42 #include "mm_camera_interface.h"
43 #include "mm_camera.h"
44 
45 #define SET_PARM_BIT32(parm, parm_arr) \
46     (parm_arr[parm/32] |= (1<<(parm%32)))
47 
48 #define GET_PARM_BIT32(parm, parm_arr) \
49     ((parm_arr[parm/32]>>(parm%32))& 0x1)
50 
51 /* internal function declare */
52 int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj,
53                           uint8_t reg_flag);
54 int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj,
55                               mm_camera_event_t *event);
56 
57 /*===========================================================================
58  * FUNCTION   : mm_camera_util_get_channel_by_handler
59  *
60  * DESCRIPTION: utility function to get a channel object from its handle
61  *
62  * PARAMETERS :
63  *   @cam_obj: ptr to a camera object
64  *   @handler: channel handle
65  *
66  * RETURN     : ptr to a channel object.
67  *              NULL if failed.
68  *==========================================================================*/
mm_camera_util_get_channel_by_handler(mm_camera_obj_t * cam_obj,uint32_t handler)69 mm_channel_t * mm_camera_util_get_channel_by_handler(
70                                     mm_camera_obj_t * cam_obj,
71                                     uint32_t handler)
72 {
73     int i;
74     mm_channel_t *ch_obj = NULL;
75     for(i = 0; i < MM_CAMERA_CHANNEL_MAX; i++) {
76         if (handler == cam_obj->ch[i].my_hdl) {
77             ch_obj = &cam_obj->ch[i];
78             break;
79         }
80     }
81     return ch_obj;
82 }
83 
84 /*===========================================================================
85  * FUNCTION   : mm_camera_util_chip_is_a_family
86  *
87  * DESCRIPTION: utility function to check if the host is A family chip
88  *
89  * PARAMETERS :
90  *
91  * RETURN     : TRUE if A family.
92  *              FALSE otherwise.
93  *==========================================================================*/
mm_camera_util_chip_is_a_family(void)94 uint8_t mm_camera_util_chip_is_a_family(void)
95 {
96     int id = 0;
97     FILE *fp;
98     if ((fp = fopen("/sys/devices/system/soc/soc0/id", "r")) != NULL) {
99         fscanf(fp, "%d", &id);
100         fclose(fp);
101     }
102     if (id == 126)
103         return FALSE;
104     else
105         return TRUE;
106 }
107 
108 /*===========================================================================
109  * FUNCTION   : mm_camera_dispatch_app_event
110  *
111  * DESCRIPTION: dispatch event to apps who regitster for event notify
112  *
113  * PARAMETERS :
114  *   @cmd_cb: ptr to a struct storing event info
115  *   @user_data: user data ptr (camera object)
116  *
117  * RETURN     : none
118  *==========================================================================*/
mm_camera_dispatch_app_event(mm_camera_cmdcb_t * cmd_cb,void * user_data)119 static void mm_camera_dispatch_app_event(mm_camera_cmdcb_t *cmd_cb,
120                                          void* user_data)
121 {
122     int i;
123     mm_camera_event_t *event = &cmd_cb->u.evt;
124     mm_camera_obj_t * my_obj = (mm_camera_obj_t *)user_data;
125     if (NULL != my_obj) {
126         pthread_mutex_lock(&my_obj->cb_lock);
127         for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
128             if(my_obj->evt.evt[i].evt_cb) {
129                 my_obj->evt.evt[i].evt_cb(
130                     my_obj->my_hdl,
131                     event,
132                     my_obj->evt.evt[i].user_data);
133             }
134         }
135         pthread_mutex_unlock(&my_obj->cb_lock);
136     }
137 }
138 
139 /*===========================================================================
140  * FUNCTION   : mm_camera_event_notify
141  *
142  * DESCRIPTION: callback to handle event notify from kernel. This call will
143  *              dequeue event from kernel.
144  *
145  * PARAMETERS :
146  *   @user_data: user data ptr (camera object)
147  *
148  * RETURN     : none
149  *==========================================================================*/
mm_camera_event_notify(void * user_data)150 static void mm_camera_event_notify(void* user_data)
151 {
152     struct v4l2_event ev;
153     struct msm_v4l2_event_data *msm_evt = NULL;
154     int rc;
155     mm_camera_event_t evt;
156     memset(&evt, 0, sizeof(mm_camera_event_t));
157 
158     mm_camera_obj_t *my_obj = (mm_camera_obj_t*)user_data;
159     if (NULL != my_obj) {
160         /* read evt */
161         memset(&ev, 0, sizeof(ev));
162         rc = ioctl(my_obj->ctrl_fd, VIDIOC_DQEVENT, &ev);
163 
164         if (rc >= 0 && ev.id == MSM_CAMERA_MSM_NOTIFY) {
165             msm_evt = (struct msm_v4l2_event_data *)ev.u.data;
166             switch (msm_evt->command) {
167             case CAM_EVENT_TYPE_MAP_UNMAP_DONE:
168                 pthread_mutex_lock(&my_obj->evt_lock);
169                 my_obj->evt_rcvd.server_event_type = msm_evt->command;
170                 my_obj->evt_rcvd.status = msm_evt->status;
171                 pthread_cond_signal(&my_obj->evt_cond);
172                 pthread_mutex_unlock(&my_obj->evt_lock);
173                 break;
174             case MSM_CAMERA_PRIV_SHUTDOWN:
175                 {
176                     evt.server_event_type = CAM_EVENT_TYPE_DAEMON_DIED;
177                     mm_camera_enqueue_evt(my_obj, &evt);
178                 }
179                 break;
180             default:
181                 break;
182             }
183         }
184     }
185 }
186 
187 /*===========================================================================
188  * FUNCTION   : mm_camera_enqueue_evt
189  *
190  * DESCRIPTION: enqueue received event into event queue to be processed by
191  *              event thread.
192  *
193  * PARAMETERS :
194  *   @my_obj   : ptr to a camera object
195  *   @event    : event to be queued
196  *
197  * RETURN     : int32_t type of status
198  *              0  -- success
199  *              -1 -- failure
200  *==========================================================================*/
mm_camera_enqueue_evt(mm_camera_obj_t * my_obj,mm_camera_event_t * event)201 int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj,
202                               mm_camera_event_t *event)
203 {
204     int32_t rc = 0;
205     mm_camera_cmdcb_t *node = NULL;
206 
207     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
208     if (NULL != node) {
209         memset(node, 0, sizeof(mm_camera_cmdcb_t));
210         node->cmd_type = MM_CAMERA_CMD_TYPE_EVT_CB;
211         node->u.evt = *event;
212 
213         /* enqueue to evt cmd thread */
214         cam_queue_enq(&(my_obj->evt_thread.cmd_queue), node);
215         /* wake up evt cmd thread */
216         cam_sem_post(&(my_obj->evt_thread.cmd_sem));
217     } else {
218         CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
219         rc = -1;
220     }
221 
222     return rc;
223 }
224 
225 /*===========================================================================
226  * FUNCTION   : mm_camera_open
227  *
228  * DESCRIPTION: open a camera
229  *
230  * PARAMETERS :
231  *   @my_obj   : ptr to a camera object
232  *
233  * RETURN     : int32_t type of status
234  *              0  -- success
235  *              -1 -- failure
236  *==========================================================================*/
mm_camera_open(mm_camera_obj_t * my_obj)237 int32_t mm_camera_open(mm_camera_obj_t *my_obj)
238 {
239     char dev_name[MM_CAMERA_DEV_NAME_LEN];
240     int32_t rc = 0;
241     int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;
242     uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP;
243     unsigned int cam_idx = 0;
244 
245     CDBG("%s:  begin\n", __func__);
246 
247     snprintf(dev_name, sizeof(dev_name), "/dev/%s",
248              mm_camera_util_get_dev_name(my_obj->my_hdl));
249     sscanf(dev_name, "/dev/video%u", &cam_idx);
250     CDBG_ERROR("%s: dev name = %s, cam_idx = %d", __func__, dev_name, cam_idx);
251 
252     do{
253         n_try--;
254         my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);
255         CDBG("%s:  ctrl_fd = %d, errno == %d", __func__, my_obj->ctrl_fd, errno);
256         if((my_obj->ctrl_fd > 0) || (errno != EIO) || (n_try <= 0 )) {
257             CDBG_ERROR("%s:  opened, break out while loop", __func__);
258             break;
259         }
260         CDBG("%s:failed with I/O error retrying after %d milli-seconds",
261              __func__, sleep_msec);
262         usleep(sleep_msec * 1000);
263     }while (n_try > 0);
264 
265     if (my_obj->ctrl_fd <= 0) {
266         CDBG_ERROR("%s: cannot open control fd of '%s' (%s)\n",
267                  __func__, dev_name, strerror(errno));
268         rc = -1;
269         goto on_error;
270     }
271 
272     /* open domain socket*/
273     n_try = MM_CAMERA_DEV_OPEN_TRIES;
274     do {
275         n_try--;
276         my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP);
277         CDBG("%s:  ds_fd = %d, errno = %d", __func__, my_obj->ds_fd, errno);
278         if((my_obj->ds_fd > 0) || (n_try <= 0 )) {
279             CDBG("%s:  opened, break out while loop", __func__);
280             break;
281         }
282         CDBG("%s:failed with I/O error retrying after %d milli-seconds",
283              __func__, sleep_msec);
284         usleep(sleep_msec * 1000);
285     } while (n_try > 0);
286 
287     if (my_obj->ds_fd <= 0) {
288         CDBG_ERROR("%s: cannot open domain socket fd of '%s'(%s)\n",
289                  __func__, dev_name, strerror(errno));
290         rc = -1;
291         goto on_error;
292     }
293     pthread_mutex_init(&my_obj->msg_lock, NULL);
294 
295     pthread_mutex_init(&my_obj->cb_lock, NULL);
296     pthread_mutex_init(&my_obj->evt_lock, NULL);
297     pthread_cond_init(&my_obj->evt_cond, NULL);
298 
299     CDBG("%s : Launch evt Thread in Cam Open",__func__);
300     mm_camera_cmd_thread_launch(&my_obj->evt_thread,
301                                 mm_camera_dispatch_app_event,
302                                 (void *)my_obj);
303 
304     /* launch event poll thread
305      * we will add evt fd into event poll thread upon user first register for evt */
306     CDBG("%s : Launch evt Poll Thread in Cam Open", __func__);
307     mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
308                                  MM_CAMERA_POLL_TYPE_EVT);
309     mm_camera_evt_sub(my_obj, TRUE);
310 
311     CDBG("%s:  end (rc = %d)\n", __func__, rc);
312     /* we do not need to unlock cam_lock here before return
313      * because for open, it's done within intf_lock */
314     return rc;
315 
316 on_error:
317     if (my_obj->ctrl_fd > 0) {
318         close(my_obj->ctrl_fd);
319         my_obj->ctrl_fd = 0;
320     }
321     if (my_obj->ds_fd > 0) {
322         mm_camera_socket_close(my_obj->ds_fd);
323        my_obj->ds_fd = 0;
324     }
325 
326     /* we do not need to unlock cam_lock here before return
327      * because for open, it's done within intf_lock */
328     return rc;
329 }
330 
331 /*===========================================================================
332  * FUNCTION   : mm_camera_close
333  *
334  * DESCRIPTION: enqueue received event into event queue to be processed by
335  *              event thread.
336  *
337  * PARAMETERS :
338  *   @my_obj   : ptr to a camera object
339  *   @event    : event to be queued
340  *
341  * RETURN     : int32_t type of status
342  *              0  -- success
343  *              -1 -- failure
344  *==========================================================================*/
mm_camera_close(mm_camera_obj_t * my_obj)345 int32_t mm_camera_close(mm_camera_obj_t *my_obj)
346 {
347     CDBG("%s : unsubscribe evt", __func__);
348     mm_camera_evt_sub(my_obj, FALSE);
349 
350     CDBG("%s : Close evt Poll Thread in Cam Close",__func__);
351     mm_camera_poll_thread_release(&my_obj->evt_poll_thread);
352 
353     CDBG("%s : Close evt cmd Thread in Cam Close",__func__);
354     mm_camera_cmd_thread_release(&my_obj->evt_thread);
355 
356     if(my_obj->ctrl_fd > 0) {
357         close(my_obj->ctrl_fd);
358         my_obj->ctrl_fd = 0;
359     }
360     if(my_obj->ds_fd > 0) {
361         mm_camera_socket_close(my_obj->ds_fd);
362         my_obj->ds_fd = 0;
363     }
364     pthread_mutex_destroy(&my_obj->msg_lock);
365 
366     pthread_mutex_destroy(&my_obj->cb_lock);
367     pthread_mutex_destroy(&my_obj->evt_lock);
368     pthread_cond_destroy(&my_obj->evt_cond);
369 
370     pthread_mutex_unlock(&my_obj->cam_lock);
371     return 0;
372 }
373 
374 /*===========================================================================
375  * FUNCTION   : mm_camera_register_event_notify_internal
376  *
377  * DESCRIPTION: internal implementation for registering callback for event notify.
378  *
379  * PARAMETERS :
380  *   @my_obj   : ptr to a camera object
381  *   @evt_cb   : callback to be registered to handle event notify
382  *   @user_data: user data ptr
383  *
384  * RETURN     : int32_t type of status
385  *              0  -- success
386  *              -1 -- failure
387  *==========================================================================*/
mm_camera_register_event_notify_internal(mm_camera_obj_t * my_obj,mm_camera_event_notify_t evt_cb,void * user_data)388 int32_t mm_camera_register_event_notify_internal(mm_camera_obj_t *my_obj,
389                                                  mm_camera_event_notify_t evt_cb,
390                                                  void * user_data)
391 {
392     int i;
393     int rc = -1;
394     mm_camera_evt_obj_t *evt_array = NULL;
395 
396     pthread_mutex_lock(&my_obj->cb_lock);
397     evt_array = &my_obj->evt;
398     if(evt_cb) {
399         /* this is reg case */
400         for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
401             if(evt_array->evt[i].user_data == NULL) {
402                 evt_array->evt[i].evt_cb = evt_cb;
403                 evt_array->evt[i].user_data = user_data;
404                 evt_array->reg_count++;
405                 rc = 0;
406                 break;
407             }
408         }
409     } else {
410         /* this is unreg case */
411         for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
412             if(evt_array->evt[i].user_data == user_data) {
413                 evt_array->evt[i].evt_cb = NULL;
414                 evt_array->evt[i].user_data = NULL;
415                 evt_array->reg_count--;
416                 rc = 0;
417                 break;
418             }
419         }
420     }
421 
422     pthread_mutex_unlock(&my_obj->cb_lock);
423     return rc;
424 }
425 
426 /*===========================================================================
427  * FUNCTION   : mm_camera_register_event_notify
428  *
429  * DESCRIPTION: registering a callback for event notify.
430  *
431  * PARAMETERS :
432  *   @my_obj   : ptr to a camera object
433  *   @evt_cb   : callback to be registered to handle event notify
434  *   @user_data: user data ptr
435  *
436  * RETURN     : int32_t type of status
437  *              0  -- success
438  *              -1 -- failure
439  *==========================================================================*/
mm_camera_register_event_notify(mm_camera_obj_t * my_obj,mm_camera_event_notify_t evt_cb,void * user_data)440 int32_t mm_camera_register_event_notify(mm_camera_obj_t *my_obj,
441                                         mm_camera_event_notify_t evt_cb,
442                                         void * user_data)
443 {
444     int rc = -1;
445     rc = mm_camera_register_event_notify_internal(my_obj,
446                                                   evt_cb,
447                                                   user_data);
448     pthread_mutex_unlock(&my_obj->cam_lock);
449     return rc;
450 }
451 
452 /*===========================================================================
453  * FUNCTION   : mm_camera_qbuf
454  *
455  * DESCRIPTION: enqueue buffer back to kernel
456  *
457  * PARAMETERS :
458  *   @my_obj       : camera object
459  *   @ch_id        : channel handle
460  *   @buf          : buf ptr to be enqueued
461  *
462  * RETURN     : int32_t type of status
463  *              0  -- success
464  *              -1 -- failure
465  *==========================================================================*/
mm_camera_qbuf(mm_camera_obj_t * my_obj,uint32_t ch_id,mm_camera_buf_def_t * buf)466 int32_t mm_camera_qbuf(mm_camera_obj_t *my_obj,
467                        uint32_t ch_id,
468                        mm_camera_buf_def_t *buf)
469 {
470     int rc = -1;
471     mm_channel_t * ch_obj = NULL;
472     ch_obj = mm_camera_util_get_channel_by_handler(my_obj, ch_id);
473 
474     pthread_mutex_unlock(&my_obj->cam_lock);
475 
476     /* we always assume qbuf will be done before channel/stream is fully stopped
477      * because qbuf is done within dataCB context
478      * in order to avoid deadlock, we are not locking ch_lock for qbuf */
479     if (NULL != ch_obj) {
480         rc = mm_channel_qbuf(ch_obj, buf);
481     }
482 
483     return rc;
484 }
485 
486 /*===========================================================================
487  * FUNCTION   : mm_camera_query_capability
488  *
489  * DESCRIPTION: query camera capability
490  *
491  * PARAMETERS :
492  *   @my_obj: camera object
493  *
494  * RETURN     : int32_t type of status
495  *              0  -- success
496  *              -1 -- failure
497  *==========================================================================*/
mm_camera_query_capability(mm_camera_obj_t * my_obj)498 int32_t mm_camera_query_capability(mm_camera_obj_t *my_obj)
499 {
500     int32_t rc = 0;
501     struct v4l2_capability cap;
502 
503     /* get camera capabilities */
504     memset(&cap, 0, sizeof(cap));
505     rc = ioctl(my_obj->ctrl_fd, VIDIOC_QUERYCAP, &cap);
506     if (rc != 0) {
507         CDBG_ERROR("%s: cannot get camera capabilities, rc = %d\n", __func__, rc);
508     }
509 
510     pthread_mutex_unlock(&my_obj->cam_lock);
511     return rc;
512 
513 }
514 
515 /*===========================================================================
516  * FUNCTION   : mm_camera_set_parms
517  *
518  * DESCRIPTION: set parameters per camera
519  *
520  * PARAMETERS :
521  *   @my_obj       : camera object
522  *   @parms        : ptr to a param struct to be set to server
523  *
524  * RETURN     : int32_t type of status
525  *              0  -- success
526  *              -1 -- failure
527  * NOTE       : Assume the parms struct buf is already mapped to server via
528  *              domain socket. Corresponding fields of parameters to be set
529  *              are already filled in by upper layer caller.
530  *==========================================================================*/
mm_camera_set_parms(mm_camera_obj_t * my_obj,parm_buffer_t * parms)531 int32_t mm_camera_set_parms(mm_camera_obj_t *my_obj,
532                             parm_buffer_t *parms)
533 {
534     int32_t rc = -1;
535     int32_t value = 0;
536     if (parms !=  NULL) {
537         rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_PARM, &value);
538     }
539     pthread_mutex_unlock(&my_obj->cam_lock);
540     return rc;
541 }
542 
543 /*===========================================================================
544  * FUNCTION   : mm_camera_get_parms
545  *
546  * DESCRIPTION: get parameters per camera
547  *
548  * PARAMETERS :
549  *   @my_obj       : camera object
550  *   @parms        : ptr to a param struct to be get from server
551  *
552  * RETURN     : int32_t type of status
553  *              0  -- success
554  *              -1 -- failure
555  * NOTE       : Assume the parms struct buf is already mapped to server via
556  *              domain socket. Parameters to be get from server are already
557  *              filled in by upper layer caller. After this call, corresponding
558  *              fields of requested parameters will be filled in by server with
559  *              detailed information.
560  *==========================================================================*/
mm_camera_get_parms(mm_camera_obj_t * my_obj,parm_buffer_t * parms)561 int32_t mm_camera_get_parms(mm_camera_obj_t *my_obj,
562                             parm_buffer_t *parms)
563 {
564     int32_t rc = -1;
565     int32_t value = 0;
566     if (parms != NULL) {
567         rc = mm_camera_util_g_ctrl(my_obj->ctrl_fd, CAM_PRIV_PARM, &value);
568     }
569     pthread_mutex_unlock(&my_obj->cam_lock);
570     return rc;
571 }
572 
573 /*===========================================================================
574  * FUNCTION   : mm_camera_do_auto_focus
575  *
576  * DESCRIPTION: performing auto focus
577  *
578  * PARAMETERS :
579  *   @camera_handle: camera handle
580  *
581  * RETURN     : int32_t type of status
582  *              0  -- success
583  *              -1 -- failure
584  * NOTE       : if this call success, we will always assume there will
585  *              be an auto_focus event following up.
586  *==========================================================================*/
mm_camera_do_auto_focus(mm_camera_obj_t * my_obj)587 int32_t mm_camera_do_auto_focus(mm_camera_obj_t *my_obj)
588 {
589     int32_t rc = -1;
590     int32_t value = 0;
591     rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_DO_AUTO_FOCUS, &value);
592     pthread_mutex_unlock(&my_obj->cam_lock);
593     return rc;
594 }
595 
596 /*===========================================================================
597  * FUNCTION   : mm_camera_cancel_auto_focus
598  *
599  * DESCRIPTION: cancel auto focus
600  *
601  * PARAMETERS :
602  *   @camera_handle: camera handle
603  *
604  * RETURN     : int32_t type of status
605  *              0  -- success
606  *              -1 -- failure
607  *==========================================================================*/
mm_camera_cancel_auto_focus(mm_camera_obj_t * my_obj)608 int32_t mm_camera_cancel_auto_focus(mm_camera_obj_t *my_obj)
609 {
610     int32_t rc = -1;
611     int32_t value = 0;
612     rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_CANCEL_AUTO_FOCUS, &value);
613     pthread_mutex_unlock(&my_obj->cam_lock);
614     return rc;
615 }
616 
617 /*===========================================================================
618  * FUNCTION   : mm_camera_prepare_snapshot
619  *
620  * DESCRIPTION: prepare hardware for snapshot
621  *
622  * PARAMETERS :
623  *   @my_obj       : camera object
624  *   @do_af_flag   : flag indicating if AF is needed
625  *
626  * RETURN     : int32_t type of status
627  *              0  -- success
628  *              -1 -- failure
629  *==========================================================================*/
mm_camera_prepare_snapshot(mm_camera_obj_t * my_obj,int32_t do_af_flag)630 int32_t mm_camera_prepare_snapshot(mm_camera_obj_t *my_obj,
631                                    int32_t do_af_flag)
632 {
633     int32_t rc = -1;
634     int32_t value = do_af_flag;
635     rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_PREPARE_SNAPSHOT, &value);
636     pthread_mutex_unlock(&my_obj->cam_lock);
637     return rc;
638 }
639 
640 /*===========================================================================
641  * FUNCTION   : mm_camera_start_zsl_snapshot
642  *
643  * DESCRIPTION: start zsl snapshot
644  *
645  * PARAMETERS :
646  *   @my_obj       : camera object
647  *
648  * RETURN     : int32_t type of status
649  *              0  -- success
650  *              -1 -- failure
651  *==========================================================================*/
mm_camera_start_zsl_snapshot(mm_camera_obj_t * my_obj)652 int32_t mm_camera_start_zsl_snapshot(mm_camera_obj_t *my_obj)
653 {
654     int32_t rc = -1;
655     int32_t value = 0;
656 
657     rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
658              CAM_PRIV_START_ZSL_SNAPSHOT, &value);
659 
660     pthread_mutex_unlock(&my_obj->cam_lock);
661     return rc;
662 }
663 
664 /*===========================================================================
665  * FUNCTION   : mm_camera_stop_zsl_snapshot
666  *
667  * DESCRIPTION: stop zsl capture
668  *
669  * PARAMETERS :
670  *   @my_obj       : camera object
671  *
672  * RETURN     : int32_t type of status
673  *              0  -- success
674  *              -1 -- failure
675  *==========================================================================*/
mm_camera_stop_zsl_snapshot(mm_camera_obj_t * my_obj)676 int32_t mm_camera_stop_zsl_snapshot(mm_camera_obj_t *my_obj)
677 {
678     int32_t rc = -1;
679     int32_t value;
680     rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
681              CAM_PRIV_STOP_ZSL_SNAPSHOT, &value);
682     pthread_mutex_unlock(&my_obj->cam_lock);
683     return rc;
684 }
685 
686 /*===========================================================================
687  * FUNCTION   : mm_camera_add_channel
688  *
689  * DESCRIPTION: add a channel
690  *
691  * PARAMETERS :
692  *   @my_obj       : camera object
693  *   @attr         : bundle attribute of the channel if needed
694  *   @channel_cb   : callback function for bundle data notify
695  *   @userdata     : user data ptr
696  *
697  * RETURN     : uint32_t type of channel handle
698  *              0  -- invalid channel handle, meaning the op failed
699  *              >0 -- successfully added a channel with a valid handle
700  * NOTE       : if no bundle data notify is needed, meaning each stream in the
701  *              channel will have its own stream data notify callback, then
702  *              attr, channel_cb, and userdata can be NULL. In this case,
703  *              no matching logic will be performed in channel for the bundling.
704  *==========================================================================*/
mm_camera_add_channel(mm_camera_obj_t * my_obj,mm_camera_channel_attr_t * attr,mm_camera_buf_notify_t channel_cb,void * userdata)705 uint32_t mm_camera_add_channel(mm_camera_obj_t *my_obj,
706                                mm_camera_channel_attr_t *attr,
707                                mm_camera_buf_notify_t channel_cb,
708                                void *userdata)
709 {
710     mm_channel_t *ch_obj = NULL;
711     uint8_t ch_idx = 0;
712     uint32_t ch_hdl = 0;
713 
714     for(ch_idx = 0; ch_idx < MM_CAMERA_CHANNEL_MAX; ch_idx++) {
715         if (MM_CHANNEL_STATE_NOTUSED == my_obj->ch[ch_idx].state) {
716             ch_obj = &my_obj->ch[ch_idx];
717             break;
718         }
719     }
720 
721     if (NULL != ch_obj) {
722         /* initialize channel obj */
723         memset(ch_obj, 0, sizeof(mm_channel_t));
724         ch_hdl = mm_camera_util_generate_handler(ch_idx);
725         ch_obj->my_hdl = ch_hdl;
726         ch_obj->state = MM_CHANNEL_STATE_STOPPED;
727         ch_obj->cam_obj = my_obj;
728         pthread_mutex_init(&ch_obj->ch_lock, NULL);
729         mm_channel_init(ch_obj, attr, channel_cb, userdata);
730     }
731 
732     pthread_mutex_unlock(&my_obj->cam_lock);
733 
734     return ch_hdl;
735 }
736 
737 /*===========================================================================
738  * FUNCTION   : mm_camera_del_channel
739  *
740  * DESCRIPTION: delete a channel by its handle
741  *
742  * PARAMETERS :
743  *   @my_obj       : camera object
744  *   @ch_id        : channel handle
745  *
746  * RETURN     : int32_t type of status
747  *              0  -- success
748  *              -1 -- failure
749  * NOTE       : all streams in the channel should be stopped already before
750  *              this channel can be deleted.
751  *==========================================================================*/
mm_camera_del_channel(mm_camera_obj_t * my_obj,uint32_t ch_id)752 int32_t mm_camera_del_channel(mm_camera_obj_t *my_obj,
753                               uint32_t ch_id)
754 {
755     int32_t rc = -1;
756     mm_channel_t * ch_obj =
757         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
758 
759     if (NULL != ch_obj) {
760         pthread_mutex_lock(&ch_obj->ch_lock);
761         pthread_mutex_unlock(&my_obj->cam_lock);
762 
763         rc = mm_channel_fsm_fn(ch_obj,
764                                MM_CHANNEL_EVT_DELETE,
765                                NULL,
766                                NULL);
767 
768         pthread_mutex_destroy(&ch_obj->ch_lock);
769         memset(ch_obj, 0, sizeof(mm_channel_t));
770     } else {
771         pthread_mutex_unlock(&my_obj->cam_lock);
772     }
773     return rc;
774 }
775 
776 /*===========================================================================
777  * FUNCTION   : mm_camera_get_bundle_info
778  *
779  * DESCRIPTION: query bundle info of the channel
780  *
781  * PARAMETERS :
782  *   @my_obj       : camera object
783  *   @ch_id        : channel handle
784  *   @bundle_info  : bundle info to be filled in
785  *
786  * RETURN     : int32_t type of status
787  *              0  -- success
788  *              -1 -- failure
789  * NOTE       : all streams in the channel should be stopped already before
790  *              this channel can be deleted.
791  *==========================================================================*/
mm_camera_get_bundle_info(mm_camera_obj_t * my_obj,uint32_t ch_id,cam_bundle_config_t * bundle_info)792 int32_t mm_camera_get_bundle_info(mm_camera_obj_t *my_obj,
793                                   uint32_t ch_id,
794                                   cam_bundle_config_t *bundle_info)
795 {
796     int32_t rc = -1;
797     mm_channel_t * ch_obj =
798         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
799 
800     if (NULL != ch_obj) {
801         pthread_mutex_lock(&ch_obj->ch_lock);
802         pthread_mutex_unlock(&my_obj->cam_lock);
803 
804         rc = mm_channel_fsm_fn(ch_obj,
805                                MM_CHANNEL_EVT_GET_BUNDLE_INFO,
806                                (void *)bundle_info,
807                                NULL);
808     } else {
809         pthread_mutex_unlock(&my_obj->cam_lock);
810     }
811     return rc;
812 }
813 
814 /*===========================================================================
815  * FUNCTION   : mm_camera_add_stream
816  *
817  * DESCRIPTION: add a stream into a channel
818  *
819  * PARAMETERS :
820  *   @my_obj       : camera object
821  *   @ch_id        : channel handle
822  *
823  * RETURN     : uint32_t type of stream handle
824  *              0  -- invalid stream handle, meaning the op failed
825  *              >0 -- successfully added a stream with a valid handle
826  *==========================================================================*/
mm_camera_add_stream(mm_camera_obj_t * my_obj,uint32_t ch_id)827 uint32_t mm_camera_add_stream(mm_camera_obj_t *my_obj,
828                               uint32_t ch_id)
829 {
830     uint32_t s_hdl = 0;
831     mm_channel_t * ch_obj =
832         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
833 
834     if (NULL != ch_obj) {
835         pthread_mutex_lock(&ch_obj->ch_lock);
836         pthread_mutex_unlock(&my_obj->cam_lock);
837 
838         mm_channel_fsm_fn(ch_obj,
839                           MM_CHANNEL_EVT_ADD_STREAM,
840                           NULL,
841                           (void*)&s_hdl);
842     } else {
843         pthread_mutex_unlock(&my_obj->cam_lock);
844     }
845 
846     return s_hdl;
847 }
848 
849 /*===========================================================================
850  * FUNCTION   : mm_camera_del_stream
851  *
852  * DESCRIPTION: delete a stream by its handle
853  *
854  * PARAMETERS :
855  *   @my_obj       : camera object
856  *   @ch_id        : channel handle
857  *   @stream_id    : stream handle
858  *
859  * RETURN     : int32_t type of status
860  *              0  -- success
861  *              -1 -- failure
862  * NOTE       : stream should be stopped already before it can be deleted.
863  *==========================================================================*/
mm_camera_del_stream(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t stream_id)864 int32_t mm_camera_del_stream(mm_camera_obj_t *my_obj,
865                              uint32_t ch_id,
866                              uint32_t stream_id)
867 {
868     int32_t rc = -1;
869     mm_channel_t * ch_obj =
870         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
871 
872     if (NULL != ch_obj) {
873         pthread_mutex_lock(&ch_obj->ch_lock);
874         pthread_mutex_unlock(&my_obj->cam_lock);
875 
876         rc = mm_channel_fsm_fn(ch_obj,
877                                MM_CHANNEL_EVT_DEL_STREAM,
878                                (void*)stream_id,
879                                NULL);
880     } else {
881         pthread_mutex_unlock(&my_obj->cam_lock);
882     }
883 
884     return rc;
885 }
886 
887 /*===========================================================================
888  * FUNCTION   : mm_camera_config_stream
889  *
890  * DESCRIPTION: configure a stream
891  *
892  * PARAMETERS :
893  *   @my_obj       : camera object
894  *   @ch_id        : channel handle
895  *   @stream_id    : stream handle
896  *   @config       : stream configuration
897  *
898  * RETURN     : int32_t type of status
899  *              0  -- success
900  *              -1 -- failure
901  *==========================================================================*/
mm_camera_config_stream(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t stream_id,mm_camera_stream_config_t * config)902 int32_t mm_camera_config_stream(mm_camera_obj_t *my_obj,
903                                 uint32_t ch_id,
904                                 uint32_t stream_id,
905                                 mm_camera_stream_config_t *config)
906 {
907     int32_t rc = -1;
908     mm_channel_t * ch_obj =
909         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
910     mm_evt_paylod_config_stream_t payload;
911 
912     if (NULL != ch_obj) {
913         pthread_mutex_lock(&ch_obj->ch_lock);
914         pthread_mutex_unlock(&my_obj->cam_lock);
915 
916         memset(&payload, 0, sizeof(mm_evt_paylod_config_stream_t));
917         payload.stream_id = stream_id;
918         payload.config = config;
919         rc = mm_channel_fsm_fn(ch_obj,
920                                MM_CHANNEL_EVT_CONFIG_STREAM,
921                                (void*)&payload,
922                                NULL);
923     } else {
924         pthread_mutex_unlock(&my_obj->cam_lock);
925     }
926 
927     return rc;
928 }
929 
930 /*===========================================================================
931  * FUNCTION   : mm_camera_start_channel
932  *
933  * DESCRIPTION: start a channel, which will start all streams in the channel
934  *
935  * PARAMETERS :
936  *   @my_obj       : camera object
937  *   @ch_id        : channel handle
938  *
939  * RETURN     : int32_t type of status
940  *              0  -- success
941  *              -1 -- failure
942  *==========================================================================*/
mm_camera_start_channel(mm_camera_obj_t * my_obj,uint32_t ch_id)943 int32_t mm_camera_start_channel(mm_camera_obj_t *my_obj,
944                                 uint32_t ch_id)
945 {
946     int32_t rc = -1;
947     mm_channel_t * ch_obj =
948         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
949 
950     if (NULL != ch_obj) {
951         pthread_mutex_lock(&ch_obj->ch_lock);
952         pthread_mutex_unlock(&my_obj->cam_lock);
953 
954         rc = mm_channel_fsm_fn(ch_obj,
955                                MM_CHANNEL_EVT_START,
956                                NULL,
957                                NULL);
958     } else {
959         pthread_mutex_unlock(&my_obj->cam_lock);
960     }
961 
962     return rc;
963 }
964 
965 /*===========================================================================
966  * FUNCTION   : mm_camera_stop_channel
967  *
968  * DESCRIPTION: stop a channel, which will stop all streams in the channel
969  *
970  * PARAMETERS :
971  *   @my_obj       : camera object
972  *   @ch_id        : channel handle
973  *
974  * RETURN     : int32_t type of status
975  *              0  -- success
976  *              -1 -- failure
977  *==========================================================================*/
mm_camera_stop_channel(mm_camera_obj_t * my_obj,uint32_t ch_id)978 int32_t mm_camera_stop_channel(mm_camera_obj_t *my_obj,
979                                uint32_t ch_id)
980 {
981     int32_t rc = 0;
982     mm_channel_t * ch_obj =
983         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
984 
985     if (NULL != ch_obj) {
986         pthread_mutex_lock(&ch_obj->ch_lock);
987         pthread_mutex_unlock(&my_obj->cam_lock);
988 
989         rc = mm_channel_fsm_fn(ch_obj,
990                                MM_CHANNEL_EVT_STOP,
991                                NULL,
992                                NULL);
993     } else {
994         pthread_mutex_unlock(&my_obj->cam_lock);
995     }
996     return rc;
997 }
998 
999 /*===========================================================================
1000  * FUNCTION   : mm_camera_request_super_buf
1001  *
1002  * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched
1003  *              frames from superbuf queue
1004  *
1005  * PARAMETERS :
1006  *   @my_obj       : camera object
1007  *   @ch_id        : channel handle
1008  *   @num_buf_requested : number of matched frames needed
1009  *
1010  * RETURN     : int32_t type of status
1011  *              0  -- success
1012  *              -1 -- failure
1013  *==========================================================================*/
mm_camera_request_super_buf(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t num_buf_requested)1014 int32_t mm_camera_request_super_buf(mm_camera_obj_t *my_obj,
1015                                     uint32_t ch_id,
1016                                     uint32_t num_buf_requested)
1017 {
1018     int32_t rc = -1;
1019     mm_channel_t * ch_obj =
1020         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1021 
1022     if (NULL != ch_obj) {
1023         pthread_mutex_lock(&ch_obj->ch_lock);
1024         pthread_mutex_unlock(&my_obj->cam_lock);
1025 
1026         rc = mm_channel_fsm_fn(ch_obj,
1027                                MM_CHANNEL_EVT_REQUEST_SUPER_BUF,
1028                                (void*)num_buf_requested,
1029                                NULL);
1030     } else {
1031         pthread_mutex_unlock(&my_obj->cam_lock);
1032     }
1033 
1034     return rc;
1035 }
1036 
1037 /*===========================================================================
1038  * FUNCTION   : mm_camera_cancel_super_buf_request
1039  *
1040  * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount
1041  *              of matched frames from superbuf queue
1042  *
1043  * PARAMETERS :
1044  *   @my_obj       : camera object
1045  *   @ch_id        : channel handle
1046  *
1047  * RETURN     : int32_t type of status
1048  *              0  -- success
1049  *              -1 -- failure
1050  *==========================================================================*/
mm_camera_cancel_super_buf_request(mm_camera_obj_t * my_obj,uint32_t ch_id)1051 int32_t mm_camera_cancel_super_buf_request(mm_camera_obj_t *my_obj, uint32_t ch_id)
1052 {
1053     int32_t rc = -1;
1054     mm_channel_t * ch_obj =
1055         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1056 
1057     if (NULL != ch_obj) {
1058         pthread_mutex_lock(&ch_obj->ch_lock);
1059         pthread_mutex_unlock(&my_obj->cam_lock);
1060 
1061         rc = mm_channel_fsm_fn(ch_obj,
1062                                MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF,
1063                                NULL,
1064                                NULL);
1065     } else {
1066         pthread_mutex_unlock(&my_obj->cam_lock);
1067     }
1068 
1069     return rc;
1070 }
1071 
1072 /*===========================================================================
1073  * FUNCTION   : mm_camera_flush_super_buf_queue
1074  *
1075  * DESCRIPTION: flush out all frames in the superbuf queue
1076  *
1077  * PARAMETERS :
1078  *   @my_obj       : camera object
1079  *   @ch_id        : channel handle
1080  *
1081  * RETURN     : int32_t type of status
1082  *              0  -- success
1083  *              -1 -- failure
1084  *==========================================================================*/
mm_camera_flush_super_buf_queue(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t frame_idx)1085 int32_t mm_camera_flush_super_buf_queue(mm_camera_obj_t *my_obj, uint32_t ch_id,
1086                                                              uint32_t frame_idx)
1087 {
1088     int32_t rc = -1;
1089     mm_channel_t * ch_obj =
1090         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1091 
1092     if (NULL != ch_obj) {
1093         pthread_mutex_lock(&ch_obj->ch_lock);
1094         pthread_mutex_unlock(&my_obj->cam_lock);
1095 
1096         rc = mm_channel_fsm_fn(ch_obj,
1097                                MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE,
1098                                (void *)frame_idx,
1099                                NULL);
1100     } else {
1101         pthread_mutex_unlock(&my_obj->cam_lock);
1102     }
1103 
1104     return rc;
1105 }
1106 
1107 /*===========================================================================
1108  * FUNCTION   : mm_camera_config_channel_notify
1109  *
1110  * DESCRIPTION: configures the channel notification mode
1111  *
1112  * PARAMETERS :
1113  *   @my_obj       : camera object
1114  *   @ch_id        : channel handle
1115  *   @notify_mode  : notification mode
1116  *
1117  * RETURN     : int32_t type of status
1118  *              0  -- success
1119  *              -1 -- failure
1120  *==========================================================================*/
mm_camera_config_channel_notify(mm_camera_obj_t * my_obj,uint32_t ch_id,mm_camera_super_buf_notify_mode_t notify_mode)1121 int32_t mm_camera_config_channel_notify(mm_camera_obj_t *my_obj,
1122                                         uint32_t ch_id,
1123                                         mm_camera_super_buf_notify_mode_t notify_mode)
1124 {
1125     int32_t rc = -1;
1126     mm_channel_t * ch_obj =
1127         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1128 
1129     if (NULL != ch_obj) {
1130         pthread_mutex_lock(&ch_obj->ch_lock);
1131         pthread_mutex_unlock(&my_obj->cam_lock);
1132 
1133         rc = mm_channel_fsm_fn(ch_obj,
1134                                MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE,
1135                                (void *)notify_mode,
1136                                NULL);
1137     } else {
1138         pthread_mutex_unlock(&my_obj->cam_lock);
1139     }
1140 
1141     return rc;
1142 }
1143 
1144 /*===========================================================================
1145  * FUNCTION   : mm_camera_set_stream_parms
1146  *
1147  * DESCRIPTION: set parameters per stream
1148  *
1149  * PARAMETERS :
1150  *   @my_obj       : camera object
1151  *   @ch_id        : channel handle
1152  *   @s_id         : stream handle
1153  *   @parms        : ptr to a param struct to be set to server
1154  *
1155  * RETURN     : int32_t type of status
1156  *              0  -- success
1157  *              -1 -- failure
1158  * NOTE       : Assume the parms struct buf is already mapped to server via
1159  *              domain socket. Corresponding fields of parameters to be set
1160  *              are already filled in by upper layer caller.
1161  *==========================================================================*/
mm_camera_set_stream_parms(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t s_id,cam_stream_parm_buffer_t * parms)1162 int32_t mm_camera_set_stream_parms(mm_camera_obj_t *my_obj,
1163                                    uint32_t ch_id,
1164                                    uint32_t s_id,
1165                                    cam_stream_parm_buffer_t *parms)
1166 {
1167     int32_t rc = -1;
1168     mm_evt_paylod_set_get_stream_parms_t payload;
1169     mm_channel_t * ch_obj =
1170         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1171 
1172     if (NULL != ch_obj) {
1173         pthread_mutex_lock(&ch_obj->ch_lock);
1174         pthread_mutex_unlock(&my_obj->cam_lock);
1175 
1176         memset(&payload, 0, sizeof(payload));
1177         payload.stream_id = s_id;
1178         payload.parms = parms;
1179 
1180         rc = mm_channel_fsm_fn(ch_obj,
1181                                MM_CHANNEL_EVT_SET_STREAM_PARM,
1182                                (void *)&payload,
1183                                NULL);
1184     } else {
1185         pthread_mutex_unlock(&my_obj->cam_lock);
1186     }
1187 
1188     return rc;
1189 }
1190 
1191 /*===========================================================================
1192  * FUNCTION   : mm_camera_get_stream_parms
1193  *
1194  * DESCRIPTION: get parameters per stream
1195  *
1196  * PARAMETERS :
1197  *   @my_obj       : camera object
1198  *   @ch_id        : channel handle
1199  *   @s_id         : stream handle
1200  *   @parms        : ptr to a param struct to be get from server
1201  *
1202  * RETURN     : int32_t type of status
1203  *              0  -- success
1204  *              -1 -- failure
1205  * NOTE       : Assume the parms struct buf is already mapped to server via
1206  *              domain socket. Parameters to be get from server are already
1207  *              filled in by upper layer caller. After this call, corresponding
1208  *              fields of requested parameters will be filled in by server with
1209  *              detailed information.
1210  *==========================================================================*/
mm_camera_get_stream_parms(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t s_id,cam_stream_parm_buffer_t * parms)1211 int32_t mm_camera_get_stream_parms(mm_camera_obj_t *my_obj,
1212                                    uint32_t ch_id,
1213                                    uint32_t s_id,
1214                                    cam_stream_parm_buffer_t *parms)
1215 {
1216     int32_t rc = -1;
1217     mm_evt_paylod_set_get_stream_parms_t payload;
1218     mm_channel_t * ch_obj =
1219         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1220 
1221     if (NULL != ch_obj) {
1222         pthread_mutex_lock(&ch_obj->ch_lock);
1223         pthread_mutex_unlock(&my_obj->cam_lock);
1224 
1225         memset(&payload, 0, sizeof(payload));
1226         payload.stream_id = s_id;
1227         payload.parms = parms;
1228 
1229         rc = mm_channel_fsm_fn(ch_obj,
1230                                MM_CHANNEL_EVT_GET_STREAM_PARM,
1231                                (void *)&payload,
1232                                NULL);
1233     } else {
1234         pthread_mutex_unlock(&my_obj->cam_lock);
1235     }
1236 
1237     return rc;
1238 }
1239 
1240 /*===========================================================================
1241  * FUNCTION   : mm_camera_do_stream_action
1242  *
1243  * DESCRIPTION: request server to perform stream based action. Maybe removed later
1244  *              if the functionality is included in mm_camera_set_parms
1245  *
1246  * PARAMETERS :
1247  *   @my_obj       : camera object
1248  *   @ch_id        : channel handle
1249  *   @s_id         : stream handle
1250  *   @actions      : ptr to an action struct buf to be performed by server
1251  *
1252  * RETURN     : int32_t type of status
1253  *              0  -- success
1254  *              -1 -- failure
1255  * NOTE       : Assume the action struct buf is already mapped to server via
1256  *              domain socket. Actions to be performed by server are already
1257  *              filled in by upper layer caller.
1258  *==========================================================================*/
mm_camera_do_stream_action(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t stream_id,void * actions)1259 int32_t mm_camera_do_stream_action(mm_camera_obj_t *my_obj,
1260                                    uint32_t ch_id,
1261                                    uint32_t stream_id,
1262                                    void *actions)
1263 {
1264     int32_t rc = -1;
1265     mm_evt_paylod_do_stream_action_t payload;
1266     mm_channel_t * ch_obj =
1267         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1268 
1269     if (NULL != ch_obj) {
1270         pthread_mutex_lock(&ch_obj->ch_lock);
1271         pthread_mutex_unlock(&my_obj->cam_lock);
1272 
1273         memset(&payload, 0, sizeof(payload));
1274         payload.stream_id = stream_id;
1275         payload.actions = actions;
1276 
1277         rc = mm_channel_fsm_fn(ch_obj,
1278                                MM_CHANNEL_EVT_DO_STREAM_ACTION,
1279                                (void*)&payload,
1280                                NULL);
1281     } else {
1282         pthread_mutex_unlock(&my_obj->cam_lock);
1283     }
1284 
1285     return rc;
1286 }
1287 
1288 /*===========================================================================
1289  * FUNCTION   : mm_camera_map_stream_buf
1290  *
1291  * DESCRIPTION: mapping stream buffer via domain socket to server
1292  *
1293  * PARAMETERS :
1294  *   @my_obj       : camera object
1295  *   @ch_id        : channel handle
1296  *   @s_id         : stream handle
1297  *   @buf_type     : type of buffer to be mapped. could be following values:
1298  *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1299  *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1300  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1301  *   @buf_idx      : index of buffer within the stream buffers, only valid if
1302  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1303  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1304  *   @plane_idx    : plane index. If all planes share the same fd,
1305  *                   plane_idx = -1; otherwise, plean_idx is the
1306  *                   index to plane (0..num_of_planes)
1307  *   @fd           : file descriptor of the buffer
1308  *   @size         : size of the buffer
1309  *
1310  * RETURN     : int32_t type of status
1311  *              0  -- success
1312  *              -1 -- failure
1313  *==========================================================================*/
mm_camera_map_stream_buf(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t stream_id,uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx,int fd,uint32_t size)1314 int32_t mm_camera_map_stream_buf(mm_camera_obj_t *my_obj,
1315                                  uint32_t ch_id,
1316                                  uint32_t stream_id,
1317                                  uint8_t buf_type,
1318                                  uint32_t buf_idx,
1319                                  int32_t plane_idx,
1320                                  int fd,
1321                                  uint32_t size)
1322 {
1323     int32_t rc = -1;
1324     mm_evt_paylod_map_stream_buf_t payload;
1325     mm_channel_t * ch_obj =
1326         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1327 
1328     if (NULL != ch_obj) {
1329         pthread_mutex_lock(&ch_obj->ch_lock);
1330         pthread_mutex_unlock(&my_obj->cam_lock);
1331 
1332         memset(&payload, 0, sizeof(payload));
1333         payload.stream_id = stream_id;
1334         payload.buf_type = buf_type;
1335         payload.buf_idx = buf_idx;
1336         payload.plane_idx = plane_idx;
1337         payload.fd = fd;
1338         payload.size = size;
1339         rc = mm_channel_fsm_fn(ch_obj,
1340                                MM_CHANNEL_EVT_MAP_STREAM_BUF,
1341                                (void*)&payload,
1342                                NULL);
1343     } else {
1344         pthread_mutex_unlock(&my_obj->cam_lock);
1345     }
1346 
1347     return rc;
1348 }
1349 
1350 /*===========================================================================
1351  * FUNCTION   : mm_camera_unmap_stream_buf
1352  *
1353  * DESCRIPTION: unmapping stream buffer via domain socket to server
1354  *
1355  * PARAMETERS :
1356  *   @my_obj       : camera object
1357  *   @ch_id        : channel handle
1358  *   @s_id         : stream handle
1359  *   @buf_type     : type of buffer to be mapped. could be following values:
1360  *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1361  *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1362  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1363  *   @buf_idx      : index of buffer within the stream buffers, only valid if
1364  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1365  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1366  *   @plane_idx    : plane index. If all planes share the same fd,
1367  *                   plane_idx = -1; otherwise, plean_idx is the
1368  *                   index to plane (0..num_of_planes)
1369  *
1370  * RETURN     : int32_t type of status
1371  *              0  -- success
1372  *              -1 -- failure
1373  *==========================================================================*/
mm_camera_unmap_stream_buf(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t stream_id,uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx)1374 int32_t mm_camera_unmap_stream_buf(mm_camera_obj_t *my_obj,
1375                                    uint32_t ch_id,
1376                                    uint32_t stream_id,
1377                                    uint8_t buf_type,
1378                                    uint32_t buf_idx,
1379                                    int32_t plane_idx)
1380 {
1381     int32_t rc = -1;
1382     mm_evt_paylod_unmap_stream_buf_t payload;
1383     mm_channel_t * ch_obj =
1384         mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1385 
1386     if (NULL != ch_obj) {
1387         pthread_mutex_lock(&ch_obj->ch_lock);
1388         pthread_mutex_unlock(&my_obj->cam_lock);
1389 
1390         memset(&payload, 0, sizeof(payload));
1391         payload.stream_id = stream_id;
1392         payload.buf_type = buf_type;
1393         payload.buf_idx = buf_idx;
1394         payload.plane_idx = plane_idx;
1395         rc = mm_channel_fsm_fn(ch_obj,
1396                                MM_CHANNEL_EVT_UNMAP_STREAM_BUF,
1397                                (void*)&payload,
1398                                NULL);
1399     } else {
1400         pthread_mutex_unlock(&my_obj->cam_lock);
1401     }
1402 
1403     return rc;
1404 }
1405 
1406 /*===========================================================================
1407  * FUNCTION   : mm_camera_evt_sub
1408  *
1409  * DESCRIPTION: subscribe/unsubscribe event notify from kernel
1410  *
1411  * PARAMETERS :
1412  *   @my_obj       : camera object
1413  *   @reg_flag     : 1 -- subscribe ; 0 -- unsubscribe
1414  *
1415  * RETURN     : int32_t type of status
1416  *              0  -- success
1417  *              -1 -- failure
1418  *==========================================================================*/
mm_camera_evt_sub(mm_camera_obj_t * my_obj,uint8_t reg_flag)1419 int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj,
1420                           uint8_t reg_flag)
1421 {
1422     int32_t rc = 0;
1423     struct v4l2_event_subscription sub;
1424 
1425     memset(&sub, 0, sizeof(sub));
1426     sub.type = MSM_CAMERA_V4L2_EVENT_TYPE;
1427     sub.id = MSM_CAMERA_MSM_NOTIFY;
1428     if(FALSE == reg_flag) {
1429         /* unsubscribe */
1430         rc = ioctl(my_obj->ctrl_fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
1431         if (rc < 0) {
1432             CDBG_ERROR("%s: unsubscribe event rc = %d", __func__, rc);
1433             return rc;
1434         }
1435         /* remove evt fd from the polling thraed when unreg the last event */
1436         rc = mm_camera_poll_thread_del_poll_fd(&my_obj->evt_poll_thread,
1437                                                my_obj->my_hdl,
1438                                                mm_camera_sync_call);
1439     } else {
1440         rc = ioctl(my_obj->ctrl_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
1441         if (rc < 0) {
1442             CDBG_ERROR("%s: subscribe event rc = %d", __func__, rc);
1443             return rc;
1444         }
1445         /* add evt fd to polling thread when subscribe the first event */
1446         rc = mm_camera_poll_thread_add_poll_fd(&my_obj->evt_poll_thread,
1447                                                my_obj->my_hdl,
1448                                                my_obj->ctrl_fd,
1449                                                mm_camera_event_notify,
1450                                                (void*)my_obj,
1451                                                mm_camera_sync_call);
1452     }
1453     return rc;
1454 }
1455 
1456 /*===========================================================================
1457  * FUNCTION   : mm_camera_util_wait_for_event
1458  *
1459  * DESCRIPTION: utility function to wait for certain events
1460  *
1461  * PARAMETERS :
1462  *   @my_obj       : camera object
1463  *   @evt_mask     : mask for events to be waited. Any of event in the mask would
1464  *                   trigger the wait to end
1465  *   @status       : status of the event
1466  *
1467  * RETURN     : none
1468  *==========================================================================*/
mm_camera_util_wait_for_event(mm_camera_obj_t * my_obj,uint32_t evt_mask,int32_t * status)1469 void mm_camera_util_wait_for_event(mm_camera_obj_t *my_obj,
1470                                    uint32_t evt_mask,
1471                                    int32_t *status)
1472 {
1473     pthread_mutex_lock(&my_obj->evt_lock);
1474     while (!(my_obj->evt_rcvd.server_event_type & evt_mask)) {
1475         pthread_cond_wait(&my_obj->evt_cond, &my_obj->evt_lock);
1476     }
1477     *status = my_obj->evt_rcvd.status;
1478     /* reset local storage for recieved event for next event */
1479     memset(&my_obj->evt_rcvd, 0, sizeof(mm_camera_event_t));
1480     pthread_mutex_unlock(&my_obj->evt_lock);
1481 }
1482 
1483 /*===========================================================================
1484  * FUNCTION   : mm_camera_util_sendmsg
1485  *
1486  * DESCRIPTION: utility function to send msg via domain socket
1487  *
1488  * PARAMETERS :
1489  *   @my_obj       : camera object
1490  *   @msg          : message to be sent
1491  *   @buf_size     : size of the message to be sent
1492  *   @sendfd       : >0 if any file descriptor need to be passed across process
1493  *
1494  * RETURN     : int32_t type of status
1495  *              0  -- success
1496  *              -1 -- failure
1497  *==========================================================================*/
mm_camera_util_sendmsg(mm_camera_obj_t * my_obj,void * msg,uint32_t buf_size,int sendfd)1498 int32_t mm_camera_util_sendmsg(mm_camera_obj_t *my_obj,
1499                                void *msg,
1500                                uint32_t buf_size,
1501                                int sendfd)
1502 {
1503     int32_t rc = -1;
1504     int32_t status;
1505 
1506     /* need to lock msg_lock, since sendmsg until reposonse back is deemed as one operation*/
1507     pthread_mutex_lock(&my_obj->msg_lock);
1508     if(mm_camera_socket_sendmsg(my_obj->ds_fd, msg, buf_size, sendfd) > 0) {
1509         /* wait for event that mapping/unmapping is done */
1510         mm_camera_util_wait_for_event(my_obj, CAM_EVENT_TYPE_MAP_UNMAP_DONE, &status);
1511         if (MSM_CAMERA_STATUS_SUCCESS == status) {
1512             rc = 0;
1513         }
1514     }
1515     pthread_mutex_unlock(&my_obj->msg_lock);
1516     return rc;
1517 }
1518 
1519 /*===========================================================================
1520  * FUNCTION   : mm_camera_map_buf
1521  *
1522  * DESCRIPTION: mapping camera buffer via domain socket to server
1523  *
1524  * PARAMETERS :
1525  *   @my_obj       : camera object
1526  *   @buf_type     : type of buffer to be mapped. could be following values:
1527  *                   CAM_MAPPING_BUF_TYPE_CAPABILITY
1528  *                   CAM_MAPPING_BUF_TYPE_SETPARM_BUF
1529  *                   CAM_MAPPING_BUF_TYPE_GETPARM_BUF
1530  *   @fd           : file descriptor of the buffer
1531  *   @size         : size of the buffer
1532  *
1533  * RETURN     : int32_t type of status
1534  *              0  -- success
1535  *              -1 -- failure
1536  *==========================================================================*/
mm_camera_map_buf(mm_camera_obj_t * my_obj,uint8_t buf_type,int fd,uint32_t size)1537 int32_t mm_camera_map_buf(mm_camera_obj_t *my_obj,
1538                           uint8_t buf_type,
1539                           int fd,
1540                           uint32_t size)
1541 {
1542     int32_t rc = 0;
1543     cam_sock_packet_t packet;
1544     memset(&packet, 0, sizeof(cam_sock_packet_t));
1545     packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
1546     packet.payload.buf_map.type = buf_type;
1547     packet.payload.buf_map.fd = fd;
1548     packet.payload.buf_map.size = size;
1549     rc = mm_camera_util_sendmsg(my_obj,
1550                                 &packet,
1551                                 sizeof(cam_sock_packet_t),
1552                                 fd);
1553     pthread_mutex_unlock(&my_obj->cam_lock);
1554     return rc;
1555 }
1556 
1557 /*===========================================================================
1558  * FUNCTION   : mm_camera_unmap_buf
1559  *
1560  * DESCRIPTION: unmapping camera buffer via domain socket to server
1561  *
1562  * PARAMETERS :
1563  *   @my_obj       : camera object
1564  *   @buf_type     : type of buffer to be mapped. could be following values:
1565  *                   CAM_MAPPING_BUF_TYPE_CAPABILITY
1566  *                   CAM_MAPPING_BUF_TYPE_SETPARM_BUF
1567  *                   CAM_MAPPING_BUF_TYPE_GETPARM_BUF
1568  *
1569  * RETURN     : int32_t type of status
1570  *              0  -- success
1571  *              -1 -- failure
1572  *==========================================================================*/
mm_camera_unmap_buf(mm_camera_obj_t * my_obj,uint8_t buf_type)1573 int32_t mm_camera_unmap_buf(mm_camera_obj_t *my_obj,
1574                             uint8_t buf_type)
1575 {
1576     int32_t rc = 0;
1577     cam_sock_packet_t packet;
1578     memset(&packet, 0, sizeof(cam_sock_packet_t));
1579     packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING;
1580     packet.payload.buf_unmap.type = buf_type;
1581     rc = mm_camera_util_sendmsg(my_obj,
1582                                 &packet,
1583                                 sizeof(cam_sock_packet_t),
1584                                 0);
1585     pthread_mutex_unlock(&my_obj->cam_lock);
1586     return rc;
1587 }
1588 
1589 /*===========================================================================
1590  * FUNCTION   : mm_camera_util_s_ctrl
1591  *
1592  * DESCRIPTION: utility function to send v4l2 ioctl for s_ctrl
1593  *
1594  * PARAMETERS :
1595  *   @fd      : file descritpor for sending ioctl
1596  *   @id      : control id
1597  *   @value   : value of the ioctl to be sent
1598  *
1599  * RETURN     : int32_t type of status
1600  *              0  -- success
1601  *              -1 -- failure
1602  *==========================================================================*/
mm_camera_util_s_ctrl(int32_t fd,uint32_t id,int32_t * value)1603 int32_t mm_camera_util_s_ctrl(int32_t fd,  uint32_t id, int32_t *value)
1604 {
1605     int rc = 0;
1606     struct v4l2_control control;
1607 
1608     memset(&control, 0, sizeof(control));
1609     control.id = id;
1610     if (value != NULL) {
1611         control.value = *value;
1612     }
1613     rc = ioctl(fd, VIDIOC_S_CTRL, &control);
1614 
1615     CDBG("%s: fd=%d, S_CTRL, id=0x%x, value = 0x%x, rc = %d\n",
1616          __func__, fd, id, (uint32_t)value, rc);
1617     if (value != NULL) {
1618         *value = control.value;
1619     }
1620     return (rc >= 0)? 0 : -1;
1621 }
1622 
1623 /*===========================================================================
1624  * FUNCTION   : mm_camera_util_g_ctrl
1625  *
1626  * DESCRIPTION: utility function to send v4l2 ioctl for g_ctrl
1627  *
1628  * PARAMETERS :
1629  *   @fd      : file descritpor for sending ioctl
1630  *   @id      : control id
1631  *   @value   : value of the ioctl to be sent
1632  *
1633  * RETURN     : int32_t type of status
1634  *              0  -- success
1635  *              -1 -- failure
1636  *==========================================================================*/
mm_camera_util_g_ctrl(int32_t fd,uint32_t id,int32_t * value)1637 int32_t mm_camera_util_g_ctrl( int32_t fd, uint32_t id, int32_t *value)
1638 {
1639     int rc = 0;
1640     struct v4l2_control control;
1641 
1642     memset(&control, 0, sizeof(control));
1643     control.id = id;
1644     if (value != NULL) {
1645         control.value = *value;
1646     }
1647     rc = ioctl(fd, VIDIOC_G_CTRL, &control);
1648     CDBG("%s: fd=%d, G_CTRL, id=0x%x, rc = %d\n", __func__, fd, id, rc);
1649     if (value != NULL) {
1650         *value = control.value;
1651     }
1652     return (rc >= 0)? 0 : -1;
1653 }
1654