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