1/* Copyright (c) 2012-2014, 2016, 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// To remove
31#include <cutils/properties.h>
32
33// System dependencies
34#include <pthread.h>
35#include <errno.h>
36#include <fcntl.h>
37#include <stdlib.h>
38#define IOCTL_H <SYSTEM_HEADER_PREFIX/ioctl.h>
39#include IOCTL_H
40
41// Camera dependencies
42#include "cam_semaphore.h"
43#include "mm_camera_dbg.h"
44#include "mm_camera_sock.h"
45#include "mm_camera_interface.h"
46#include "mm_camera.h"
47
48#define SET_PARM_BIT32(parm, parm_arr) \
49    (parm_arr[parm/32] |= (1<<(parm%32)))
50
51#define GET_PARM_BIT32(parm, parm_arr) \
52    ((parm_arr[parm/32]>>(parm%32))& 0x1)
53
54/* internal function declare */
55int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj,
56                          uint8_t reg_flag);
57int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj,
58                              mm_camera_event_t *event);
59
60/*===========================================================================
61 * FUNCTION   : mm_camera_util_get_channel_by_handler
62 *
63 * DESCRIPTION: utility function to get a channel object from its handle
64 *
65 * PARAMETERS :
66 *   @cam_obj: ptr to a camera object
67 *   @handler: channel handle
68 *
69 * RETURN     : ptr to a channel object.
70 *              NULL if failed.
71 *==========================================================================*/
72mm_channel_t * mm_camera_util_get_channel_by_handler(
73                                    mm_camera_obj_t * cam_obj,
74                                    uint32_t handler)
75{
76    int i;
77    mm_channel_t *ch_obj = NULL;
78    for(i = 0; i < MM_CAMERA_CHANNEL_MAX; i++) {
79        if (handler == cam_obj->ch[i].my_hdl) {
80            ch_obj = &cam_obj->ch[i];
81            break;
82        }
83    }
84    return ch_obj;
85}
86
87/*===========================================================================
88 * FUNCTION   : mm_camera_util_chip_is_a_family
89 *
90 * DESCRIPTION: utility function to check if the host is A family chip
91 *
92 * PARAMETERS :
93 *
94 * RETURN     : TRUE if A family.
95 *              FALSE otherwise.
96 *==========================================================================*/
97uint8_t mm_camera_util_chip_is_a_family(void)
98{
99#ifdef USE_A_FAMILY
100    return TRUE;
101#else
102    return FALSE;
103#endif
104}
105
106/*===========================================================================
107 * FUNCTION   : mm_camera_dispatch_app_event
108 *
109 * DESCRIPTION: dispatch event to apps who regitster for event notify
110 *
111 * PARAMETERS :
112 *   @cmd_cb: ptr to a struct storing event info
113 *   @user_data: user data ptr (camera object)
114 *
115 * RETURN     : none
116 *==========================================================================*/
117static void mm_camera_dispatch_app_event(mm_camera_cmdcb_t *cmd_cb,
118                                         void* user_data)
119{
120    int i;
121    mm_camera_event_t *event = &cmd_cb->u.evt;
122    mm_camera_obj_t * my_obj = (mm_camera_obj_t *)user_data;
123    if (NULL != my_obj) {
124        mm_camera_cmd_thread_name(my_obj->evt_thread.threadName);
125        pthread_mutex_lock(&my_obj->cb_lock);
126        for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
127            if(my_obj->evt.evt[i].evt_cb) {
128                my_obj->evt.evt[i].evt_cb(
129                    my_obj->my_hdl,
130                    event,
131                    my_obj->evt.evt[i].user_data);
132            }
133        }
134        pthread_mutex_unlock(&my_obj->cb_lock);
135    }
136}
137
138/*===========================================================================
139 * FUNCTION   : mm_camera_event_notify
140 *
141 * DESCRIPTION: callback to handle event notify from kernel. This call will
142 *              dequeue event from kernel.
143 *
144 * PARAMETERS :
145 *   @user_data: user data ptr (camera object)
146 *
147 * RETURN     : none
148 *==========================================================================*/
149static void mm_camera_event_notify(void* user_data)
150{
151    struct v4l2_event ev;
152    struct msm_v4l2_event_data *msm_evt = NULL;
153    int rc;
154    mm_camera_event_t evt;
155    memset(&evt, 0, sizeof(mm_camera_event_t));
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_DAEMON_PULL_REQ:
167                evt.server_event_type = CAM_EVENT_TYPE_DAEMON_PULL_REQ;
168                mm_camera_enqueue_evt(my_obj, &evt);
169                break;
170            case CAM_EVENT_TYPE_MAP_UNMAP_DONE:
171                pthread_mutex_lock(&my_obj->evt_lock);
172                my_obj->evt_rcvd.server_event_type = msm_evt->command;
173                my_obj->evt_rcvd.status = msm_evt->status;
174                pthread_cond_signal(&my_obj->evt_cond);
175                pthread_mutex_unlock(&my_obj->evt_lock);
176                break;
177            case CAM_EVENT_TYPE_INT_TAKE_JPEG:
178            case CAM_EVENT_TYPE_INT_TAKE_RAW:
179                {
180                    evt.server_event_type = msm_evt->command;
181                    mm_camera_enqueue_evt(my_obj, &evt);
182                }
183                break;
184            case MSM_CAMERA_PRIV_SHUTDOWN:
185                {
186                    LOGE("Camera Event DAEMON DIED received");
187                    evt.server_event_type = CAM_EVENT_TYPE_DAEMON_DIED;
188                    mm_camera_enqueue_evt(my_obj, &evt);
189                }
190                break;
191            case CAM_EVENT_TYPE_CAC_DONE:
192                {
193                    evt.server_event_type = CAM_EVENT_TYPE_CAC_DONE;
194                    mm_camera_enqueue_evt(my_obj, &evt);
195                }
196                break;
197            default:
198                break;
199            }
200        }
201    }
202}
203
204/*===========================================================================
205 * FUNCTION   : mm_camera_enqueue_evt
206 *
207 * DESCRIPTION: enqueue received event into event queue to be processed by
208 *              event thread.
209 *
210 * PARAMETERS :
211 *   @my_obj   : ptr to a camera object
212 *   @event    : event to be queued
213 *
214 * RETURN     : int32_t type of status
215 *              0  -- success
216 *              -1 -- failure
217 *==========================================================================*/
218int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj,
219                              mm_camera_event_t *event)
220{
221    int32_t rc = 0;
222    mm_camera_cmdcb_t *node = NULL;
223
224    node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
225    if (NULL != node) {
226        memset(node, 0, sizeof(mm_camera_cmdcb_t));
227        node->cmd_type = MM_CAMERA_CMD_TYPE_EVT_CB;
228        node->u.evt = *event;
229
230        /* enqueue to evt cmd thread */
231        cam_queue_enq(&(my_obj->evt_thread.cmd_queue), node);
232        /* wake up evt cmd thread */
233        cam_sem_post(&(my_obj->evt_thread.cmd_sem));
234    } else {
235        LOGE("No memory for mm_camera_node_t");
236        rc = -1;
237    }
238
239    return rc;
240}
241
242/*===========================================================================
243 * FUNCTION   : mm_camera_open
244 *
245 * DESCRIPTION: open a camera
246 *
247 * PARAMETERS :
248 *   @my_obj   : ptr to a camera object
249 *
250 * RETURN     : int32_t type of status
251 *              0  -- success
252 *              -1 -- failure
253 *==========================================================================*/
254int32_t mm_camera_open(mm_camera_obj_t *my_obj)
255{
256    char dev_name[MM_CAMERA_DEV_NAME_LEN];
257    int32_t rc = 0;
258    int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;
259    uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP;
260    int cam_idx = 0;
261    const char *dev_name_value = NULL;
262    int l_errno = 0;
263
264    LOGD("begin\n");
265
266    if (NULL == my_obj) {
267        goto on_error;
268    }
269    dev_name_value = mm_camera_util_get_dev_name(my_obj->my_hdl);
270    if (NULL == dev_name_value) {
271        goto on_error;
272    }
273    snprintf(dev_name, sizeof(dev_name), "/dev/%s",
274             dev_name_value);
275    sscanf(dev_name, "/dev/video%d", &cam_idx);
276    LOGD("dev name = %s, cam_idx = %d", dev_name, cam_idx);
277
278    do{
279        n_try--;
280        errno = 0;
281        my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);
282        l_errno = errno;
283        LOGD("ctrl_fd = %d, errno == %d", my_obj->ctrl_fd, l_errno);
284        if((my_obj->ctrl_fd >= 0) || (errno != EIO && errno != ETIMEDOUT) || (n_try <= 0 )) {
285            LOGH("opened, break out while loop");
286            break;
287        }
288        LOGE("Failed with %s error, retrying after %d milli-seconds",
289              strerror(errno), sleep_msec);
290        usleep(sleep_msec * 1000U);
291    }while (n_try > 0);
292
293    if (my_obj->ctrl_fd < 0) {
294        LOGE("cannot open control fd of '%s' (%s)\n",
295                  dev_name, strerror(l_errno));
296        if (l_errno == EBUSY)
297            rc = -EUSERS;
298        else
299            rc = -1;
300        goto on_error;
301    }
302
303    /* open domain socket*/
304    n_try = MM_CAMERA_DEV_OPEN_TRIES;
305    do {
306        n_try--;
307        my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP);
308        l_errno = errno;
309        LOGD("ds_fd = %d, errno = %d", my_obj->ds_fd, l_errno);
310        if((my_obj->ds_fd >= 0) || (n_try <= 0 )) {
311            LOGD("opened, break out while loop");
312            break;
313        }
314        LOGD("failed with I/O error retrying after %d milli-seconds",
315              sleep_msec);
316        usleep(sleep_msec * 1000U);
317    } while (n_try > 0);
318
319    if (my_obj->ds_fd < 0) {
320        LOGE("cannot open domain socket fd of '%s'(%s)\n",
321                  dev_name, strerror(l_errno));
322        rc = -1;
323        goto on_error;
324    }
325    pthread_mutex_init(&my_obj->msg_lock, NULL);
326
327    pthread_mutex_init(&my_obj->cb_lock, NULL);
328    pthread_mutex_init(&my_obj->evt_lock, NULL);
329    pthread_cond_init(&my_obj->evt_cond, NULL);
330
331    LOGD("Launch evt Thread in Cam Open");
332    snprintf(my_obj->evt_thread.threadName, THREAD_NAME_SIZE, "CAM_Dispatch");
333    mm_camera_cmd_thread_launch(&my_obj->evt_thread,
334                                mm_camera_dispatch_app_event,
335                                (void *)my_obj);
336
337    /* launch event poll thread
338     * we will add evt fd into event poll thread upon user first register for evt */
339    LOGD("Launch evt Poll Thread in Cam Open");
340    snprintf(my_obj->evt_poll_thread.threadName, THREAD_NAME_SIZE, "CAM_evntPoll");
341    mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
342                                 MM_CAMERA_POLL_TYPE_EVT);
343    mm_camera_evt_sub(my_obj, TRUE);
344
345    /* unlock cam_lock, we need release global intf_lock in camera_open(),
346     * in order not block operation of other Camera in dual camera use case.*/
347    pthread_mutex_unlock(&my_obj->cam_lock);
348    LOGD("end (rc = %d)\n", rc);
349    return rc;
350
351on_error:
352
353    if (NULL == dev_name_value) {
354        LOGE("Invalid device name\n");
355        rc = -1;
356    }
357
358    if (NULL == my_obj) {
359        LOGE("Invalid camera object\n");
360        rc = -1;
361    } else {
362        if (my_obj->ctrl_fd >= 0) {
363            close(my_obj->ctrl_fd);
364            my_obj->ctrl_fd = -1;
365        }
366        if (my_obj->ds_fd >= 0) {
367            mm_camera_socket_close(my_obj->ds_fd);
368            my_obj->ds_fd = -1;
369        }
370    }
371
372    /* unlock cam_lock, we need release global intf_lock in camera_open(),
373     * in order not block operation of other Camera in dual camera use case.*/
374    pthread_mutex_unlock(&my_obj->cam_lock);
375    return rc;
376}
377
378/*===========================================================================
379 * FUNCTION   : mm_camera_close
380 *
381 * DESCRIPTION: enqueue received event into event queue to be processed by
382 *              event thread.
383 *
384 * PARAMETERS :
385 *   @my_obj   : ptr to a camera object
386 *   @event    : event to be queued
387 *
388 * RETURN     : int32_t type of status
389 *              0  -- success
390 *              -1 -- failure
391 *==========================================================================*/
392int32_t mm_camera_close(mm_camera_obj_t *my_obj)
393{
394    LOGD("unsubscribe evt");
395    mm_camera_evt_sub(my_obj, FALSE);
396
397    LOGD("Close evt Poll Thread in Cam Close");
398    mm_camera_poll_thread_release(&my_obj->evt_poll_thread);
399
400    LOGD("Close evt cmd Thread in Cam Close");
401    mm_camera_cmd_thread_release(&my_obj->evt_thread);
402
403    if(my_obj->ctrl_fd >= 0) {
404        close(my_obj->ctrl_fd);
405        my_obj->ctrl_fd = -1;
406    }
407    if(my_obj->ds_fd >= 0) {
408        mm_camera_socket_close(my_obj->ds_fd);
409        my_obj->ds_fd = -1;
410    }
411    pthread_mutex_destroy(&my_obj->msg_lock);
412
413    pthread_mutex_destroy(&my_obj->cb_lock);
414    pthread_mutex_destroy(&my_obj->evt_lock);
415    pthread_cond_destroy(&my_obj->evt_cond);
416
417    pthread_mutex_unlock(&my_obj->cam_lock);
418    return 0;
419}
420
421/*===========================================================================
422 * FUNCTION   : mm_camera_register_event_notify_internal
423 *
424 * DESCRIPTION: internal implementation for registering callback for event notify.
425 *
426 * PARAMETERS :
427 *   @my_obj   : ptr to a camera object
428 *   @evt_cb   : callback to be registered to handle event notify
429 *   @user_data: user data ptr
430 *
431 * RETURN     : int32_t type of status
432 *              0  -- success
433 *              -1 -- failure
434 *==========================================================================*/
435int32_t mm_camera_register_event_notify_internal(mm_camera_obj_t *my_obj,
436                                                 mm_camera_event_notify_t evt_cb,
437                                                 void * user_data)
438{
439    int i;
440    int rc = -1;
441    mm_camera_evt_obj_t *evt_array = NULL;
442
443    pthread_mutex_lock(&my_obj->cb_lock);
444    evt_array = &my_obj->evt;
445    if(evt_cb) {
446        /* this is reg case */
447        for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
448            if(evt_array->evt[i].user_data == NULL) {
449                evt_array->evt[i].evt_cb = evt_cb;
450                evt_array->evt[i].user_data = user_data;
451                evt_array->reg_count++;
452                rc = 0;
453                break;
454            }
455        }
456    } else {
457        /* this is unreg case */
458        for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
459            if(evt_array->evt[i].user_data == user_data) {
460                evt_array->evt[i].evt_cb = NULL;
461                evt_array->evt[i].user_data = NULL;
462                evt_array->reg_count--;
463                rc = 0;
464                break;
465            }
466        }
467    }
468
469    pthread_mutex_unlock(&my_obj->cb_lock);
470    return rc;
471}
472
473/*===========================================================================
474 * FUNCTION   : mm_camera_register_event_notify
475 *
476 * DESCRIPTION: registering a callback for event notify.
477 *
478 * PARAMETERS :
479 *   @my_obj   : ptr to a camera object
480 *   @evt_cb   : callback to be registered to handle event notify
481 *   @user_data: user data ptr
482 *
483 * RETURN     : int32_t type of status
484 *              0  -- success
485 *              -1 -- failure
486 *==========================================================================*/
487int32_t mm_camera_register_event_notify(mm_camera_obj_t *my_obj,
488                                        mm_camera_event_notify_t evt_cb,
489                                        void * user_data)
490{
491    int rc = -1;
492    rc = mm_camera_register_event_notify_internal(my_obj,
493                                                  evt_cb,
494                                                  user_data);
495    pthread_mutex_unlock(&my_obj->cam_lock);
496    return rc;
497}
498
499/*===========================================================================
500 * FUNCTION   : mm_camera_qbuf
501 *
502 * DESCRIPTION: enqueue buffer back to kernel
503 *
504 * PARAMETERS :
505 *   @my_obj       : camera object
506 *   @ch_id        : channel handle
507 *   @buf          : buf ptr to be enqueued
508 *
509 * RETURN     : int32_t type of status
510 *              0  -- success
511 *              -1 -- failure
512 *==========================================================================*/
513int32_t mm_camera_qbuf(mm_camera_obj_t *my_obj,
514                       uint32_t ch_id,
515                       mm_camera_buf_def_t *buf)
516{
517    int rc = -1;
518    mm_channel_t * ch_obj = NULL;
519    ch_obj = mm_camera_util_get_channel_by_handler(my_obj, ch_id);
520
521    pthread_mutex_unlock(&my_obj->cam_lock);
522
523    /* we always assume qbuf will be done before channel/stream is fully stopped
524     * because qbuf is done within dataCB context
525     * in order to avoid deadlock, we are not locking ch_lock for qbuf */
526    if (NULL != ch_obj) {
527        rc = mm_channel_qbuf(ch_obj, buf);
528    }
529
530    return rc;
531}
532
533/*===========================================================================
534 * FUNCTION   : mm_camera_get_queued_buf_count
535 *
536 * DESCRIPTION: return queued buffer count
537 *
538 * PARAMETERS :
539 *   @my_obj       : camera object
540 *   @ch_id        : channel handle
541 *   @stream_id : stream id
542 *
543 * RETURN     : queued buffer count
544 *==========================================================================*/
545int32_t mm_camera_get_queued_buf_count(mm_camera_obj_t *my_obj,
546        uint32_t ch_id, uint32_t stream_id)
547{
548    int rc = -1;
549    mm_channel_t * ch_obj = NULL;
550    uint32_t payload;
551    ch_obj = mm_camera_util_get_channel_by_handler(my_obj, ch_id);
552    payload = stream_id;
553
554    if (NULL != ch_obj) {
555        pthread_mutex_lock(&ch_obj->ch_lock);
556        pthread_mutex_unlock(&my_obj->cam_lock);
557        rc = mm_channel_fsm_fn(ch_obj,
558                MM_CHANNEL_EVT_GET_STREAM_QUEUED_BUF_COUNT,
559                (void *)&payload,
560                NULL);
561    } else {
562        pthread_mutex_unlock(&my_obj->cam_lock);
563    }
564
565    return rc;
566}
567
568/*===========================================================================
569 * FUNCTION   : mm_camera_query_capability
570 *
571 * DESCRIPTION: query camera capability
572 *
573 * PARAMETERS :
574 *   @my_obj: camera object
575 *
576 * RETURN     : int32_t type of status
577 *              0  -- success
578 *              -1 -- failure
579 *==========================================================================*/
580int32_t mm_camera_query_capability(mm_camera_obj_t *my_obj)
581{
582    int32_t rc = 0;
583    struct v4l2_capability cap;
584
585    /* get camera capabilities */
586    memset(&cap, 0, sizeof(cap));
587    rc = ioctl(my_obj->ctrl_fd, VIDIOC_QUERYCAP, &cap);
588    if (rc != 0) {
589        LOGE("cannot get camera capabilities, rc = %d, errno %d",
590                 rc, errno);
591    }
592
593    pthread_mutex_unlock(&my_obj->cam_lock);
594    return rc;
595
596}
597
598/*===========================================================================
599 * FUNCTION   : mm_camera_set_parms
600 *
601 * DESCRIPTION: set parameters per camera
602 *
603 * PARAMETERS :
604 *   @my_obj       : camera object
605 *   @parms        : ptr to a param struct to be set to server
606 *
607 * RETURN     : int32_t type of status
608 *              0  -- success
609 *              -1 -- failure
610 * NOTE       : Assume the parms struct buf is already mapped to server via
611 *              domain socket. Corresponding fields of parameters to be set
612 *              are already filled in by upper layer caller.
613 *==========================================================================*/
614int32_t mm_camera_set_parms(mm_camera_obj_t *my_obj,
615                            parm_buffer_t *parms)
616{
617    int32_t rc = -1;
618    int32_t value = 0;
619    if (parms !=  NULL) {
620        rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_PARM, &value);
621    }
622    pthread_mutex_unlock(&my_obj->cam_lock);
623    return rc;
624}
625
626/*===========================================================================
627 * FUNCTION   : mm_camera_get_parms
628 *
629 * DESCRIPTION: get parameters per camera
630 *
631 * PARAMETERS :
632 *   @my_obj       : camera object
633 *   @parms        : ptr to a param struct to be get from server
634 *
635 * RETURN     : int32_t type of status
636 *              0  -- success
637 *              -1 -- failure
638 * NOTE       : Assume the parms struct buf is already mapped to server via
639 *              domain socket. Parameters to be get from server are already
640 *              filled in by upper layer caller. After this call, corresponding
641 *              fields of requested parameters will be filled in by server with
642 *              detailed information.
643 *==========================================================================*/
644int32_t mm_camera_get_parms(mm_camera_obj_t *my_obj,
645                            parm_buffer_t *parms)
646{
647    int32_t rc = -1;
648    int32_t value = 0;
649    if (parms != NULL) {
650        rc = mm_camera_util_g_ctrl(my_obj->ctrl_fd, CAM_PRIV_PARM, &value);
651    }
652    pthread_mutex_unlock(&my_obj->cam_lock);
653    return rc;
654}
655
656/*===========================================================================
657 * FUNCTION   : mm_camera_do_auto_focus
658 *
659 * DESCRIPTION: performing auto focus
660 *
661 * PARAMETERS :
662 *   @camera_handle: camera handle
663 *
664 * RETURN     : int32_t type of status
665 *              0  -- success
666 *              -1 -- failure
667 * NOTE       : if this call success, we will always assume there will
668 *              be an auto_focus event following up.
669 *==========================================================================*/
670int32_t mm_camera_do_auto_focus(mm_camera_obj_t *my_obj)
671{
672    int32_t rc = -1;
673    int32_t value = 0;
674    rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_DO_AUTO_FOCUS, &value);
675    pthread_mutex_unlock(&my_obj->cam_lock);
676    return rc;
677}
678
679/*===========================================================================
680 * FUNCTION   : mm_camera_cancel_auto_focus
681 *
682 * DESCRIPTION: cancel auto focus
683 *
684 * PARAMETERS :
685 *   @camera_handle: camera handle
686 *
687 * RETURN     : int32_t type of status
688 *              0  -- success
689 *              -1 -- failure
690 *==========================================================================*/
691int32_t mm_camera_cancel_auto_focus(mm_camera_obj_t *my_obj)
692{
693    int32_t rc = -1;
694    int32_t value = 0;
695    rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_CANCEL_AUTO_FOCUS, &value);
696    pthread_mutex_unlock(&my_obj->cam_lock);
697    return rc;
698}
699
700/*===========================================================================
701 * FUNCTION   : mm_camera_prepare_snapshot
702 *
703 * DESCRIPTION: prepare hardware for snapshot
704 *
705 * PARAMETERS :
706 *   @my_obj       : camera object
707 *   @do_af_flag   : flag indicating if AF is needed
708 *
709 * RETURN     : int32_t type of status
710 *              0  -- success
711 *              -1 -- failure
712 *==========================================================================*/
713int32_t mm_camera_prepare_snapshot(mm_camera_obj_t *my_obj,
714                                   int32_t do_af_flag)
715{
716    int32_t rc = -1;
717    int32_t value = do_af_flag;
718    rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_PREPARE_SNAPSHOT, &value);
719    pthread_mutex_unlock(&my_obj->cam_lock);
720    return rc;
721}
722
723/*===========================================================================
724 * FUNCTION   : mm_camera_start_zsl_snapshot
725 *
726 * DESCRIPTION: start zsl snapshot
727 *
728 * PARAMETERS :
729 *   @my_obj       : camera object
730 *
731 * RETURN     : int32_t type of status
732 *              0  -- success
733 *              -1 -- failure
734 *==========================================================================*/
735int32_t mm_camera_start_zsl_snapshot(mm_camera_obj_t *my_obj)
736{
737    int32_t rc = -1;
738    int32_t value = 0;
739
740    rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
741             CAM_PRIV_START_ZSL_SNAPSHOT, &value);
742    return rc;
743}
744
745/*===========================================================================
746 * FUNCTION   : mm_camera_stop_zsl_snapshot
747 *
748 * DESCRIPTION: stop zsl capture
749 *
750 * PARAMETERS :
751 *   @my_obj       : camera object
752 *
753 * RETURN     : int32_t type of status
754 *              0  -- success
755 *              -1 -- failure
756 *==========================================================================*/
757int32_t mm_camera_stop_zsl_snapshot(mm_camera_obj_t *my_obj)
758{
759    int32_t rc = -1;
760    int32_t value;
761    rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
762             CAM_PRIV_STOP_ZSL_SNAPSHOT, &value);
763    return rc;
764}
765
766/*===========================================================================
767 * FUNCTION   : mm_camera_flush
768 *
769 * DESCRIPTION: flush the current camera state and buffers
770 *
771 * PARAMETERS :
772 *   @my_obj       : camera object
773 *
774 * RETURN     : int32_t type of status
775 *              0  -- success
776 *              -1 -- failure
777 *==========================================================================*/
778int32_t mm_camera_flush(mm_camera_obj_t *my_obj)
779{
780    int32_t rc = -1;
781    int32_t value;
782    rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
783            CAM_PRIV_FLUSH, &value);
784    pthread_mutex_unlock(&my_obj->cam_lock);
785    return rc;
786}
787
788/*===========================================================================
789 * FUNCTION   : mm_camera_add_channel
790 *
791 * DESCRIPTION: add a channel
792 *
793 * PARAMETERS :
794 *   @my_obj       : camera object
795 *   @attr         : bundle attribute of the channel if needed
796 *   @channel_cb   : callback function for bundle data notify
797 *   @userdata     : user data ptr
798 *
799 * RETURN     : uint32_t type of channel handle
800 *              0  -- invalid channel handle, meaning the op failed
801 *              >0 -- successfully added a channel with a valid handle
802 * NOTE       : if no bundle data notify is needed, meaning each stream in the
803 *              channel will have its own stream data notify callback, then
804 *              attr, channel_cb, and userdata can be NULL. In this case,
805 *              no matching logic will be performed in channel for the bundling.
806 *==========================================================================*/
807uint32_t mm_camera_add_channel(mm_camera_obj_t *my_obj,
808                               mm_camera_channel_attr_t *attr,
809                               mm_camera_buf_notify_t channel_cb,
810                               void *userdata)
811{
812    mm_channel_t *ch_obj = NULL;
813    uint8_t ch_idx = 0;
814    uint32_t ch_hdl = 0;
815
816    for(ch_idx = 0; ch_idx < MM_CAMERA_CHANNEL_MAX; ch_idx++) {
817        if (MM_CHANNEL_STATE_NOTUSED == my_obj->ch[ch_idx].state) {
818            ch_obj = &my_obj->ch[ch_idx];
819            break;
820        }
821    }
822
823    if (NULL != ch_obj) {
824        /* initialize channel obj */
825        memset(ch_obj, 0, sizeof(mm_channel_t));
826        ch_hdl = mm_camera_util_generate_handler(ch_idx);
827        ch_obj->my_hdl = ch_hdl;
828        ch_obj->state = MM_CHANNEL_STATE_STOPPED;
829        ch_obj->cam_obj = my_obj;
830        pthread_mutex_init(&ch_obj->ch_lock, NULL);
831        ch_obj->sessionid = my_obj->sessionid;
832        mm_channel_init(ch_obj, attr, channel_cb, userdata);
833    }
834
835    pthread_mutex_unlock(&my_obj->cam_lock);
836
837    return ch_hdl;
838}
839
840/*===========================================================================
841 * FUNCTION   : mm_camera_del_channel
842 *
843 * DESCRIPTION: delete a channel by its handle
844 *
845 * PARAMETERS :
846 *   @my_obj       : camera object
847 *   @ch_id        : channel handle
848 *
849 * RETURN     : int32_t type of status
850 *              0  -- success
851 *              -1 -- failure
852 * NOTE       : all streams in the channel should be stopped already before
853 *              this channel can be deleted.
854 *==========================================================================*/
855int32_t mm_camera_del_channel(mm_camera_obj_t *my_obj,
856                              uint32_t ch_id)
857{
858    int32_t rc = -1;
859    mm_channel_t * ch_obj =
860        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
861
862    if (NULL != ch_obj) {
863        pthread_mutex_lock(&ch_obj->ch_lock);
864        pthread_mutex_unlock(&my_obj->cam_lock);
865
866        rc = mm_channel_fsm_fn(ch_obj,
867                               MM_CHANNEL_EVT_DELETE,
868                               NULL,
869                               NULL);
870
871        pthread_mutex_destroy(&ch_obj->ch_lock);
872        memset(ch_obj, 0, sizeof(mm_channel_t));
873    } else {
874        pthread_mutex_unlock(&my_obj->cam_lock);
875    }
876    return rc;
877}
878
879/*===========================================================================
880 * FUNCTION   : mm_camera_get_bundle_info
881 *
882 * DESCRIPTION: query bundle info of the channel
883 *
884 * PARAMETERS :
885 *   @my_obj       : camera object
886 *   @ch_id        : channel handle
887 *   @bundle_info  : bundle info to be filled in
888 *
889 * RETURN     : int32_t type of status
890 *              0  -- success
891 *              -1 -- failure
892 * NOTE       : all streams in the channel should be stopped already before
893 *              this channel can be deleted.
894 *==========================================================================*/
895int32_t mm_camera_get_bundle_info(mm_camera_obj_t *my_obj,
896                                  uint32_t ch_id,
897                                  cam_bundle_config_t *bundle_info)
898{
899    int32_t rc = -1;
900    mm_channel_t * ch_obj =
901        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
902
903    if (NULL != ch_obj) {
904        pthread_mutex_lock(&ch_obj->ch_lock);
905        pthread_mutex_unlock(&my_obj->cam_lock);
906
907        rc = mm_channel_fsm_fn(ch_obj,
908                               MM_CHANNEL_EVT_GET_BUNDLE_INFO,
909                               (void *)bundle_info,
910                               NULL);
911    } else {
912        pthread_mutex_unlock(&my_obj->cam_lock);
913    }
914    return rc;
915}
916
917/*===========================================================================
918 * FUNCTION   : mm_camera_link_stream
919 *
920 * DESCRIPTION: link a stream into a channel
921 *
922 * PARAMETERS :
923 *   @my_obj       : camera object
924 *   @ch_id        : channel handle
925 *   @stream_id    : stream that will be linked
926 *   @linked_ch_id : channel in which the stream will be linked
927 *
928 * RETURN     : uint32_t type of stream handle
929 *              0  -- invalid stream handle, meaning the op failed
930 *              >0 -- successfully linked a stream with a valid handle
931 *==========================================================================*/
932uint32_t mm_camera_link_stream(mm_camera_obj_t *my_obj,
933        uint32_t ch_id,
934        uint32_t stream_id,
935        uint32_t linked_ch_id)
936{
937    uint32_t s_hdl = 0;
938    mm_channel_t * ch_obj =
939            mm_camera_util_get_channel_by_handler(my_obj, linked_ch_id);
940    mm_channel_t * owner_obj =
941            mm_camera_util_get_channel_by_handler(my_obj, ch_id);
942
943    if ((NULL != ch_obj) && (NULL != owner_obj)) {
944        pthread_mutex_lock(&ch_obj->ch_lock);
945        pthread_mutex_unlock(&my_obj->cam_lock);
946
947        mm_camera_stream_link_t stream_link;
948        memset(&stream_link, 0, sizeof(mm_camera_stream_link_t));
949        stream_link.ch = owner_obj;
950        stream_link.stream_id = stream_id;
951        mm_channel_fsm_fn(ch_obj,
952                          MM_CHANNEL_EVT_LINK_STREAM,
953                          (void*)&stream_link,
954                          (void*)&s_hdl);
955    } else {
956        pthread_mutex_unlock(&my_obj->cam_lock);
957    }
958
959    return s_hdl;
960}
961
962/*===========================================================================
963 * FUNCTION   : mm_camera_add_stream
964 *
965 * DESCRIPTION: add a stream into a channel
966 *
967 * PARAMETERS :
968 *   @my_obj       : camera object
969 *   @ch_id        : channel handle
970 *
971 * RETURN     : uint32_t type of stream handle
972 *              0  -- invalid stream handle, meaning the op failed
973 *              >0 -- successfully added a stream with a valid handle
974 *==========================================================================*/
975uint32_t mm_camera_add_stream(mm_camera_obj_t *my_obj,
976                              uint32_t ch_id)
977{
978    uint32_t s_hdl = 0;
979    mm_channel_t * ch_obj =
980        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
981
982    if (NULL != ch_obj) {
983        pthread_mutex_lock(&ch_obj->ch_lock);
984        pthread_mutex_unlock(&my_obj->cam_lock);
985
986        mm_channel_fsm_fn(ch_obj,
987                          MM_CHANNEL_EVT_ADD_STREAM,
988                          NULL,
989                          (void *)&s_hdl);
990    } else {
991        pthread_mutex_unlock(&my_obj->cam_lock);
992    }
993
994    return s_hdl;
995}
996
997/*===========================================================================
998 * FUNCTION   : mm_camera_del_stream
999 *
1000 * DESCRIPTION: delete a stream by its handle
1001 *
1002 * PARAMETERS :
1003 *   @my_obj       : camera object
1004 *   @ch_id        : channel handle
1005 *   @stream_id    : stream handle
1006 *
1007 * RETURN     : int32_t type of status
1008 *              0  -- success
1009 *              -1 -- failure
1010 * NOTE       : stream should be stopped already before it can be deleted.
1011 *==========================================================================*/
1012int32_t mm_camera_del_stream(mm_camera_obj_t *my_obj,
1013                             uint32_t ch_id,
1014                             uint32_t stream_id)
1015{
1016    int32_t rc = -1;
1017    mm_channel_t * ch_obj =
1018        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1019
1020    if (NULL != ch_obj) {
1021        pthread_mutex_lock(&ch_obj->ch_lock);
1022        pthread_mutex_unlock(&my_obj->cam_lock);
1023
1024        rc = mm_channel_fsm_fn(ch_obj,
1025                               MM_CHANNEL_EVT_DEL_STREAM,
1026                               (void *)&stream_id,
1027                               NULL);
1028    } else {
1029        pthread_mutex_unlock(&my_obj->cam_lock);
1030    }
1031
1032    return rc;
1033}
1034
1035/*===========================================================================
1036 * FUNCTION   : mm_camera_start_zsl_snapshot_ch
1037 *
1038 * DESCRIPTION: starts zsl snapshot for specific channel
1039 *
1040 * PARAMETERS :
1041 *   @my_obj       : camera object
1042 *   @ch_id        : channel handle
1043 *
1044 * RETURN     : int32_t type of status
1045 *              0  -- success
1046 *              -1 -- failure
1047 *==========================================================================*/
1048int32_t mm_camera_start_zsl_snapshot_ch(mm_camera_obj_t *my_obj,
1049        uint32_t ch_id)
1050{
1051    int32_t rc = -1;
1052    mm_channel_t * ch_obj =
1053        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1054
1055    if (NULL != ch_obj) {
1056        pthread_mutex_lock(&ch_obj->ch_lock);
1057        pthread_mutex_unlock(&my_obj->cam_lock);
1058
1059        rc = mm_channel_fsm_fn(ch_obj,
1060                               MM_CHANNEL_EVT_START_ZSL_SNAPSHOT,
1061                               NULL,
1062                               NULL);
1063    } else {
1064        pthread_mutex_unlock(&my_obj->cam_lock);
1065    }
1066
1067    return rc;
1068}
1069
1070/*===========================================================================
1071 * FUNCTION   : mm_camera_stop_zsl_snapshot_ch
1072 *
1073 * DESCRIPTION: stops zsl snapshot for specific channel
1074 *
1075 * PARAMETERS :
1076 *   @my_obj       : camera object
1077 *   @ch_id        : channel handle
1078 *
1079 * RETURN     : int32_t type of status
1080 *              0  -- success
1081 *              -1 -- failure
1082 *==========================================================================*/
1083int32_t mm_camera_stop_zsl_snapshot_ch(mm_camera_obj_t *my_obj,
1084        uint32_t ch_id)
1085{
1086    int32_t rc = -1;
1087    mm_channel_t * ch_obj =
1088        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1089
1090    if (NULL != ch_obj) {
1091        pthread_mutex_lock(&ch_obj->ch_lock);
1092        pthread_mutex_unlock(&my_obj->cam_lock);
1093
1094        rc = mm_channel_fsm_fn(ch_obj,
1095                               MM_CHANNEL_EVT_STOP_ZSL_SNAPSHOT,
1096                               NULL,
1097                               NULL);
1098    } else {
1099        pthread_mutex_unlock(&my_obj->cam_lock);
1100    }
1101
1102    return rc;
1103}
1104
1105/*===========================================================================
1106 * FUNCTION   : mm_camera_config_stream
1107 *
1108 * DESCRIPTION: configure a stream
1109 *
1110 * PARAMETERS :
1111 *   @my_obj       : camera object
1112 *   @ch_id        : channel handle
1113 *   @stream_id    : stream handle
1114 *   @config       : stream configuration
1115 *
1116 * RETURN     : int32_t type of status
1117 *              0  -- success
1118 *              -1 -- failure
1119 *==========================================================================*/
1120int32_t mm_camera_config_stream(mm_camera_obj_t *my_obj,
1121                                uint32_t ch_id,
1122                                uint32_t stream_id,
1123                                mm_camera_stream_config_t *config)
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    mm_evt_paylod_config_stream_t payload;
1129
1130    if (NULL != ch_obj) {
1131        pthread_mutex_lock(&ch_obj->ch_lock);
1132        pthread_mutex_unlock(&my_obj->cam_lock);
1133
1134        memset(&payload, 0, sizeof(mm_evt_paylod_config_stream_t));
1135        payload.stream_id = stream_id;
1136        payload.config = config;
1137        rc = mm_channel_fsm_fn(ch_obj,
1138                               MM_CHANNEL_EVT_CONFIG_STREAM,
1139                               (void *)&payload,
1140                               NULL);
1141    } else {
1142        pthread_mutex_unlock(&my_obj->cam_lock);
1143    }
1144
1145    return rc;
1146}
1147
1148/*===========================================================================
1149 * FUNCTION   : mm_camera_start_channel
1150 *
1151 * DESCRIPTION: start a channel, which will start all streams in the channel
1152 *
1153 * PARAMETERS :
1154 *   @my_obj       : camera object
1155 *   @ch_id        : channel handle
1156 *
1157 * RETURN     : int32_t type of status
1158 *              0  -- success
1159 *              -1 -- failure
1160 *==========================================================================*/
1161int32_t mm_camera_start_channel(mm_camera_obj_t *my_obj, uint32_t ch_id)
1162{
1163    int32_t rc = -1;
1164    mm_channel_t * ch_obj =
1165        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1166
1167    if (NULL != ch_obj) {
1168        pthread_mutex_lock(&ch_obj->ch_lock);
1169        pthread_mutex_unlock(&my_obj->cam_lock);
1170
1171        rc = mm_channel_fsm_fn(ch_obj,
1172                               MM_CHANNEL_EVT_START,
1173                               NULL,
1174                               NULL);
1175    } else {
1176        pthread_mutex_unlock(&my_obj->cam_lock);
1177    }
1178
1179    return rc;
1180}
1181
1182/*===========================================================================
1183 * FUNCTION   : mm_camera_stop_channel
1184 *
1185 * DESCRIPTION: stop a channel, which will stop all streams in the channel
1186 *
1187 * PARAMETERS :
1188 *   @my_obj       : camera object
1189 *   @ch_id        : channel handle
1190 *
1191 * RETURN     : int32_t type of status
1192 *              0  -- success
1193 *              -1 -- failure
1194 *==========================================================================*/
1195int32_t mm_camera_stop_channel(mm_camera_obj_t *my_obj,
1196                               uint32_t ch_id)
1197{
1198    int32_t rc = 0;
1199    mm_channel_t * ch_obj =
1200        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1201
1202    if (NULL != ch_obj) {
1203        pthread_mutex_lock(&ch_obj->ch_lock);
1204        pthread_mutex_unlock(&my_obj->cam_lock);
1205
1206        rc = mm_channel_fsm_fn(ch_obj,
1207                               MM_CHANNEL_EVT_STOP,
1208                               NULL,
1209                               NULL);
1210    } else {
1211        pthread_mutex_unlock(&my_obj->cam_lock);
1212    }
1213    return rc;
1214}
1215
1216/*===========================================================================
1217 * FUNCTION   : mm_camera_request_super_buf
1218 *
1219 * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched
1220 *              frames from superbuf queue
1221 *
1222 * PARAMETERS :
1223 *   @my_obj       : camera object
1224 *   @ch_id        : channel handle
1225 *   @num_buf_requested : number of matched frames needed
1226 *
1227 * RETURN     : int32_t type of status
1228 *              0  -- success
1229 *              -1 -- failure
1230 *==========================================================================*/
1231int32_t mm_camera_request_super_buf(mm_camera_obj_t *my_obj,
1232        uint32_t ch_id, mm_camera_req_buf_t *buf)
1233{
1234    int32_t rc = -1;
1235    mm_channel_t * ch_obj =
1236        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1237
1238    if ((NULL != ch_obj) && (buf != NULL)) {
1239        pthread_mutex_lock(&ch_obj->ch_lock);
1240        pthread_mutex_unlock(&my_obj->cam_lock);
1241
1242        rc = mm_channel_fsm_fn(ch_obj, MM_CHANNEL_EVT_REQUEST_SUPER_BUF,
1243                (void *)buf, NULL);
1244    } else {
1245        pthread_mutex_unlock(&my_obj->cam_lock);
1246    }
1247
1248    return rc;
1249}
1250
1251/*===========================================================================
1252 * FUNCTION   : mm_camera_cancel_super_buf_request
1253 *
1254 * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount
1255 *              of matched frames from superbuf queue
1256 *
1257 * PARAMETERS :
1258 *   @my_obj       : camera object
1259 *   @ch_id        : channel handle
1260 *
1261 * RETURN     : int32_t type of status
1262 *              0  -- success
1263 *              -1 -- failure
1264 *==========================================================================*/
1265int32_t mm_camera_cancel_super_buf_request(mm_camera_obj_t *my_obj, uint32_t ch_id)
1266{
1267    int32_t rc = -1;
1268    mm_channel_t * ch_obj =
1269        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1270
1271    if (NULL != ch_obj) {
1272        pthread_mutex_lock(&ch_obj->ch_lock);
1273        pthread_mutex_unlock(&my_obj->cam_lock);
1274
1275        rc = mm_channel_fsm_fn(ch_obj,
1276                               MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF,
1277                               NULL,
1278                               NULL);
1279    } else {
1280        pthread_mutex_unlock(&my_obj->cam_lock);
1281    }
1282
1283    return rc;
1284}
1285
1286/*===========================================================================
1287 * FUNCTION   : mm_camera_flush_super_buf_queue
1288 *
1289 * DESCRIPTION: flush out all frames in the superbuf queue
1290 *
1291 * PARAMETERS :
1292 *   @my_obj       : camera object
1293 *   @ch_id        : channel handle
1294 *
1295 * RETURN     : int32_t type of status
1296 *              0  -- success
1297 *              -1 -- failure
1298 *==========================================================================*/
1299int32_t mm_camera_flush_super_buf_queue(mm_camera_obj_t *my_obj, uint32_t ch_id,
1300                                                             uint32_t frame_idx)
1301{
1302    int32_t rc = -1;
1303    mm_channel_t * ch_obj =
1304        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1305
1306    if (NULL != ch_obj) {
1307        pthread_mutex_lock(&ch_obj->ch_lock);
1308        pthread_mutex_unlock(&my_obj->cam_lock);
1309
1310        rc = mm_channel_fsm_fn(ch_obj,
1311                               MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE,
1312                               (void *)&frame_idx,
1313                               NULL);
1314    } else {
1315        pthread_mutex_unlock(&my_obj->cam_lock);
1316    }
1317
1318    return rc;
1319}
1320
1321/*===========================================================================
1322 * FUNCTION   : mm_camera_config_channel_notify
1323 *
1324 * DESCRIPTION: configures the channel notification mode
1325 *
1326 * PARAMETERS :
1327 *   @my_obj       : camera object
1328 *   @ch_id        : channel handle
1329 *   @notify_mode  : notification mode
1330 *
1331 * RETURN     : int32_t type of status
1332 *              0  -- success
1333 *              -1 -- failure
1334 *==========================================================================*/
1335int32_t mm_camera_config_channel_notify(mm_camera_obj_t *my_obj,
1336                                        uint32_t ch_id,
1337                                        mm_camera_super_buf_notify_mode_t notify_mode)
1338{
1339    int32_t rc = -1;
1340    mm_channel_t * ch_obj =
1341        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1342
1343    if (NULL != ch_obj) {
1344        pthread_mutex_lock(&ch_obj->ch_lock);
1345        pthread_mutex_unlock(&my_obj->cam_lock);
1346
1347        rc = mm_channel_fsm_fn(ch_obj,
1348                               MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE,
1349                               (void *)&notify_mode,
1350                               NULL);
1351    } else {
1352        pthread_mutex_unlock(&my_obj->cam_lock);
1353    }
1354
1355    return rc;
1356}
1357
1358/*===========================================================================
1359 * FUNCTION   : mm_camera_set_stream_parms
1360 *
1361 * DESCRIPTION: set parameters per stream
1362 *
1363 * PARAMETERS :
1364 *   @my_obj       : camera object
1365 *   @ch_id        : channel handle
1366 *   @s_id         : stream handle
1367 *   @parms        : ptr to a param struct to be set to server
1368 *
1369 * RETURN     : int32_t type of status
1370 *              0  -- success
1371 *              -1 -- failure
1372 * NOTE       : Assume the parms struct buf is already mapped to server via
1373 *              domain socket. Corresponding fields of parameters to be set
1374 *              are already filled in by upper layer caller.
1375 *==========================================================================*/
1376int32_t mm_camera_set_stream_parms(mm_camera_obj_t *my_obj,
1377                                   uint32_t ch_id,
1378                                   uint32_t s_id,
1379                                   cam_stream_parm_buffer_t *parms)
1380{
1381    int32_t rc = -1;
1382    mm_evt_paylod_set_get_stream_parms_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 = s_id;
1392        payload.parms = parms;
1393
1394        rc = mm_channel_fsm_fn(ch_obj,
1395                               MM_CHANNEL_EVT_SET_STREAM_PARM,
1396                               (void *)&payload,
1397                               NULL);
1398    } else {
1399        pthread_mutex_unlock(&my_obj->cam_lock);
1400    }
1401
1402    return rc;
1403}
1404
1405/*===========================================================================
1406 * FUNCTION   : mm_camera_get_stream_parms
1407 *
1408 * DESCRIPTION: get parameters per stream
1409 *
1410 * PARAMETERS :
1411 *   @my_obj       : camera object
1412 *   @ch_id        : channel handle
1413 *   @s_id         : stream handle
1414 *   @parms        : ptr to a param struct to be get from server
1415 *
1416 * RETURN     : int32_t type of status
1417 *              0  -- success
1418 *              -1 -- failure
1419 * NOTE       : Assume the parms struct buf is already mapped to server via
1420 *              domain socket. Parameters to be get from server are already
1421 *              filled in by upper layer caller. After this call, corresponding
1422 *              fields of requested parameters will be filled in by server with
1423 *              detailed information.
1424 *==========================================================================*/
1425int32_t mm_camera_get_stream_parms(mm_camera_obj_t *my_obj,
1426                                   uint32_t ch_id,
1427                                   uint32_t s_id,
1428                                   cam_stream_parm_buffer_t *parms)
1429{
1430    int32_t rc = -1;
1431    mm_evt_paylod_set_get_stream_parms_t payload;
1432    mm_channel_t * ch_obj =
1433        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1434
1435    if (NULL != ch_obj) {
1436        pthread_mutex_lock(&ch_obj->ch_lock);
1437        pthread_mutex_unlock(&my_obj->cam_lock);
1438
1439        memset(&payload, 0, sizeof(payload));
1440        payload.stream_id = s_id;
1441        payload.parms = parms;
1442
1443        rc = mm_channel_fsm_fn(ch_obj,
1444                               MM_CHANNEL_EVT_GET_STREAM_PARM,
1445                               (void *)&payload,
1446                               NULL);
1447    } else {
1448        pthread_mutex_unlock(&my_obj->cam_lock);
1449    }
1450
1451    return rc;
1452}
1453
1454/*===========================================================================
1455 * FUNCTION   : mm_camera_do_stream_action
1456 *
1457 * DESCRIPTION: request server to perform stream based action. Maybe removed later
1458 *              if the functionality is included in mm_camera_set_parms
1459 *
1460 * PARAMETERS :
1461 *   @my_obj       : camera object
1462 *   @ch_id        : channel handle
1463 *   @s_id         : stream handle
1464 *   @actions      : ptr to an action struct buf to be performed by server
1465 *
1466 * RETURN     : int32_t type of status
1467 *              0  -- success
1468 *              -1 -- failure
1469 * NOTE       : Assume the action struct buf is already mapped to server via
1470 *              domain socket. Actions to be performed by server are already
1471 *              filled in by upper layer caller.
1472 *==========================================================================*/
1473int32_t mm_camera_do_stream_action(mm_camera_obj_t *my_obj,
1474                                   uint32_t ch_id,
1475                                   uint32_t stream_id,
1476                                   void *actions)
1477{
1478    int32_t rc = -1;
1479    mm_evt_paylod_do_stream_action_t payload;
1480    mm_channel_t * ch_obj =
1481        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1482
1483    if (NULL != ch_obj) {
1484        pthread_mutex_lock(&ch_obj->ch_lock);
1485        pthread_mutex_unlock(&my_obj->cam_lock);
1486
1487        memset(&payload, 0, sizeof(payload));
1488        payload.stream_id = stream_id;
1489        payload.actions = actions;
1490
1491        rc = mm_channel_fsm_fn(ch_obj,
1492                               MM_CHANNEL_EVT_DO_STREAM_ACTION,
1493                               (void*)&payload,
1494                               NULL);
1495    } else {
1496        pthread_mutex_unlock(&my_obj->cam_lock);
1497    }
1498
1499    return rc;
1500}
1501
1502/*===========================================================================
1503 * FUNCTION   : mm_camera_map_stream_buf
1504 *
1505 * DESCRIPTION: mapping stream buffer via domain socket to server
1506 *
1507 * PARAMETERS :
1508 *   @my_obj       : camera object
1509 *   @ch_id        : channel handle
1510 *   @s_id         : stream handle
1511 *   @buf_type     : type of buffer to be mapped. could be following values:
1512 *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1513 *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1514 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1515 *   @buf_idx      : index of buffer within the stream buffers, only valid if
1516 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1517 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1518 *   @plane_idx    : plane index. If all planes share the same fd,
1519 *                   plane_idx = -1; otherwise, plean_idx is the
1520 *                   index to plane (0..num_of_planes)
1521 *   @fd           : file descriptor of the buffer
1522 *   @size         : size of the buffer
1523 *
1524 * RETURN     : int32_t type of status
1525 *              0  -- success
1526 *              -1 -- failure
1527 *==========================================================================*/
1528int32_t mm_camera_map_stream_buf(mm_camera_obj_t *my_obj,
1529                                 uint32_t ch_id,
1530                                 uint32_t stream_id,
1531                                 uint8_t buf_type,
1532                                 uint32_t buf_idx,
1533                                 int32_t plane_idx,
1534                                 int fd,
1535                                 size_t size)
1536{
1537    int32_t rc = -1;
1538    cam_buf_map_type payload;
1539    mm_channel_t * ch_obj =
1540        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1541
1542    if (NULL != ch_obj) {
1543        pthread_mutex_lock(&ch_obj->ch_lock);
1544        pthread_mutex_unlock(&my_obj->cam_lock);
1545
1546        memset(&payload, 0, sizeof(payload));
1547        payload.stream_id = stream_id;
1548        payload.type = buf_type;
1549        payload.frame_idx = buf_idx;
1550        payload.plane_idx = plane_idx;
1551        payload.fd = fd;
1552        payload.size = size;
1553        rc = mm_channel_fsm_fn(ch_obj,
1554                               MM_CHANNEL_EVT_MAP_STREAM_BUF,
1555                               (void*)&payload,
1556                               NULL);
1557    } else {
1558        pthread_mutex_unlock(&my_obj->cam_lock);
1559    }
1560
1561    return rc;
1562}
1563
1564/*===========================================================================
1565 * FUNCTION   : mm_camera_map_stream_bufs
1566 *
1567 * DESCRIPTION: mapping stream buffers via domain socket to server
1568 *
1569 * PARAMETERS :
1570 *   @my_obj       : camera object
1571 *   @ch_id        : channel handle
1572 *   @buf_map_list : list of buffers to be mapped
1573 *
1574 * RETURN     : int32_t type of status
1575 *              0  -- success
1576 *              -1 -- failure
1577 *==========================================================================*/
1578int32_t mm_camera_map_stream_bufs(mm_camera_obj_t *my_obj,
1579                                  uint32_t ch_id,
1580                                  const cam_buf_map_type_list *buf_map_list)
1581{
1582    int32_t rc = -1;
1583    cam_buf_map_type_list payload;
1584    mm_channel_t * ch_obj =
1585        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1586
1587    if (NULL != ch_obj) {
1588        pthread_mutex_lock(&ch_obj->ch_lock);
1589        pthread_mutex_unlock(&my_obj->cam_lock);
1590
1591        memcpy(&payload, buf_map_list, sizeof(payload));
1592        rc = mm_channel_fsm_fn(ch_obj,
1593                               MM_CHANNEL_EVT_MAP_STREAM_BUFS,
1594                               (void*)&payload,
1595                               NULL);
1596    } else {
1597        pthread_mutex_unlock(&my_obj->cam_lock);
1598    }
1599
1600    return rc;
1601}
1602
1603/*===========================================================================
1604 * FUNCTION   : mm_camera_unmap_stream_buf
1605 *
1606 * DESCRIPTION: unmapping stream buffer via domain socket to server
1607 *
1608 * PARAMETERS :
1609 *   @my_obj       : camera object
1610 *   @ch_id        : channel handle
1611 *   @s_id         : stream handle
1612 *   @buf_type     : type of buffer to be mapped. could be following values:
1613 *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1614 *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1615 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1616 *   @buf_idx      : index of buffer within the stream buffers, only valid if
1617 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1618 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1619 *   @plane_idx    : plane index. If all planes share the same fd,
1620 *                   plane_idx = -1; otherwise, plean_idx is the
1621 *                   index to plane (0..num_of_planes)
1622 *
1623 * RETURN     : int32_t type of status
1624 *              0  -- success
1625 *              -1 -- failure
1626 *==========================================================================*/
1627int32_t mm_camera_unmap_stream_buf(mm_camera_obj_t *my_obj,
1628                                   uint32_t ch_id,
1629                                   uint32_t stream_id,
1630                                   uint8_t buf_type,
1631                                   uint32_t buf_idx,
1632                                   int32_t plane_idx)
1633{
1634    int32_t rc = -1;
1635    cam_buf_unmap_type payload;
1636    mm_channel_t * ch_obj =
1637        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1638
1639    if (NULL != ch_obj) {
1640        pthread_mutex_lock(&ch_obj->ch_lock);
1641        pthread_mutex_unlock(&my_obj->cam_lock);
1642
1643        memset(&payload, 0, sizeof(payload));
1644        payload.stream_id = stream_id;
1645        payload.type = buf_type;
1646        payload.frame_idx = buf_idx;
1647        payload.plane_idx = plane_idx;
1648        rc = mm_channel_fsm_fn(ch_obj,
1649                               MM_CHANNEL_EVT_UNMAP_STREAM_BUF,
1650                               (void*)&payload,
1651                               NULL);
1652    } else {
1653        pthread_mutex_unlock(&my_obj->cam_lock);
1654    }
1655
1656    return rc;
1657}
1658
1659/*===========================================================================
1660 * FUNCTION   : mm_camera_evt_sub
1661 *
1662 * DESCRIPTION: subscribe/unsubscribe event notify from kernel
1663 *
1664 * PARAMETERS :
1665 *   @my_obj       : camera object
1666 *   @reg_flag     : 1 -- subscribe ; 0 -- unsubscribe
1667 *
1668 * RETURN     : int32_t type of status
1669 *              0  -- success
1670 *              -1 -- failure
1671 *==========================================================================*/
1672int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj,
1673                          uint8_t reg_flag)
1674{
1675    int32_t rc = 0;
1676    struct v4l2_event_subscription sub;
1677
1678    memset(&sub, 0, sizeof(sub));
1679    sub.type = MSM_CAMERA_V4L2_EVENT_TYPE;
1680    sub.id = MSM_CAMERA_MSM_NOTIFY;
1681    if(FALSE == reg_flag) {
1682        /* unsubscribe */
1683        rc = ioctl(my_obj->ctrl_fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
1684        if (rc < 0) {
1685            LOGE("unsubscribe event rc = %d, errno %d",
1686                     rc, errno);
1687            return rc;
1688        }
1689        /* remove evt fd from the polling thraed when unreg the last event */
1690        rc = mm_camera_poll_thread_del_poll_fd(&my_obj->evt_poll_thread,
1691                                               my_obj->my_hdl,
1692                                               mm_camera_sync_call);
1693    } else {
1694        rc = ioctl(my_obj->ctrl_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
1695        if (rc < 0) {
1696            LOGE("subscribe event rc = %d, errno %d",
1697             rc, errno);
1698            return rc;
1699        }
1700        /* add evt fd to polling thread when subscribe the first event */
1701        rc = mm_camera_poll_thread_add_poll_fd(&my_obj->evt_poll_thread,
1702                                               my_obj->my_hdl,
1703                                               my_obj->ctrl_fd,
1704                                               mm_camera_event_notify,
1705                                               (void*)my_obj,
1706                                               mm_camera_sync_call);
1707    }
1708    return rc;
1709}
1710
1711/*===========================================================================
1712 * FUNCTION   : mm_camera_util_wait_for_event
1713 *
1714 * DESCRIPTION: utility function to wait for certain events
1715 *
1716 * PARAMETERS :
1717 *   @my_obj       : camera object
1718 *   @evt_mask     : mask for events to be waited. Any of event in the mask would
1719 *                   trigger the wait to end
1720 *   @status       : status of the event
1721 *
1722 * RETURN     : none
1723 *==========================================================================*/
1724void mm_camera_util_wait_for_event(mm_camera_obj_t *my_obj,
1725                                   uint32_t evt_mask,
1726                                   uint32_t *status)
1727{
1728    int32_t rc = 0;
1729    struct timespec ts;
1730
1731    pthread_mutex_lock(&my_obj->evt_lock);
1732    while (!(my_obj->evt_rcvd.server_event_type & evt_mask)) {
1733        clock_gettime(CLOCK_REALTIME, &ts);
1734        ts.tv_sec += WAIT_TIMEOUT;
1735        rc = pthread_cond_timedwait(&my_obj->evt_cond, &my_obj->evt_lock, &ts);
1736        if (rc) {
1737            LOGE("pthread_cond_timedwait of evt_mask 0x%x failed %d",
1738                     evt_mask, rc);
1739            break;
1740        }
1741    }
1742    if (!rc) {
1743        *status = my_obj->evt_rcvd.status;
1744    } else {
1745        *status = MSM_CAMERA_STATUS_FAIL;
1746    }
1747    /* reset local storage for recieved event for next event */
1748    memset(&my_obj->evt_rcvd, 0, sizeof(mm_camera_event_t));
1749    pthread_mutex_unlock(&my_obj->evt_lock);
1750}
1751
1752/*===========================================================================
1753 * FUNCTION   : mm_camera_util_bundled_sendmsg
1754 *
1755 * DESCRIPTION: utility function to send bundled msg via domain socket
1756 *
1757 * PARAMETERS :
1758 *   @my_obj       : camera object
1759 *   @msg          : message to be sent
1760 *   @buf_size     : size of the message to be sent
1761 *   @sendfds      : array of file descriptors to be sent
1762 *   @numfds       : number of file descriptors to be sent
1763 *
1764 * RETURN     : int32_t type of status
1765 *              0  -- success
1766 *              -1 -- failure
1767 *==========================================================================*/
1768int32_t mm_camera_util_bundled_sendmsg(mm_camera_obj_t *my_obj,
1769                                       void *msg,
1770                                       size_t buf_size,
1771                                       int sendfds[CAM_MAX_NUM_BUFS_PER_STREAM],
1772                                       int numfds)
1773{
1774    int32_t rc = -1;
1775    uint32_t status;
1776
1777    /* need to lock msg_lock, since sendmsg until response back is deemed as one operation*/
1778    pthread_mutex_lock(&my_obj->msg_lock);
1779    if(mm_camera_socket_bundle_sendmsg(my_obj->ds_fd, msg, buf_size, sendfds, numfds) > 0) {
1780        /* wait for event that mapping/unmapping is done */
1781        mm_camera_util_wait_for_event(my_obj, CAM_EVENT_TYPE_MAP_UNMAP_DONE, &status);
1782        if (MSM_CAMERA_STATUS_SUCCESS == status) {
1783            rc = 0;
1784        }
1785    }
1786    pthread_mutex_unlock(&my_obj->msg_lock);
1787    return rc;
1788}
1789
1790/*===========================================================================
1791 * FUNCTION   : mm_camera_util_sendmsg
1792 *
1793 * DESCRIPTION: utility function to send msg via domain socket
1794 *
1795 * PARAMETERS :
1796 *   @my_obj       : camera object
1797 *   @msg          : message to be sent
1798 *   @buf_size     : size of the message to be sent
1799 *   @sendfd       : >0 if any file descriptor need to be passed across process
1800 *
1801 * RETURN     : int32_t type of status
1802 *              0  -- success
1803 *              -1 -- failure
1804 *==========================================================================*/
1805int32_t mm_camera_util_sendmsg(mm_camera_obj_t *my_obj,
1806                               void *msg,
1807                               size_t buf_size,
1808                               int sendfd)
1809{
1810    int32_t rc = -1;
1811    uint32_t status;
1812
1813    /* need to lock msg_lock, since sendmsg until reposonse back is deemed as one operation*/
1814    pthread_mutex_lock(&my_obj->msg_lock);
1815    if(mm_camera_socket_sendmsg(my_obj->ds_fd, msg, buf_size, sendfd) > 0) {
1816        /* wait for event that mapping/unmapping is done */
1817        mm_camera_util_wait_for_event(my_obj, CAM_EVENT_TYPE_MAP_UNMAP_DONE, &status);
1818        if (MSM_CAMERA_STATUS_SUCCESS == status) {
1819            rc = 0;
1820        }
1821    }
1822    pthread_mutex_unlock(&my_obj->msg_lock);
1823    return rc;
1824}
1825
1826/*===========================================================================
1827 * FUNCTION   : mm_camera_map_buf
1828 *
1829 * DESCRIPTION: mapping camera buffer via domain socket to server
1830 *
1831 * PARAMETERS :
1832 *   @my_obj       : camera object
1833 *   @buf_type     : type of buffer to be mapped. could be following values:
1834 *                   CAM_MAPPING_BUF_TYPE_CAPABILITY
1835 *                   CAM_MAPPING_BUF_TYPE_SETPARM_BUF
1836 *                   CAM_MAPPING_BUF_TYPE_GETPARM_BUF
1837 *   @fd           : file descriptor of the buffer
1838 *   @size         : size of the buffer
1839 *
1840 * RETURN     : int32_t type of status
1841 *              0  -- success
1842 *              -1 -- failure
1843 *==========================================================================*/
1844int32_t mm_camera_map_buf(mm_camera_obj_t *my_obj,
1845                          uint8_t buf_type,
1846                          int fd,
1847                          size_t size)
1848{
1849    int32_t rc = 0;
1850    cam_sock_packet_t packet;
1851    memset(&packet, 0, sizeof(cam_sock_packet_t));
1852    packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
1853    packet.payload.buf_map.type = buf_type;
1854    packet.payload.buf_map.fd = fd;
1855    packet.payload.buf_map.size = size;
1856    rc = mm_camera_util_sendmsg(my_obj,
1857                                &packet,
1858                                sizeof(cam_sock_packet_t),
1859                                fd);
1860    pthread_mutex_unlock(&my_obj->cam_lock);
1861    return rc;
1862}
1863
1864/*===========================================================================
1865 * FUNCTION   : mm_camera_map_bufs
1866 *
1867 * DESCRIPTION: mapping camera buffers via domain socket to server
1868 *
1869 * PARAMETERS :
1870 *   @my_obj       : camera object
1871 *   @buf_map_list : list of buffers to be mapped
1872 *
1873 * RETURN     : int32_t type of status
1874 *              0  -- success
1875 *              -1 -- failure
1876 *==========================================================================*/
1877int32_t mm_camera_map_bufs(mm_camera_obj_t *my_obj,
1878                           const cam_buf_map_type_list* buf_map_list)
1879{
1880    int32_t rc = 0;
1881    cam_sock_packet_t packet;
1882    memset(&packet, 0, sizeof(cam_sock_packet_t));
1883    packet.msg_type = CAM_MAPPING_TYPE_FD_BUNDLED_MAPPING;
1884
1885    memcpy(&packet.payload.buf_map_list, buf_map_list,
1886           sizeof(packet.payload.buf_map_list));
1887
1888    int sendfds[CAM_MAX_NUM_BUFS_PER_STREAM];
1889    uint32_t numbufs = packet.payload.buf_map_list.length;
1890    uint32_t i;
1891    for (i = 0; i < numbufs; i++) {
1892        sendfds[i] = packet.payload.buf_map_list.buf_maps[i].fd;
1893    }
1894
1895    for (i = numbufs; i < CAM_MAX_NUM_BUFS_PER_STREAM; i++) {
1896        packet.payload.buf_map_list.buf_maps[i].fd = -1;
1897        sendfds[i] = -1;
1898    }
1899
1900    rc = mm_camera_util_bundled_sendmsg(my_obj,
1901                                        &packet,
1902                                        sizeof(cam_sock_packet_t),
1903                                        sendfds,
1904                                        numbufs);
1905
1906    pthread_mutex_unlock(&my_obj->cam_lock);
1907    return rc;
1908}
1909
1910/*===========================================================================
1911 * FUNCTION   : mm_camera_unmap_buf
1912 *
1913 * DESCRIPTION: unmapping camera buffer via domain socket to server
1914 *
1915 * PARAMETERS :
1916 *   @my_obj       : camera object
1917 *   @buf_type     : type of buffer to be mapped. could be following values:
1918 *                   CAM_MAPPING_BUF_TYPE_CAPABILITY
1919 *                   CAM_MAPPING_BUF_TYPE_SETPARM_BUF
1920 *                   CAM_MAPPING_BUF_TYPE_GETPARM_BUF
1921 *
1922 * RETURN     : int32_t type of status
1923 *              0  -- success
1924 *              -1 -- failure
1925 *==========================================================================*/
1926int32_t mm_camera_unmap_buf(mm_camera_obj_t *my_obj,
1927                            uint8_t buf_type)
1928{
1929    int32_t rc = 0;
1930    cam_sock_packet_t packet;
1931    memset(&packet, 0, sizeof(cam_sock_packet_t));
1932    packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING;
1933    packet.payload.buf_unmap.type = buf_type;
1934    rc = mm_camera_util_sendmsg(my_obj,
1935                                &packet,
1936                                sizeof(cam_sock_packet_t),
1937                                -1);
1938    pthread_mutex_unlock(&my_obj->cam_lock);
1939    return rc;
1940}
1941
1942/*===========================================================================
1943 * FUNCTION   : mm_camera_util_s_ctrl
1944 *
1945 * DESCRIPTION: utility function to send v4l2 ioctl for s_ctrl
1946 *
1947 * PARAMETERS :
1948 *   @fd      : file descritpor for sending ioctl
1949 *   @id      : control id
1950 *   @value   : value of the ioctl to be sent
1951 *
1952 * RETURN     : int32_t type of status
1953 *              0  -- success
1954 *              -1 -- failure
1955 *==========================================================================*/
1956int32_t mm_camera_util_s_ctrl(int32_t fd,  uint32_t id, int32_t *value)
1957{
1958    int rc = 0;
1959    struct v4l2_control control;
1960
1961    memset(&control, 0, sizeof(control));
1962    control.id = id;
1963    if (value != NULL) {
1964        control.value = *value;
1965    }
1966    rc = ioctl(fd, VIDIOC_S_CTRL, &control);
1967
1968    LOGD("fd=%d, S_CTRL, id=0x%x, value = %p, rc = %d\n",
1969          fd, id, value, rc);
1970    if (rc < 0) {
1971        LOGE("ioctl failed %d, errno %d", rc, errno);
1972    } else if (value != NULL) {
1973        *value = control.value;
1974    }
1975    return (rc >= 0)? 0 : -1;
1976}
1977
1978/*===========================================================================
1979 * FUNCTION   : mm_camera_util_g_ctrl
1980 *
1981 * DESCRIPTION: utility function to send v4l2 ioctl for g_ctrl
1982 *
1983 * PARAMETERS :
1984 *   @fd      : file descritpor for sending ioctl
1985 *   @id      : control id
1986 *   @value   : value of the ioctl to be sent
1987 *
1988 * RETURN     : int32_t type of status
1989 *              0  -- success
1990 *              -1 -- failure
1991 *==========================================================================*/
1992int32_t mm_camera_util_g_ctrl( int32_t fd, uint32_t id, int32_t *value)
1993{
1994    int rc = 0;
1995    struct v4l2_control control;
1996
1997    memset(&control, 0, sizeof(control));
1998    control.id = id;
1999    if (value != NULL) {
2000        control.value = *value;
2001    }
2002    rc = ioctl(fd, VIDIOC_G_CTRL, &control);
2003    LOGD("fd=%d, G_CTRL, id=0x%x, rc = %d\n", fd, id, rc);
2004    if (value != NULL) {
2005        *value = control.value;
2006    }
2007    return (rc >= 0)? 0 : -1;
2008}
2009
2010/*===========================================================================
2011 * FUNCTION   : mm_camera_channel_advanced_capture
2012 *
2013 * DESCRIPTION: sets the channel advanced capture
2014 *
2015 * PARAMETERS :
2016 *   @my_obj       : camera object
2017 *   @ch_id        : channel handle
2018  *   @type : advanced capture type.
2019 *   @start_flag  : flag to indicate start/stop
2020  *   @in_value  : input configaration
2021 *
2022 * RETURN     : int32_t type of status
2023 *              0  -- success
2024 *              -1 -- failure
2025 *==========================================================================*/
2026int32_t mm_camera_channel_advanced_capture(mm_camera_obj_t *my_obj,
2027            uint32_t ch_id, mm_camera_advanced_capture_t type,
2028            uint32_t trigger, void *in_value)
2029{
2030    LOGD("E type = %d", type);
2031    int32_t rc = -1;
2032    mm_channel_t * ch_obj =
2033        mm_camera_util_get_channel_by_handler(my_obj, ch_id);
2034
2035    if (NULL != ch_obj) {
2036        pthread_mutex_lock(&ch_obj->ch_lock);
2037        pthread_mutex_unlock(&my_obj->cam_lock);
2038        switch (type) {
2039            case MM_CAMERA_AF_BRACKETING:
2040                rc = mm_channel_fsm_fn(ch_obj,
2041                                       MM_CHANNEL_EVT_AF_BRACKETING,
2042                                       (void *)&trigger,
2043                                       NULL);
2044                break;
2045            case MM_CAMERA_AE_BRACKETING:
2046                rc = mm_channel_fsm_fn(ch_obj,
2047                                       MM_CHANNEL_EVT_AE_BRACKETING,
2048                                       (void *)&trigger,
2049                                       NULL);
2050                break;
2051            case MM_CAMERA_FLASH_BRACKETING:
2052                rc = mm_channel_fsm_fn(ch_obj,
2053                                       MM_CHANNEL_EVT_FLASH_BRACKETING,
2054                                       (void *)&trigger,
2055                                       NULL);
2056                break;
2057            case MM_CAMERA_ZOOM_1X:
2058                rc = mm_channel_fsm_fn(ch_obj,
2059                                       MM_CHANNEL_EVT_ZOOM_1X,
2060                                       (void *)&trigger,
2061                                       NULL);
2062                break;
2063            case MM_CAMERA_FRAME_CAPTURE:
2064                rc = mm_channel_fsm_fn(ch_obj,
2065                                       MM_CAMERA_EVT_CAPTURE_SETTING,
2066                                       (void *)in_value,
2067                                       NULL);
2068                break;
2069            default:
2070                break;
2071        }
2072
2073    } else {
2074        pthread_mutex_unlock(&my_obj->cam_lock);
2075    }
2076
2077    LOGD("X");
2078    return rc;
2079}
2080
2081/*===========================================================================
2082 * FUNCTION   : mm_camera_get_session_id
2083 *
2084 * DESCRIPTION: get the session identity
2085 *
2086 * PARAMETERS :
2087 *   @my_obj       : camera object
2088 *   @sessionid: pointer to the output session id
2089 *
2090 * RETURN     : int32_t type of status
2091 *              0  -- success
2092 *              -1 -- failure
2093 * NOTE       : if this call succeeds, we will get a valid session id
2094 *==========================================================================*/
2095int32_t mm_camera_get_session_id(mm_camera_obj_t *my_obj,
2096        uint32_t* sessionid)
2097{
2098    int32_t rc = -1;
2099    int32_t value = 0;
2100    if(sessionid != NULL) {
2101        rc = mm_camera_util_g_ctrl(my_obj->ctrl_fd,
2102                MSM_CAMERA_PRIV_G_SESSION_ID, &value);
2103        LOGD("fd=%d, get_session_id, id=0x%x, value = %d, rc = %d\n",
2104                 my_obj->ctrl_fd, MSM_CAMERA_PRIV_G_SESSION_ID,
2105                value, rc);
2106        *sessionid = value;
2107        my_obj->sessionid = value;
2108    }
2109
2110    pthread_mutex_unlock(&my_obj->cam_lock);
2111    return rc;
2112}
2113
2114/*===========================================================================
2115 * FUNCTION   : mm_camera_sync_related_sensors
2116 *
2117 * DESCRIPTION: send sync cmd
2118 *
2119 * PARAMETERS :
2120 *   @my_obj       : camera object
2121 *   @parms        : ptr to the related cam info to be sent to server
2122 *
2123 * RETURN     : int32_t type of status
2124 *              0  -- success
2125 *              -1 -- failure
2126 * NOTE       : Assume the sync struct buf is already mapped to server via
2127 *              domain socket. Corresponding fields of parameters to be set
2128 *              are already filled in by upper layer caller.
2129 *==========================================================================*/
2130int32_t mm_camera_sync_related_sensors(mm_camera_obj_t *my_obj,
2131        cam_sync_related_sensors_event_info_t* parms)
2132{
2133    int32_t rc = -1;
2134    int32_t value = 0;
2135    if (parms !=  NULL) {
2136        rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
2137                CAM_PRIV_SYNC_RELATED_SENSORS, &value);
2138    }
2139    pthread_mutex_unlock(&my_obj->cam_lock);
2140    return rc;
2141}
2142
2143/*===========================================================================
2144 * FUNCTION   : mm_camera_reg_stream_buf_cb
2145 *
2146 * DESCRIPTION: Register callback for stream buffer
2147 *
2148 * PARAMETERS :
2149 *   @my_obj    : camera object
2150 *   @ch_id     : channel handle
2151 *   @stream_id : stream that will be linked
2152 *   @buf_cb    : special callback needs to be registered for stream buffer
2153 *   @cb_type   : Callback type SYNC/ASYNC
2154 *   @userdata  : user data pointer
2155 *
2156 * RETURN    : int32_t type of status
2157 *             0  -- success
2158 *             1 --  failure
2159 *==========================================================================*/
2160int32_t mm_camera_reg_stream_buf_cb(mm_camera_obj_t *my_obj,
2161        uint32_t ch_id, uint32_t stream_id, mm_camera_buf_notify_t stream_cb,
2162        mm_camera_stream_cb_type cb_type, void *userdata)
2163{
2164    int rc = 0;
2165    mm_stream_data_cb_t buf_cb;
2166    mm_channel_t * ch_obj =
2167            mm_camera_util_get_channel_by_handler(my_obj, ch_id);
2168
2169    if (NULL != ch_obj) {
2170        pthread_mutex_lock(&ch_obj->ch_lock);
2171        pthread_mutex_unlock(&my_obj->cam_lock);
2172
2173        memset(&buf_cb, 0, sizeof(mm_stream_data_cb_t));
2174        buf_cb.cb = stream_cb;
2175        buf_cb.cb_count = -1;
2176        buf_cb.cb_type = cb_type;
2177        buf_cb.user_data = userdata;
2178
2179        mm_evt_paylod_reg_stream_buf_cb payload;
2180        memset(&payload, 0, sizeof(mm_evt_paylod_reg_stream_buf_cb));
2181        payload.buf_cb = buf_cb;
2182        payload.stream_id = stream_id;
2183        mm_channel_fsm_fn(ch_obj,
2184                MM_CHANNEL_EVT_REG_STREAM_BUF_CB,
2185                (void*)&payload, NULL);
2186    } else {
2187        pthread_mutex_unlock(&my_obj->cam_lock);
2188    }
2189    return rc;
2190}
2191
2192#ifdef QCAMERA_REDEFINE_LOG
2193
2194/*===========================================================================
2195 * DESCRIPTION: mm camera debug interface
2196 *
2197 *==========================================================================*/
2198pthread_mutex_t dbg_log_mutex;
2199
2200#undef LOG_TAG
2201#define LOG_TAG "QCamera"
2202#define CDBG_MAX_STR_LEN 1024
2203#define CDBG_MAX_LINE_LENGTH 256
2204
2205/* current trace loggin permissions
2206   * {NONE, ERR, WARN, HIGH, DEBUG, LOW, INFO} */
2207int g_cam_log[CAM_LAST_MODULE][CAM_GLBL_DBG_INFO + 1] = {
2208    {0, 1, 0, 0, 0, 0, 1}, /* CAM_NO_MODULE     */
2209    {0, 1, 0, 0, 0, 0, 1}, /* CAM_HAL_MODULE    */
2210    {0, 1, 0, 0, 0, 0, 1}, /* CAM_MCI_MODULE    */
2211    {0, 1, 0, 0, 0, 0, 1}, /* CAM_JPEG_MODULE   */
2212};
2213
2214/* string representation for logging level */
2215static const char *cam_dbg_level_to_str[] = {
2216     "",        /* CAM_GLBL_DBG_NONE  */
2217     "<ERROR>", /* CAM_GLBL_DBG_ERR   */
2218     "<WARN>", /* CAM_GLBL_DBG_WARN  */
2219     "<HIGH>", /* CAM_GLBL_DBG_HIGH  */
2220     "<DBG>", /* CAM_GLBL_DBG_DEBUG */
2221     "<LOW>", /* CAM_GLBL_DBG_LOW   */
2222     "<INFO>"  /* CAM_GLBL_DBG_INFO  */
2223};
2224
2225/* current trace logging configuration */
2226typedef struct {
2227   cam_global_debug_level_t  level;
2228   int                       initialized;
2229   const char               *name;
2230   const char               *prop;
2231} module_debug_t;
2232
2233static module_debug_t cam_loginfo[(int)CAM_LAST_MODULE] = {
2234  {CAM_GLBL_DBG_ERR, 1,
2235      "",         "persist.camera.global.debug"     }, /* CAM_NO_MODULE     */
2236  {CAM_GLBL_DBG_ERR, 1,
2237      "<HAL>", "persist.camera.hal.debug"        }, /* CAM_HAL_MODULE    */
2238  {CAM_GLBL_DBG_ERR, 1,
2239      "<MCI>", "persist.camera.mci.debug"        }, /* CAM_MCI_MODULE    */
2240  {CAM_GLBL_DBG_ERR, 1,
2241      "<JPEG>", "persist.camera.mmstill.logs"     }, /* CAM_JPEG_MODULE   */
2242};
2243
2244/** cam_get_dbg_level
2245 *
2246 *    @module: module name
2247 *    @level:  module debug logging level
2248 *
2249 *  Maps debug log string to value.
2250 *
2251 *  Return: logging level
2252 **/
2253__unused
2254static cam_global_debug_level_t cam_get_dbg_level(const char *module,
2255  char *pValue) {
2256
2257  cam_global_debug_level_t rc = CAM_GLBL_DBG_NONE;
2258
2259  if (!strcmp(pValue, "none")) {
2260    rc = CAM_GLBL_DBG_NONE;
2261  } else if (!strcmp(pValue, "warn")) {
2262    rc = CAM_GLBL_DBG_WARN;
2263  } else if (!strcmp(pValue, "debug")) {
2264    rc = CAM_GLBL_DBG_DEBUG;
2265  } else if (!strcmp(pValue, "error")) {
2266    rc = CAM_GLBL_DBG_ERR;
2267  } else if (!strcmp(pValue, "low")) {
2268    rc = CAM_GLBL_DBG_LOW;
2269  } else if (!strcmp(pValue, "high")) {
2270    rc = CAM_GLBL_DBG_HIGH;
2271  } else if (!strcmp(pValue, "info")) {
2272    rc = CAM_GLBL_DBG_INFO;
2273  } else {
2274    ALOGE("Invalid %s debug log level %s\n", module, pValue);
2275  }
2276
2277  ALOGD("%s debug log level: %s\n", module, cam_dbg_level_to_str[rc]);
2278
2279  return rc;
2280}
2281
2282/** cam_vsnprintf
2283 *    @pdst:   destination buffer pointer
2284 *    @size:   size of destination b uffer
2285 *    @pfmt:   string format
2286 *    @argptr: variabkle length argument list
2287 *
2288 *  Processes variable length argument list to a formatted string.
2289 *
2290 *  Return: n/a
2291 **/
2292static void cam_vsnprintf(char* pdst, unsigned int size,
2293                          const char* pfmt, va_list argptr) {
2294  int num_chars_written = 0;
2295
2296  pdst[0] = '\0';
2297  num_chars_written = vsnprintf(pdst, size, pfmt, argptr);
2298
2299  if ((num_chars_written >= (int)size) && (size > 0)) {
2300     /* Message length exceeds the buffer limit size */
2301     num_chars_written = size - 1;
2302     pdst[size - 1] = '\0';
2303  }
2304}
2305
2306/** mm_camera_debug_log
2307 *    @module: origin or log message
2308 *    @level:  logging level
2309 *    @func:   caller function name
2310 *    @line:   caller line number
2311 *    @fmt:    log message formatting string
2312 *    @...:    variable argument list
2313 *
2314 *  Generig logger method.
2315 *
2316 *  Return: N/A
2317 **/
2318void mm_camera_debug_log(const cam_modules_t module,
2319                   const cam_global_debug_level_t level,
2320                   const char *func, const int line, const char *fmt, ...) {
2321  char    str_buffer[CDBG_MAX_STR_LEN];
2322  va_list args;
2323
2324  va_start(args, fmt);
2325  cam_vsnprintf(str_buffer, CDBG_MAX_STR_LEN, fmt, args);
2326  va_end(args);
2327
2328  switch (level) {
2329  case CAM_GLBL_DBG_WARN:
2330    ALOGW("%s%s %s: %d: %s", cam_loginfo[module].name,
2331      cam_dbg_level_to_str[level], func, line, str_buffer);
2332    break;
2333  case CAM_GLBL_DBG_ERR:
2334    ALOGE("%s%s %s: %d: %s", cam_loginfo[module].name,
2335      cam_dbg_level_to_str[level], func, line, str_buffer);
2336    break;
2337  case CAM_GLBL_DBG_INFO:
2338    ALOGI("%s%s %s: %d: %s", cam_loginfo[module].name,
2339      cam_dbg_level_to_str[level], func, line, str_buffer);
2340    break;
2341  case CAM_GLBL_DBG_HIGH:
2342  case CAM_GLBL_DBG_DEBUG:
2343  case CAM_GLBL_DBG_LOW:
2344  default:
2345    ALOGD("%s%s %s: %d: %s", cam_loginfo[module].name,
2346      cam_dbg_level_to_str[level], func, line, str_buffer);
2347  }
2348}
2349
2350 /** mm_camera_set_dbg_log_properties
2351 *
2352 *  Set global and module log level properties.
2353 *
2354 *  Return: N/A
2355 **/
2356void mm_camera_set_dbg_log_properties(void) {
2357  int          i;
2358  unsigned int j;
2359  static int   boot_init = 1;
2360  char         property_value[PROPERTY_VALUE_MAX] = {0};
2361  char         default_value[PROPERTY_VALUE_MAX]  = {0};
2362
2363  if (boot_init) {
2364      boot_init = 0;
2365      pthread_mutex_init(&dbg_log_mutex, 0);
2366  }
2367
2368  /* set global and individual module logging levels */
2369  pthread_mutex_lock(&dbg_log_mutex);
2370  for (i = CAM_NO_MODULE; i < CAM_LAST_MODULE; i++) {
2371    cam_global_debug_level_t log_level;
2372    snprintf(default_value, PROPERTY_VALUE_MAX, "%d", (int)cam_loginfo[i].level);
2373    property_get(cam_loginfo[i].prop, property_value, default_value);
2374    log_level = (cam_global_debug_level_t)atoi(property_value);
2375
2376    /* fix KW warnings */
2377    if (log_level > CAM_GLBL_DBG_INFO) {
2378       log_level = CAM_GLBL_DBG_INFO;
2379    }
2380
2381    cam_loginfo[i].level = log_level;
2382
2383    /* The logging macros will produce a log message when logging level for
2384     * a module is less or equal to the level specified in the property for
2385     * the module, or less or equal the level specified by the global logging
2386     * property. Currently we don't allow INFO logging to be turned off */
2387    for (j = CAM_GLBL_DBG_ERR; j <= CAM_GLBL_DBG_LOW; j++) {
2388      g_cam_log[i][j] = (cam_loginfo[CAM_NO_MODULE].level != CAM_GLBL_DBG_NONE)     &&
2389                        (cam_loginfo[i].level             != CAM_GLBL_DBG_NONE)     &&
2390                        ((j                                <= cam_loginfo[i].level) ||
2391                         (j                                <= cam_loginfo[CAM_NO_MODULE].level));
2392    }
2393  }
2394  pthread_mutex_unlock(&dbg_log_mutex);
2395}
2396
2397#endif
2398