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