mm_camera_interface.c revision 1843dcd973c7f9ba08362c524d1f731fa827b662
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#include <linux/media.h>
38
39#include "mm_camera_dbg.h"
40#include "mm_camera_interface.h"
41#include "mm_camera_sock.h"
42#include "mm_camera.h"
43
44static pthread_mutex_t g_intf_lock = PTHREAD_MUTEX_INITIALIZER;
45
46static mm_camera_ctrl_t g_cam_ctrl = {0, {{0}}, {0}};
47
48static pthread_mutex_t g_handler_lock = PTHREAD_MUTEX_INITIALIZER;
49static uint16_t g_handler_history_count = 0; /* history count for handler */
50
51/*===========================================================================
52 * FUNCTION   : mm_camera_util_generate_handler
53 *
54 * DESCRIPTION: utility function to generate handler for camera/channel/stream
55 *
56 * PARAMETERS :
57 *   @index: index of the object to have handler
58 *
59 * RETURN     : uint32_t type of handle that uniquely identify the object
60 *==========================================================================*/
61uint32_t mm_camera_util_generate_handler(uint8_t index)
62{
63    uint32_t handler = 0;
64    pthread_mutex_lock(&g_handler_lock);
65    g_handler_history_count++;
66    if (0 == g_handler_history_count) {
67        g_handler_history_count++;
68    }
69    handler = g_handler_history_count;
70    handler = (handler<<8) | index;
71    pthread_mutex_unlock(&g_handler_lock);
72    return handler;
73}
74
75/*===========================================================================
76 * FUNCTION   : mm_camera_util_get_index_by_handler
77 *
78 * DESCRIPTION: utility function to get index from handle
79 *
80 * PARAMETERS :
81 *   @handler: object handle
82 *
83 * RETURN     : uint8_t type of index derived from handle
84 *==========================================================================*/
85uint8_t mm_camera_util_get_index_by_handler(uint32_t handler)
86{
87    return (handler&0x000000ff);
88}
89
90/*===========================================================================
91 * FUNCTION   : mm_camera_util_get_dev_name
92 *
93 * DESCRIPTION: utility function to get device name from camera handle
94 *
95 * PARAMETERS :
96 *   @cam_handle: camera handle
97 *
98 * RETURN     : char ptr to the device name stored in global variable
99 * NOTE       : caller should not free the char ptr
100 *==========================================================================*/
101const char *mm_camera_util_get_dev_name(uint32_t cam_handle)
102{
103    char *dev_name = NULL;
104    uint8_t cam_idx = mm_camera_util_get_index_by_handler(cam_handle);
105    if(cam_idx < MM_CAMERA_MAX_NUM_SENSORS) {
106        dev_name = g_cam_ctrl.video_dev_name[cam_idx];
107    }
108    return dev_name;
109}
110
111/*===========================================================================
112 * FUNCTION   : mm_camera_util_get_camera_by_handler
113 *
114 * DESCRIPTION: utility function to get camera object from camera handle
115 *
116 * PARAMETERS :
117 *   @cam_handle: camera handle
118 *
119 * RETURN     : ptr to the camera object stored in global variable
120 * NOTE       : caller should not free the camera object ptr
121 *==========================================================================*/
122mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handle)
123{
124    mm_camera_obj_t *cam_obj = NULL;
125    uint8_t cam_idx = mm_camera_util_get_index_by_handler(cam_handle);
126
127    if (cam_idx < MM_CAMERA_MAX_NUM_SENSORS &&
128        (NULL != g_cam_ctrl.cam_obj[cam_idx]) &&
129        (cam_handle == g_cam_ctrl.cam_obj[cam_idx]->my_hdl)) {
130        cam_obj = g_cam_ctrl.cam_obj[cam_idx];
131    }
132    return cam_obj;
133}
134
135/*===========================================================================
136 * FUNCTION   : mm_camera_intf_query_capability
137 *
138 * DESCRIPTION: query camera capability
139 *
140 * PARAMETERS :
141 *   @camera_handle: camera handle
142 *
143 * RETURN     : int32_t type of status
144 *              0  -- success
145 *              -1 -- failure
146 *==========================================================================*/
147static int32_t mm_camera_intf_query_capability(uint32_t camera_handle)
148{
149    int32_t rc = -1;
150    mm_camera_obj_t * my_obj = NULL;
151
152    CDBG("%s E: camera_handler = %d ", __func__, camera_handle);
153
154    pthread_mutex_lock(&g_intf_lock);
155    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
156
157    if(my_obj) {
158        pthread_mutex_lock(&my_obj->cam_lock);
159        pthread_mutex_unlock(&g_intf_lock);
160        rc = mm_camera_query_capability(my_obj);
161    } else {
162        pthread_mutex_unlock(&g_intf_lock);
163    }
164    CDBG("%s :X rc = %d", __func__, rc);
165    return rc;
166}
167
168/*===========================================================================
169 * FUNCTION   : mm_camera_intf_set_parms
170 *
171 * DESCRIPTION: set parameters per camera
172 *
173 * PARAMETERS :
174 *   @camera_handle: camera handle
175 *   @parms        : ptr to a param struct to be set to server
176 *
177 * RETURN     : int32_t type of status
178 *              0  -- success
179 *              -1 -- failure
180 * NOTE       : Assume the parms struct buf is already mapped to server via
181 *              domain socket. Corresponding fields of parameters to be set
182 *              are already filled in by upper layer caller.
183 *==========================================================================*/
184static int32_t mm_camera_intf_set_parms(uint32_t camera_handle,
185                                        parm_buffer_t *parms)
186{
187    int32_t rc = -1;
188    mm_camera_obj_t * my_obj = NULL;
189
190    pthread_mutex_lock(&g_intf_lock);
191    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
192
193    if(my_obj) {
194        pthread_mutex_lock(&my_obj->cam_lock);
195        pthread_mutex_unlock(&g_intf_lock);
196        rc = mm_camera_set_parms(my_obj, parms);
197    } else {
198        pthread_mutex_unlock(&g_intf_lock);
199    }
200    return rc;
201}
202
203/*===========================================================================
204 * FUNCTION   : mm_camera_intf_get_parms
205 *
206 * DESCRIPTION: get parameters per camera
207 *
208 * PARAMETERS :
209 *   @camera_handle: camera handle
210 *   @parms        : ptr to a param struct to be get from server
211 *
212 * RETURN     : int32_t type of status
213 *              0  -- success
214 *              -1 -- failure
215 * NOTE       : Assume the parms struct buf is already mapped to server via
216 *              domain socket. Parameters to be get from server are already
217 *              filled in by upper layer caller. After this call, corresponding
218 *              fields of requested parameters will be filled in by server with
219 *              detailed information.
220 *==========================================================================*/
221static int32_t mm_camera_intf_get_parms(uint32_t camera_handle,
222                                        parm_buffer_t *parms)
223{
224    int32_t rc = -1;
225    mm_camera_obj_t * my_obj = NULL;
226
227    pthread_mutex_lock(&g_intf_lock);
228    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
229
230    if(my_obj) {
231        pthread_mutex_lock(&my_obj->cam_lock);
232        pthread_mutex_unlock(&g_intf_lock);
233        rc = mm_camera_get_parms(my_obj, parms);
234    } else {
235        pthread_mutex_unlock(&g_intf_lock);
236    }
237    return rc;
238}
239
240/*===========================================================================
241 * FUNCTION   : mm_camera_intf_do_auto_focus
242 *
243 * DESCRIPTION: performing auto focus
244 *
245 * PARAMETERS :
246 *   @camera_handle: camera handle
247 *
248 * RETURN     : int32_t type of status
249 *              0  -- success
250 *              -1 -- failure
251 * NOTE       : if this call success, we will always assume there will
252 *              be an auto_focus event following up.
253 *==========================================================================*/
254static int32_t mm_camera_intf_do_auto_focus(uint32_t camera_handle)
255{
256    int32_t rc = -1;
257    mm_camera_obj_t * my_obj = NULL;
258
259    pthread_mutex_lock(&g_intf_lock);
260    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
261
262    if(my_obj) {
263        pthread_mutex_lock(&my_obj->cam_lock);
264        pthread_mutex_unlock(&g_intf_lock);
265        rc = mm_camera_do_auto_focus(my_obj);
266    } else {
267        pthread_mutex_unlock(&g_intf_lock);
268    }
269    return rc;
270}
271
272/*===========================================================================
273 * FUNCTION   : mm_camera_intf_cancel_auto_focus
274 *
275 * DESCRIPTION: cancel auto focus
276 *
277 * PARAMETERS :
278 *   @camera_handle: camera handle
279 *
280 * RETURN     : int32_t type of status
281 *              0  -- success
282 *              -1 -- failure
283 *==========================================================================*/
284static int32_t mm_camera_intf_cancel_auto_focus(uint32_t camera_handle)
285{
286    int32_t rc = -1;
287    mm_camera_obj_t * my_obj = NULL;
288
289    pthread_mutex_lock(&g_intf_lock);
290    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
291
292    if(my_obj) {
293        pthread_mutex_lock(&my_obj->cam_lock);
294        pthread_mutex_unlock(&g_intf_lock);
295        rc = mm_camera_cancel_auto_focus(my_obj);
296    } else {
297        pthread_mutex_unlock(&g_intf_lock);
298    }
299    return rc;
300}
301
302/*===========================================================================
303 * FUNCTION   : mm_camera_intf_prepare_snapshot
304 *
305 * DESCRIPTION: prepare hardware for snapshot
306 *
307 * PARAMETERS :
308 *   @camera_handle: camera handle
309 *   @do_af_flag   : flag indicating if AF is needed
310 *
311 * RETURN     : int32_t type of status
312 *              0  -- success
313 *              -1 -- failure
314 *==========================================================================*/
315static int32_t mm_camera_intf_prepare_snapshot(uint32_t camera_handle,
316                                               int32_t do_af_flag)
317{
318    int32_t rc = -1;
319    mm_camera_obj_t * my_obj = NULL;
320
321    pthread_mutex_lock(&g_intf_lock);
322    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
323
324    if(my_obj) {
325        pthread_mutex_lock(&my_obj->cam_lock);
326        pthread_mutex_unlock(&g_intf_lock);
327        rc = mm_camera_prepare_snapshot(my_obj, do_af_flag);
328    } else {
329        pthread_mutex_unlock(&g_intf_lock);
330    }
331    return rc;
332}
333
334/*===========================================================================
335 * FUNCTION   : mm_camera_intf_start_zsl_snapshot
336 *
337 * DESCRIPTION: start zsl snapshot
338 *
339 * PARAMETERS :
340 *   @camera_handle: camera handle
341 *
342 * RETURN     : int32_t type of status
343 *              0  -- success
344 *              -1 -- failure
345 *==========================================================================*/
346static int32_t mm_camera_intf_start_zsl_snapshot(uint32_t camera_handle)
347{
348    int32_t rc = -1;
349    mm_camera_obj_t * my_obj = NULL;
350
351    pthread_mutex_lock(&g_intf_lock);
352    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
353
354    if(my_obj) {
355        pthread_mutex_lock(&my_obj->cam_lock);
356        pthread_mutex_unlock(&g_intf_lock);
357        rc = mm_camera_start_zsl_snapshot(my_obj);
358    } else {
359        pthread_mutex_unlock(&g_intf_lock);
360    }
361    return rc;
362}
363
364/*===========================================================================
365 * FUNCTION   : mm_camera_intf_stop_zsl_snapshot
366 *
367 * DESCRIPTION: stop zsl snapshot
368 *
369 * PARAMETERS :
370 *   @camera_handle: camera handle
371 *
372 * RETURN     : int32_t type of status
373 *              0  -- success
374 *              -1 -- failure
375 *==========================================================================*/
376static int32_t mm_camera_intf_stop_zsl_snapshot(uint32_t camera_handle)
377{
378    int32_t rc = -1;
379    mm_camera_obj_t * my_obj = NULL;
380
381    pthread_mutex_lock(&g_intf_lock);
382    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
383
384    if(my_obj) {
385        pthread_mutex_lock(&my_obj->cam_lock);
386        pthread_mutex_unlock(&g_intf_lock);
387        rc = mm_camera_stop_zsl_snapshot(my_obj);
388    } else {
389        pthread_mutex_unlock(&g_intf_lock);
390    }
391    return rc;
392}
393
394/*===========================================================================
395 * FUNCTION   : mm_camera_intf_close
396 *
397 * DESCRIPTION: close a camera by its handle
398 *
399 * PARAMETERS :
400 *   @camera_handle: camera handle
401 *
402 * RETURN     : int32_t type of status
403 *              0  -- success
404 *              -1 -- failure
405 *==========================================================================*/
406static int32_t mm_camera_intf_close(uint32_t camera_handle)
407{
408    int32_t rc = -1;
409    uint8_t cam_idx = camera_handle & 0x00ff;
410    mm_camera_obj_t * my_obj = NULL;
411
412    CDBG("%s E: camera_handler = %d ", __func__, camera_handle);
413
414    pthread_mutex_lock(&g_intf_lock);
415    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
416
417    if (my_obj){
418        my_obj->ref_count--;
419
420        if(my_obj->ref_count > 0) {
421            /* still have reference to obj, return here */
422            CDBG("%s: ref_count=%d\n", __func__, my_obj->ref_count);
423            pthread_mutex_unlock(&g_intf_lock);
424            rc = 0;
425        } else {
426            /* need close camera here as no other reference
427             * first empty g_cam_ctrl's referent to cam_obj */
428            g_cam_ctrl.cam_obj[cam_idx] = NULL;
429
430            pthread_mutex_lock(&my_obj->cam_lock);
431            pthread_mutex_unlock(&g_intf_lock);
432
433            rc = mm_camera_close(my_obj);
434
435            pthread_mutex_destroy(&my_obj->cam_lock);
436            free(my_obj);
437        }
438    } else {
439        pthread_mutex_unlock(&g_intf_lock);
440    }
441
442    return rc;
443}
444
445/*===========================================================================
446 * FUNCTION   : mm_camera_intf_add_channel
447 *
448 * DESCRIPTION: add a channel
449 *
450 * PARAMETERS :
451 *   @camera_handle: camera handle
452 *   @attr         : bundle attribute of the channel if needed
453 *   @channel_cb   : callback function for bundle data notify
454 *   @userdata     : user data ptr
455 *
456 * RETURN     : uint32_t type of channel handle
457 *              0  -- invalid channel handle, meaning the op failed
458 *              >0 -- successfully added a channel with a valid handle
459 * NOTE       : if no bundle data notify is needed, meaning each stream in the
460 *              channel will have its own stream data notify callback, then
461 *              attr, channel_cb, and userdata can be NULL. In this case,
462 *              no matching logic will be performed in channel for the bundling.
463 *==========================================================================*/
464static uint32_t mm_camera_intf_add_channel(uint32_t camera_handle,
465                                           mm_camera_channel_attr_t *attr,
466                                           mm_camera_buf_notify_t channel_cb,
467                                           void *userdata)
468{
469    uint32_t ch_id = 0;
470    mm_camera_obj_t * my_obj = NULL;
471
472    CDBG("%s :E camera_handler = %d", __func__, camera_handle);
473    pthread_mutex_lock(&g_intf_lock);
474    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
475
476    if(my_obj) {
477        pthread_mutex_lock(&my_obj->cam_lock);
478        pthread_mutex_unlock(&g_intf_lock);
479        ch_id = mm_camera_add_channel(my_obj, attr, channel_cb, userdata);
480    } else {
481        pthread_mutex_unlock(&g_intf_lock);
482    }
483    CDBG("%s :X ch_id = %d", __func__, ch_id);
484    return ch_id;
485}
486
487/*===========================================================================
488 * FUNCTION   : mm_camera_intf_del_channel
489 *
490 * DESCRIPTION: delete a channel by its handle
491 *
492 * PARAMETERS :
493 *   @camera_handle: camera handle
494 *   @ch_id        : channel handle
495 *
496 * RETURN     : int32_t type of status
497 *              0  -- success
498 *              -1 -- failure
499 * NOTE       : all streams in the channel should be stopped already before
500 *              this channel can be deleted.
501 *==========================================================================*/
502static int32_t mm_camera_intf_del_channel(uint32_t camera_handle,
503                                          uint32_t ch_id)
504{
505    int32_t rc = -1;
506    mm_camera_obj_t * my_obj = NULL;
507
508    CDBG("%s :E ch_id = %d", __func__, ch_id);
509    pthread_mutex_lock(&g_intf_lock);
510    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
511
512    if(my_obj) {
513        pthread_mutex_lock(&my_obj->cam_lock);
514        pthread_mutex_unlock(&g_intf_lock);
515        rc = mm_camera_del_channel(my_obj, ch_id);
516    } else {
517        pthread_mutex_unlock(&g_intf_lock);
518    }
519    CDBG("%s :X", __func__);
520    return rc;
521}
522
523/*===========================================================================
524 * FUNCTION   : mm_camera_intf_get_bundle_info
525 *
526 * DESCRIPTION: query bundle info of the channel
527 *
528 * PARAMETERS :
529 *   @camera_handle: camera handle
530 *   @ch_id        : channel handle
531 *   @bundle_info  : bundle info to be filled in
532 *
533 * RETURN     : int32_t type of status
534 *              0  -- success
535 *              -1 -- failure
536 * NOTE       : all streams in the channel should be stopped already before
537 *              this channel can be deleted.
538 *==========================================================================*/
539static int32_t mm_camera_intf_get_bundle_info(uint32_t camera_handle,
540                                              uint32_t ch_id,
541                                              cam_bundle_config_t *bundle_info)
542{
543    int32_t rc = -1;
544    mm_camera_obj_t * my_obj = NULL;
545
546    CDBG("%s :E ch_id = %d", __func__, ch_id);
547    pthread_mutex_lock(&g_intf_lock);
548    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
549
550    if(my_obj) {
551        pthread_mutex_lock(&my_obj->cam_lock);
552        pthread_mutex_unlock(&g_intf_lock);
553        rc = mm_camera_get_bundle_info(my_obj, ch_id, bundle_info);
554    } else {
555        pthread_mutex_unlock(&g_intf_lock);
556    }
557    CDBG("%s :X", __func__);
558    return rc;
559}
560
561/*===========================================================================
562 * FUNCTION   : mm_camera_intf_register_event_notify
563 *
564 * DESCRIPTION: register for event notify
565 *
566 * PARAMETERS :
567 *   @camera_handle: camera handle
568 *   @evt_cb       : callback for event notify
569 *   @user_data    : user data ptr
570 *
571 * RETURN     : int32_t type of status
572 *              0  -- success
573 *              -1 -- failure
574 *==========================================================================*/
575static int32_t mm_camera_intf_register_event_notify(uint32_t camera_handle,
576                                                    mm_camera_event_notify_t evt_cb,
577                                                    void * user_data)
578{
579    int32_t rc = -1;
580    mm_camera_obj_t * my_obj = NULL;
581
582    CDBG("%s :E ", __func__);
583    pthread_mutex_lock(&g_intf_lock);
584    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
585
586    if(my_obj) {
587        pthread_mutex_lock(&my_obj->cam_lock);
588        pthread_mutex_unlock(&g_intf_lock);
589        rc = mm_camera_register_event_notify(my_obj, evt_cb, user_data);
590    } else {
591        pthread_mutex_unlock(&g_intf_lock);
592    }
593    CDBG("%s :E rc = %d", __func__, rc);
594    return rc;
595}
596
597/*===========================================================================
598 * FUNCTION   : mm_camera_intf_qbuf
599 *
600 * DESCRIPTION: enqueue buffer back to kernel
601 *
602 * PARAMETERS :
603 *   @camera_handle: camera handle
604 *   @ch_id        : channel handle
605 *   @buf          : buf ptr to be enqueued
606 *
607 * RETURN     : int32_t type of status
608 *              0  -- success
609 *              -1 -- failure
610 *==========================================================================*/
611static int32_t mm_camera_intf_qbuf(uint32_t camera_handle,
612                                    uint32_t ch_id,
613                                    mm_camera_buf_def_t *buf)
614{
615    int32_t rc = -1;
616    mm_camera_obj_t * my_obj = NULL;
617
618    pthread_mutex_lock(&g_intf_lock);
619    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
620
621    if(my_obj) {
622        pthread_mutex_lock(&my_obj->cam_lock);
623        pthread_mutex_unlock(&g_intf_lock);
624        rc = mm_camera_qbuf(my_obj, ch_id, buf);
625    } else {
626        pthread_mutex_unlock(&g_intf_lock);
627    }
628    CDBG("%s :X evt_type = %d",__func__,rc);
629    return rc;
630}
631
632/*===========================================================================
633 * FUNCTION   : mm_camera_intf_add_stream
634 *
635 * DESCRIPTION: add a stream into a channel
636 *
637 * PARAMETERS :
638 *   @camera_handle: camera handle
639 *   @ch_id        : channel handle
640 *
641 * RETURN     : uint32_t type of stream handle
642 *              0  -- invalid stream handle, meaning the op failed
643 *              >0 -- successfully added a stream with a valid handle
644 *==========================================================================*/
645static uint32_t mm_camera_intf_add_stream(uint32_t camera_handle,
646                                          uint32_t ch_id)
647{
648    uint32_t stream_id = 0;
649    mm_camera_obj_t * my_obj = NULL;
650
651    CDBG("%s : E handle = %d ch_id = %d",
652         __func__, camera_handle, ch_id);
653
654    pthread_mutex_lock(&g_intf_lock);
655    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
656
657    if(my_obj) {
658        pthread_mutex_lock(&my_obj->cam_lock);
659        pthread_mutex_unlock(&g_intf_lock);
660        stream_id = mm_camera_add_stream(my_obj, ch_id);
661    } else {
662        pthread_mutex_unlock(&g_intf_lock);
663    }
664    CDBG("%s :X stream_id = %d", __func__, stream_id);
665    return stream_id;
666}
667
668/*===========================================================================
669 * FUNCTION   : mm_camera_intf_del_stream
670 *
671 * DESCRIPTION: delete a stream by its handle
672 *
673 * PARAMETERS :
674 *   @camera_handle: camera handle
675 *   @ch_id        : channel handle
676 *   @stream_id    : stream handle
677 *
678 * RETURN     : int32_t type of status
679 *              0  -- success
680 *              -1 -- failure
681 * NOTE       : stream should be stopped already before it can be deleted.
682 *==========================================================================*/
683static int32_t mm_camera_intf_del_stream(uint32_t camera_handle,
684                                         uint32_t ch_id,
685                                         uint32_t stream_id)
686{
687    int32_t rc = -1;
688    mm_camera_obj_t * my_obj = NULL;
689
690    CDBG("%s : E handle = %d ch_id = %d stream_id = %d",
691         __func__, camera_handle, ch_id, stream_id);
692
693    pthread_mutex_lock(&g_intf_lock);
694    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
695
696    if(my_obj) {
697        pthread_mutex_lock(&my_obj->cam_lock);
698        pthread_mutex_unlock(&g_intf_lock);
699        rc = mm_camera_del_stream(my_obj, ch_id, stream_id);
700    } else {
701        pthread_mutex_unlock(&g_intf_lock);
702    }
703    CDBG("%s :X rc = %d", __func__, rc);
704    return rc;
705}
706
707/*===========================================================================
708 * FUNCTION   : mm_camera_intf_config_stream
709 *
710 * DESCRIPTION: configure a stream
711 *
712 * PARAMETERS :
713 *   @camera_handle: camera handle
714 *   @ch_id        : channel handle
715 *   @stream_id    : stream handle
716 *   @config       : stream configuration
717 *
718 * RETURN     : int32_t type of status
719 *              0  -- success
720 *              -1 -- failure
721 *==========================================================================*/
722static int32_t mm_camera_intf_config_stream(uint32_t camera_handle,
723                                            uint32_t ch_id,
724                                            uint32_t stream_id,
725                                            mm_camera_stream_config_t *config)
726{
727    int32_t rc = -1;
728    mm_camera_obj_t * my_obj = NULL;
729
730    CDBG("%s :E handle = %d, ch_id = %d,stream_id = %d",
731         __func__, camera_handle, ch_id, stream_id);
732
733    pthread_mutex_lock(&g_intf_lock);
734    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
735
736    CDBG("%s :mm_camera_intf_config_stream stream_id = %d",__func__,stream_id);
737
738    if(my_obj) {
739        pthread_mutex_lock(&my_obj->cam_lock);
740        pthread_mutex_unlock(&g_intf_lock);
741        rc = mm_camera_config_stream(my_obj, ch_id, stream_id, config);
742    } else {
743        pthread_mutex_unlock(&g_intf_lock);
744    }
745    CDBG("%s :X rc = %d", __func__, rc);
746    return rc;
747}
748
749/*===========================================================================
750 * FUNCTION   : mm_camera_intf_start_channel
751 *
752 * DESCRIPTION: start a channel, which will start all streams in the channel
753 *
754 * PARAMETERS :
755 *   @camera_handle: camera handle
756 *   @ch_id        : channel handle
757 *
758 * RETURN     : int32_t type of status
759 *              0  -- success
760 *              -1 -- failure
761 *==========================================================================*/
762static int32_t mm_camera_intf_start_channel(uint32_t camera_handle,
763                                            uint32_t ch_id)
764{
765    int32_t rc = -1;
766    mm_camera_obj_t * my_obj = NULL;
767
768    pthread_mutex_lock(&g_intf_lock);
769    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
770
771    if(my_obj) {
772        pthread_mutex_lock(&my_obj->cam_lock);
773        pthread_mutex_unlock(&g_intf_lock);
774        rc = mm_camera_start_channel(my_obj, ch_id);
775    } else {
776        pthread_mutex_unlock(&g_intf_lock);
777    }
778    CDBG("%s :X rc = %d", __func__, rc);
779    return rc;
780}
781
782/*===========================================================================
783 * FUNCTION   : mm_camera_intf_stop_channel
784 *
785 * DESCRIPTION: stop a channel, which will stop all streams in the channel
786 *
787 * PARAMETERS :
788 *   @camera_handle: camera handle
789 *   @ch_id        : channel handle
790 *
791 * RETURN     : int32_t type of status
792 *              0  -- success
793 *              -1 -- failure
794 *==========================================================================*/
795static int32_t mm_camera_intf_stop_channel(uint32_t camera_handle,
796                                           uint32_t ch_id)
797{
798    int32_t rc = -1;
799    mm_camera_obj_t * my_obj = NULL;
800
801    pthread_mutex_lock(&g_intf_lock);
802    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
803
804    if(my_obj) {
805        pthread_mutex_lock(&my_obj->cam_lock);
806        pthread_mutex_unlock(&g_intf_lock);
807        rc = mm_camera_stop_channel(my_obj, ch_id);
808    } else {
809        pthread_mutex_unlock(&g_intf_lock);
810    }
811    CDBG("%s :X rc = %d", __func__, rc);
812    return rc;
813}
814
815/*===========================================================================
816 * FUNCTION   : mm_camera_intf_request_super_buf
817 *
818 * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched
819 *              frames from superbuf queue
820 *
821 * PARAMETERS :
822 *   @camera_handle: camera handle
823 *   @ch_id        : channel handle
824 *   @num_buf_requested : number of matched frames needed
825 *
826 * RETURN     : int32_t type of status
827 *              0  -- success
828 *              -1 -- failure
829 *==========================================================================*/
830static int32_t mm_camera_intf_request_super_buf(uint32_t camera_handle,
831                                                uint32_t ch_id,
832                                                uint32_t num_buf_requested)
833{
834    int32_t rc = -1;
835    CDBG("%s :E camera_handler = %d,ch_id = %d",
836         __func__, camera_handle, ch_id);
837    mm_camera_obj_t * my_obj = NULL;
838
839    pthread_mutex_lock(&g_intf_lock);
840    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
841
842    if(my_obj) {
843        pthread_mutex_lock(&my_obj->cam_lock);
844        pthread_mutex_unlock(&g_intf_lock);
845        rc = mm_camera_request_super_buf(my_obj, ch_id, num_buf_requested);
846    } else {
847        pthread_mutex_unlock(&g_intf_lock);
848    }
849    CDBG("%s :X rc = %d", __func__, rc);
850    return rc;
851}
852
853/*===========================================================================
854 * FUNCTION   : mm_camera_intf_cancel_super_buf_request
855 *
856 * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount
857 *              of matched frames from superbuf queue
858 *
859 * PARAMETERS :
860 *   @camera_handle: camera handle
861 *   @ch_id        : channel handle
862 *
863 * RETURN     : int32_t type of status
864 *              0  -- success
865 *              -1 -- failure
866 *==========================================================================*/
867static int32_t mm_camera_intf_cancel_super_buf_request(uint32_t camera_handle,
868                                                       uint32_t ch_id)
869{
870    int32_t rc = -1;
871    mm_camera_obj_t * my_obj = NULL;
872
873    CDBG("%s :E camera_handler = %d,ch_id = %d",
874         __func__, camera_handle, ch_id);
875    pthread_mutex_lock(&g_intf_lock);
876    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
877
878    if(my_obj) {
879        pthread_mutex_lock(&my_obj->cam_lock);
880        pthread_mutex_unlock(&g_intf_lock);
881        rc = mm_camera_cancel_super_buf_request(my_obj, ch_id);
882    } else {
883        pthread_mutex_unlock(&g_intf_lock);
884    }
885    CDBG("%s :X rc = %d", __func__, rc);
886    return rc;
887}
888
889/*===========================================================================
890 * FUNCTION   : mm_camera_intf_flush_super_buf_queue
891 *
892 * DESCRIPTION: flush out all frames in the superbuf queue
893 *
894 * PARAMETERS :
895 *   @camera_handle: camera handle
896 *   @ch_id        : channel handle
897 *   @frame_idx    : frame index
898 *
899 * RETURN     : int32_t type of status
900 *              0  -- success
901 *              -1 -- failure
902 *==========================================================================*/
903static int32_t mm_camera_intf_flush_super_buf_queue(uint32_t camera_handle,
904                                                    uint32_t ch_id, uint32_t frame_idx)
905{
906    int32_t rc = -1;
907    mm_camera_obj_t * my_obj = NULL;
908
909    CDBG("%s :E camera_handler = %d,ch_id = %d",
910         __func__, camera_handle, ch_id);
911    pthread_mutex_lock(&g_intf_lock);
912    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
913
914    if(my_obj) {
915        pthread_mutex_lock(&my_obj->cam_lock);
916        pthread_mutex_unlock(&g_intf_lock);
917        rc = mm_camera_flush_super_buf_queue(my_obj, ch_id, frame_idx);
918    } else {
919        pthread_mutex_unlock(&g_intf_lock);
920    }
921    CDBG("%s :X rc = %d", __func__, rc);
922    return rc;
923}
924
925/*===========================================================================
926 * FUNCTION   : mm_camera_intf_map_buf
927 *
928 * DESCRIPTION: mapping camera buffer via domain socket to server
929 *
930 * PARAMETERS :
931 *   @camera_handle: camera handle
932 *   @buf_type     : type of buffer to be mapped. could be following values:
933 *                   CAM_MAPPING_BUF_TYPE_CAPABILITY
934 *                   CAM_MAPPING_BUF_TYPE_SETPARM_BUF
935 *                   CAM_MAPPING_BUF_TYPE_GETPARM_BUF
936 *   @fd           : file descriptor of the buffer
937 *   @size         : size of the buffer
938 *
939 * RETURN     : int32_t type of status
940 *              0  -- success
941 *              -1 -- failure
942 *==========================================================================*/
943static int32_t mm_camera_intf_map_buf(uint32_t camera_handle,
944                                      uint8_t buf_type,
945                                      int fd,
946                                      uint32_t size)
947{
948    int32_t rc = -1;
949    mm_camera_obj_t * my_obj = NULL;
950
951    pthread_mutex_lock(&g_intf_lock);
952    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
953
954    if(my_obj) {
955        pthread_mutex_lock(&my_obj->cam_lock);
956        pthread_mutex_unlock(&g_intf_lock);
957        rc = mm_camera_map_buf(my_obj, buf_type, fd, size);
958    } else {
959        pthread_mutex_unlock(&g_intf_lock);
960    }
961    return rc;
962}
963
964/*===========================================================================
965 * FUNCTION   : mm_camera_intf_unmap_buf
966 *
967 * DESCRIPTION: unmapping camera buffer via domain socket to server
968 *
969 * PARAMETERS :
970 *   @camera_handle: camera handle
971 *   @buf_type     : type of buffer to be unmapped. could be following values:
972 *                   CAM_MAPPING_BUF_TYPE_CAPABILITY
973 *                   CAM_MAPPING_BUF_TYPE_SETPARM_BUF
974 *                   CAM_MAPPING_BUF_TYPE_GETPARM_BUF
975 *
976 * RETURN     : int32_t type of status
977 *              0  -- success
978 *              -1 -- failure
979 *==========================================================================*/
980static int32_t mm_camera_intf_unmap_buf(uint32_t camera_handle,
981                                        uint8_t buf_type)
982{
983    int32_t rc = -1;
984    mm_camera_obj_t * my_obj = NULL;
985
986    pthread_mutex_lock(&g_intf_lock);
987    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
988
989    if(my_obj) {
990        pthread_mutex_lock(&my_obj->cam_lock);
991        pthread_mutex_unlock(&g_intf_lock);
992        rc = mm_camera_unmap_buf(my_obj, buf_type);
993    } else {
994        pthread_mutex_unlock(&g_intf_lock);
995    }
996    return rc;
997}
998
999/*===========================================================================
1000 * FUNCTION   : mm_camera_intf_set_stream_parms
1001 *
1002 * DESCRIPTION: set parameters per stream
1003 *
1004 * PARAMETERS :
1005 *   @camera_handle: camera handle
1006 *   @ch_id        : channel handle
1007 *   @s_id         : stream handle
1008 *   @parms        : ptr to a param struct to be set to server
1009 *
1010 * RETURN     : int32_t type of status
1011 *              0  -- success
1012 *              -1 -- failure
1013 * NOTE       : Assume the parms struct buf is already mapped to server via
1014 *              domain socket. Corresponding fields of parameters to be set
1015 *              are already filled in by upper layer caller.
1016 *==========================================================================*/
1017static int32_t mm_camera_intf_set_stream_parms(uint32_t camera_handle,
1018                                               uint32_t ch_id,
1019                                               uint32_t s_id,
1020                                               cam_stream_parm_buffer_t *parms)
1021{
1022    int32_t rc = -1;
1023    mm_camera_obj_t * my_obj = NULL;
1024
1025    pthread_mutex_lock(&g_intf_lock);
1026    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
1027
1028    CDBG("%s :E camera_handle = %d,ch_id = %d,s_id = %d",
1029         __func__, camera_handle, ch_id, s_id);
1030
1031    if(my_obj) {
1032        pthread_mutex_lock(&my_obj->cam_lock);
1033        pthread_mutex_unlock(&g_intf_lock);
1034        rc = mm_camera_set_stream_parms(my_obj, ch_id, s_id, parms);
1035    }else{
1036        pthread_mutex_unlock(&g_intf_lock);
1037    }
1038    CDBG("%s :X rc = %d", __func__, rc);
1039    return rc;
1040}
1041
1042/*===========================================================================
1043 * FUNCTION   : mm_camera_intf_get_stream_parms
1044 *
1045 * DESCRIPTION: get parameters per stream
1046 *
1047 * PARAMETERS :
1048 *   @camera_handle: camera handle
1049 *   @ch_id        : channel handle
1050 *   @s_id         : stream handle
1051 *   @parms        : ptr to a param struct to be get from server
1052 *
1053 * RETURN     : int32_t type of status
1054 *              0  -- success
1055 *              -1 -- failure
1056 * NOTE       : Assume the parms struct buf is already mapped to server via
1057 *              domain socket. Parameters to be get from server are already
1058 *              filled in by upper layer caller. After this call, corresponding
1059 *              fields of requested parameters will be filled in by server with
1060 *              detailed information.
1061 *==========================================================================*/
1062static int32_t mm_camera_intf_get_stream_parms(uint32_t camera_handle,
1063                                               uint32_t ch_id,
1064                                               uint32_t s_id,
1065                                               cam_stream_parm_buffer_t *parms)
1066{
1067    int32_t rc = -1;
1068    mm_camera_obj_t * my_obj = NULL;
1069
1070    pthread_mutex_lock(&g_intf_lock);
1071    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
1072
1073    CDBG("%s :E camera_handle = %d,ch_id = %d,s_id = %d",
1074         __func__, camera_handle, ch_id, s_id);
1075
1076    if(my_obj) {
1077        pthread_mutex_lock(&my_obj->cam_lock);
1078        pthread_mutex_unlock(&g_intf_lock);
1079        rc = mm_camera_get_stream_parms(my_obj, ch_id, s_id, parms);
1080    }else{
1081        pthread_mutex_unlock(&g_intf_lock);
1082    }
1083
1084    CDBG("%s :X rc = %d", __func__, rc);
1085    return rc;
1086}
1087
1088/*===========================================================================
1089 * FUNCTION   : mm_camera_intf_map_stream_buf
1090 *
1091 * DESCRIPTION: mapping stream buffer via domain socket to server
1092 *
1093 * PARAMETERS :
1094 *   @camera_handle: camera handle
1095 *   @ch_id        : channel handle
1096 *   @s_id         : stream handle
1097 *   @buf_type     : type of buffer to be mapped. could be following values:
1098 *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1099 *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1100 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1101 *   @buf_idx      : index of buffer within the stream buffers, only valid if
1102 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1103 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1104 *   @plane_idx    : plane index. If all planes share the same fd,
1105 *                   plane_idx = -1; otherwise, plean_idx is the
1106 *                   index to plane (0..num_of_planes)
1107 *   @fd           : file descriptor of the buffer
1108 *   @size         : size of the buffer
1109 *
1110 * RETURN     : int32_t type of status
1111 *              0  -- success
1112 *              -1 -- failure
1113 *==========================================================================*/
1114static int32_t mm_camera_intf_map_stream_buf(uint32_t camera_handle,
1115                                             uint32_t ch_id,
1116                                             uint32_t stream_id,
1117                                             uint8_t buf_type,
1118                                             uint32_t buf_idx,
1119                                             int32_t plane_idx,
1120                                             int fd,
1121                                             uint32_t size)
1122{
1123    int32_t rc = -1;
1124    mm_camera_obj_t * my_obj = NULL;
1125
1126    pthread_mutex_lock(&g_intf_lock);
1127    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
1128
1129    CDBG("%s :E camera_handle = %d, ch_id = %d, s_id = %d, buf_idx = %d, plane_idx = %d",
1130         __func__, camera_handle, ch_id, stream_id, buf_idx, plane_idx);
1131
1132    if(my_obj) {
1133        pthread_mutex_lock(&my_obj->cam_lock);
1134        pthread_mutex_unlock(&g_intf_lock);
1135        rc = mm_camera_map_stream_buf(my_obj, ch_id, stream_id,
1136                                      buf_type, buf_idx, plane_idx,
1137                                      fd, size);
1138    }else{
1139        pthread_mutex_unlock(&g_intf_lock);
1140    }
1141
1142    CDBG("%s :X rc = %d", __func__, rc);
1143    return rc;
1144}
1145
1146/*===========================================================================
1147 * FUNCTION   : mm_camera_intf_unmap_stream_buf
1148 *
1149 * DESCRIPTION: unmapping stream buffer via domain socket to server
1150 *
1151 * PARAMETERS :
1152 *   @camera_handle: camera handle
1153 *   @ch_id        : channel handle
1154 *   @s_id         : stream handle
1155 *   @buf_type     : type of buffer to be unmapped. could be following values:
1156 *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1157 *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1158 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1159 *   @buf_idx      : index of buffer within the stream buffers, only valid if
1160 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1161 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1162 *   @plane_idx    : plane index. If all planes share the same fd,
1163 *                   plane_idx = -1; otherwise, plean_idx is the
1164 *                   index to plane (0..num_of_planes)
1165 *
1166 * RETURN     : int32_t type of status
1167 *              0  -- success
1168 *              -1 -- failure
1169 *==========================================================================*/
1170static int32_t mm_camera_intf_unmap_stream_buf(uint32_t camera_handle,
1171                                               uint32_t ch_id,
1172                                               uint32_t stream_id,
1173                                               uint8_t buf_type,
1174                                               uint32_t buf_idx,
1175                                               int32_t plane_idx)
1176{
1177    int32_t rc = -1;
1178    mm_camera_obj_t * my_obj = NULL;
1179
1180    pthread_mutex_lock(&g_intf_lock);
1181    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
1182
1183    CDBG("%s :E camera_handle = %d, ch_id = %d, s_id = %d, buf_idx = %d, plane_idx = %d",
1184         __func__, camera_handle, ch_id, stream_id, buf_idx, plane_idx);
1185
1186    if(my_obj) {
1187        pthread_mutex_lock(&my_obj->cam_lock);
1188        pthread_mutex_unlock(&g_intf_lock);
1189        rc = mm_camera_unmap_stream_buf(my_obj, ch_id, stream_id,
1190                                        buf_type, buf_idx, plane_idx);
1191    }else{
1192        pthread_mutex_unlock(&g_intf_lock);
1193    }
1194
1195    CDBG("%s :X rc = %d", __func__, rc);
1196    return rc;
1197}
1198
1199/*===========================================================================
1200 * FUNCTION   : get_num_of_cameras
1201 *
1202 * DESCRIPTION: get number of cameras
1203 *
1204 * PARAMETERS :
1205 *
1206 * RETURN     : number of cameras supported
1207 *==========================================================================*/
1208uint8_t get_num_of_cameras()
1209{
1210    int rc = 0;
1211    int dev_fd = 0;
1212    struct media_device_info mdev_info;
1213    int num_media_devices = 0;
1214    uint8_t num_cameras = 0;
1215
1216    CDBG("%s : E", __func__);
1217    /* lock the mutex */
1218    pthread_mutex_lock(&g_intf_lock);
1219    while (1) {
1220        char dev_name[32];
1221        int num_entities;
1222        snprintf(dev_name, sizeof(dev_name), "/dev/media%d", num_media_devices);
1223        dev_fd = open(dev_name, O_RDWR | O_NONBLOCK);
1224        if (dev_fd <= 0) {
1225            CDBG("Done discovering media devices\n");
1226            break;
1227        }
1228        num_media_devices++;
1229        memset(&mdev_info, 0, sizeof(mdev_info));
1230        rc = ioctl(dev_fd, MEDIA_IOC_DEVICE_INFO, &mdev_info);
1231        if (rc < 0) {
1232            CDBG_ERROR("Error: ioctl media_dev failed: %s\n", strerror(errno));
1233            close(dev_fd);
1234            dev_fd = 0;
1235            num_cameras = 0;
1236            break;
1237        }
1238
1239        if(strncmp(mdev_info.model, MSM_CAMERA_NAME, sizeof(mdev_info.model)) != 0) {
1240            close(dev_fd);
1241            dev_fd = 0;
1242            continue;
1243        }
1244
1245        num_entities = 1;
1246        while (1) {
1247            struct media_entity_desc entity;
1248            memset(&entity, 0, sizeof(entity));
1249            entity.id = num_entities++;
1250            rc = ioctl(dev_fd, MEDIA_IOC_ENUM_ENTITIES, &entity);
1251            if (rc < 0) {
1252                CDBG("Done enumerating media entities\n");
1253                rc = 0;
1254                break;
1255            }
1256            if(entity.type == MEDIA_ENT_T_DEVNODE_V4L && entity.group_id == QCAMERA_VNODE_GROUP_ID) {
1257                strncpy(g_cam_ctrl.video_dev_name[num_cameras],
1258                     entity.name, sizeof(entity.name));
1259                break;
1260            }
1261        }
1262
1263        CDBG("%s: dev_info[id=%d,name='%s']\n",
1264            __func__, num_cameras, g_cam_ctrl.video_dev_name[num_cameras]);
1265
1266        num_cameras++;
1267        close(dev_fd);
1268        dev_fd = 0;
1269    }
1270    g_cam_ctrl.num_cam = num_cameras;
1271
1272    /* unlock the mutex */
1273    pthread_mutex_unlock(&g_intf_lock);
1274    CDBG("%s: num_cameras=%d\n", __func__, g_cam_ctrl.num_cam);
1275    return g_cam_ctrl.num_cam;
1276}
1277
1278/* camera ops v-table */
1279static mm_camera_ops_t mm_camera_ops = {
1280    .query_capability = mm_camera_intf_query_capability,
1281    .register_event_notify = mm_camera_intf_register_event_notify,
1282    .close_camera = mm_camera_intf_close,
1283    .set_parms = mm_camera_intf_set_parms,
1284    .get_parms = mm_camera_intf_get_parms,
1285    .do_auto_focus = mm_camera_intf_do_auto_focus,
1286    .cancel_auto_focus = mm_camera_intf_cancel_auto_focus,
1287    .prepare_snapshot = mm_camera_intf_prepare_snapshot,
1288    .start_zsl_snapshot = mm_camera_intf_start_zsl_snapshot,
1289    .stop_zsl_snapshot = mm_camera_intf_stop_zsl_snapshot,
1290    .map_buf = mm_camera_intf_map_buf,
1291    .unmap_buf = mm_camera_intf_unmap_buf,
1292    .add_channel = mm_camera_intf_add_channel,
1293    .delete_channel = mm_camera_intf_del_channel,
1294    .get_bundle_info = mm_camera_intf_get_bundle_info,
1295    .add_stream = mm_camera_intf_add_stream,
1296    .delete_stream = mm_camera_intf_del_stream,
1297    .config_stream = mm_camera_intf_config_stream,
1298    .qbuf = mm_camera_intf_qbuf,
1299    .map_stream_buf = mm_camera_intf_map_stream_buf,
1300    .unmap_stream_buf = mm_camera_intf_unmap_stream_buf,
1301    .set_stream_parms = mm_camera_intf_set_stream_parms,
1302    .get_stream_parms = mm_camera_intf_get_stream_parms,
1303    .start_channel = mm_camera_intf_start_channel,
1304    .stop_channel = mm_camera_intf_stop_channel,
1305    .request_super_buf = mm_camera_intf_request_super_buf,
1306    .cancel_super_buf_request = mm_camera_intf_cancel_super_buf_request,
1307    .flush_super_buf_queue = mm_camera_intf_flush_super_buf_queue
1308};
1309
1310/*===========================================================================
1311 * FUNCTION   : camera_open
1312 *
1313 * DESCRIPTION: open a camera by camera index
1314 *
1315 * PARAMETERS :
1316 *   @camera_idx : camera index. should within range of 0 to num_of_cameras
1317 *
1318 * RETURN     : ptr to a virtual table containing camera handle and operation table.
1319 *              NULL if failed.
1320 *==========================================================================*/
1321mm_camera_vtbl_t * camera_open(uint8_t camera_idx)
1322{
1323    int32_t rc = 0;
1324    mm_camera_obj_t* cam_obj = NULL;
1325
1326    CDBG("%s: E camera_idx = %d\n", __func__, camera_idx);
1327    if (camera_idx >= g_cam_ctrl.num_cam) {
1328        CDBG_ERROR("%s: Invalid camera_idx (%d)", __func__, camera_idx);
1329        return NULL;
1330    }
1331
1332    pthread_mutex_lock(&g_intf_lock);
1333    /* opened already */
1334    if(NULL != g_cam_ctrl.cam_obj[camera_idx]) {
1335        /* Add reference */
1336        g_cam_ctrl.cam_obj[camera_idx]->ref_count++;
1337        pthread_mutex_unlock(&g_intf_lock);
1338        CDBG("%s:  opened alreadyn", __func__);
1339        return &cam_obj->vtbl;
1340    }
1341
1342    cam_obj = (mm_camera_obj_t *)malloc(sizeof(mm_camera_obj_t));
1343    if(NULL == cam_obj) {
1344        pthread_mutex_unlock(&g_intf_lock);
1345        CDBG("%s:  no mem", __func__);
1346        return NULL;
1347    }
1348
1349    /* initialize camera obj */
1350    memset(cam_obj, 0, sizeof(mm_camera_obj_t));
1351    cam_obj->ref_count++;
1352    cam_obj->my_hdl = mm_camera_util_generate_handler(camera_idx);
1353    cam_obj->vtbl.camera_handle = cam_obj->my_hdl; /* set handler */
1354    cam_obj->vtbl.ops = &mm_camera_ops;
1355    pthread_mutex_init(&cam_obj->cam_lock, NULL);
1356
1357    rc = mm_camera_open(cam_obj);
1358    if(rc != 0) {
1359        CDBG_ERROR("%s: mm_camera_open err = %d", __func__, rc);
1360        pthread_mutex_destroy(&cam_obj->cam_lock);
1361        g_cam_ctrl.cam_obj[camera_idx] = NULL;
1362        free(cam_obj);
1363        cam_obj = NULL;
1364        pthread_mutex_unlock(&g_intf_lock);
1365        return NULL;
1366    }else{
1367        CDBG("%s: Open succeded\n", __func__);
1368        g_cam_ctrl.cam_obj[camera_idx] = cam_obj;
1369        pthread_mutex_unlock(&g_intf_lock);
1370        return &cam_obj->vtbl;
1371    }
1372}
1373