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