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