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