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