mm_camera_interface.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#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_configure_notify_mode
927 *
928 * DESCRIPTION: Configures channel notification mode
929 *
930 * PARAMETERS :
931 *   @camera_handle: camera handle
932 *   @ch_id        : channel handle
933 *   @notify_mode  : notification mode
934 *
935 * RETURN     : int32_t type of status
936 *              0  -- success
937 *              -1 -- failure
938 *==========================================================================*/
939static int32_t mm_camera_intf_configure_notify_mode(uint32_t camera_handle,
940                                                    uint32_t ch_id,
941                                                    mm_camera_super_buf_notify_mode_t notify_mode)
942{
943    int32_t rc = -1;
944    mm_camera_obj_t * my_obj = NULL;
945
946    CDBG("%s :E camera_handler = %d,ch_id = %d",
947         __func__, camera_handle, ch_id);
948    pthread_mutex_lock(&g_intf_lock);
949    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
950
951    if(my_obj) {
952        pthread_mutex_lock(&my_obj->cam_lock);
953        pthread_mutex_unlock(&g_intf_lock);
954        rc = mm_camera_config_channel_notify(my_obj, ch_id, notify_mode);
955    } else {
956        pthread_mutex_unlock(&g_intf_lock);
957    }
958    CDBG("%s :X rc = %d", __func__, rc);
959    return rc;
960}
961
962/*===========================================================================
963 * FUNCTION   : mm_camera_intf_map_buf
964 *
965 * DESCRIPTION: mapping camera buffer via domain socket to server
966 *
967 * PARAMETERS :
968 *   @camera_handle: camera handle
969 *   @buf_type     : type of buffer to be mapped. could be following values:
970 *                   CAM_MAPPING_BUF_TYPE_CAPABILITY
971 *                   CAM_MAPPING_BUF_TYPE_SETPARM_BUF
972 *                   CAM_MAPPING_BUF_TYPE_GETPARM_BUF
973 *   @fd           : file descriptor of the buffer
974 *   @size         : size of the buffer
975 *
976 * RETURN     : int32_t type of status
977 *              0  -- success
978 *              -1 -- failure
979 *==========================================================================*/
980static int32_t mm_camera_intf_map_buf(uint32_t camera_handle,
981                                      uint8_t buf_type,
982                                      int fd,
983                                      uint32_t size)
984{
985    int32_t rc = -1;
986    mm_camera_obj_t * my_obj = NULL;
987
988    pthread_mutex_lock(&g_intf_lock);
989    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
990
991    if(my_obj) {
992        pthread_mutex_lock(&my_obj->cam_lock);
993        pthread_mutex_unlock(&g_intf_lock);
994        rc = mm_camera_map_buf(my_obj, buf_type, fd, size);
995    } else {
996        pthread_mutex_unlock(&g_intf_lock);
997    }
998    return rc;
999}
1000
1001/*===========================================================================
1002 * FUNCTION   : mm_camera_intf_unmap_buf
1003 *
1004 * DESCRIPTION: unmapping camera buffer via domain socket to server
1005 *
1006 * PARAMETERS :
1007 *   @camera_handle: camera handle
1008 *   @buf_type     : type of buffer to be unmapped. could be following values:
1009 *                   CAM_MAPPING_BUF_TYPE_CAPABILITY
1010 *                   CAM_MAPPING_BUF_TYPE_SETPARM_BUF
1011 *                   CAM_MAPPING_BUF_TYPE_GETPARM_BUF
1012 *
1013 * RETURN     : int32_t type of status
1014 *              0  -- success
1015 *              -1 -- failure
1016 *==========================================================================*/
1017static int32_t mm_camera_intf_unmap_buf(uint32_t camera_handle,
1018                                        uint8_t buf_type)
1019{
1020    int32_t rc = -1;
1021    mm_camera_obj_t * my_obj = NULL;
1022
1023    pthread_mutex_lock(&g_intf_lock);
1024    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
1025
1026    if(my_obj) {
1027        pthread_mutex_lock(&my_obj->cam_lock);
1028        pthread_mutex_unlock(&g_intf_lock);
1029        rc = mm_camera_unmap_buf(my_obj, buf_type);
1030    } else {
1031        pthread_mutex_unlock(&g_intf_lock);
1032    }
1033    return rc;
1034}
1035
1036/*===========================================================================
1037 * FUNCTION   : mm_camera_intf_set_stream_parms
1038 *
1039 * DESCRIPTION: set parameters per stream
1040 *
1041 * PARAMETERS :
1042 *   @camera_handle: camera handle
1043 *   @ch_id        : channel handle
1044 *   @s_id         : stream handle
1045 *   @parms        : ptr to a param struct to be set to server
1046 *
1047 * RETURN     : int32_t type of status
1048 *              0  -- success
1049 *              -1 -- failure
1050 * NOTE       : Assume the parms struct buf is already mapped to server via
1051 *              domain socket. Corresponding fields of parameters to be set
1052 *              are already filled in by upper layer caller.
1053 *==========================================================================*/
1054static int32_t mm_camera_intf_set_stream_parms(uint32_t camera_handle,
1055                                               uint32_t ch_id,
1056                                               uint32_t s_id,
1057                                               cam_stream_parm_buffer_t *parms)
1058{
1059    int32_t rc = -1;
1060    mm_camera_obj_t * my_obj = NULL;
1061
1062    pthread_mutex_lock(&g_intf_lock);
1063    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
1064
1065    CDBG("%s :E camera_handle = %d,ch_id = %d,s_id = %d",
1066         __func__, camera_handle, ch_id, s_id);
1067
1068    if(my_obj) {
1069        pthread_mutex_lock(&my_obj->cam_lock);
1070        pthread_mutex_unlock(&g_intf_lock);
1071        rc = mm_camera_set_stream_parms(my_obj, ch_id, s_id, parms);
1072    }else{
1073        pthread_mutex_unlock(&g_intf_lock);
1074    }
1075    CDBG("%s :X rc = %d", __func__, rc);
1076    return rc;
1077}
1078
1079/*===========================================================================
1080 * FUNCTION   : mm_camera_intf_get_stream_parms
1081 *
1082 * DESCRIPTION: get parameters per stream
1083 *
1084 * PARAMETERS :
1085 *   @camera_handle: camera handle
1086 *   @ch_id        : channel handle
1087 *   @s_id         : stream handle
1088 *   @parms        : ptr to a param struct to be get from server
1089 *
1090 * RETURN     : int32_t type of status
1091 *              0  -- success
1092 *              -1 -- failure
1093 * NOTE       : Assume the parms struct buf is already mapped to server via
1094 *              domain socket. Parameters to be get from server are already
1095 *              filled in by upper layer caller. After this call, corresponding
1096 *              fields of requested parameters will be filled in by server with
1097 *              detailed information.
1098 *==========================================================================*/
1099static int32_t mm_camera_intf_get_stream_parms(uint32_t camera_handle,
1100                                               uint32_t ch_id,
1101                                               uint32_t s_id,
1102                                               cam_stream_parm_buffer_t *parms)
1103{
1104    int32_t rc = -1;
1105    mm_camera_obj_t * my_obj = NULL;
1106
1107    pthread_mutex_lock(&g_intf_lock);
1108    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
1109
1110    CDBG("%s :E camera_handle = %d,ch_id = %d,s_id = %d",
1111         __func__, camera_handle, ch_id, s_id);
1112
1113    if(my_obj) {
1114        pthread_mutex_lock(&my_obj->cam_lock);
1115        pthread_mutex_unlock(&g_intf_lock);
1116        rc = mm_camera_get_stream_parms(my_obj, ch_id, s_id, parms);
1117    }else{
1118        pthread_mutex_unlock(&g_intf_lock);
1119    }
1120
1121    CDBG("%s :X rc = %d", __func__, rc);
1122    return rc;
1123}
1124
1125/*===========================================================================
1126 * FUNCTION   : mm_camera_intf_map_stream_buf
1127 *
1128 * DESCRIPTION: mapping stream buffer via domain socket to server
1129 *
1130 * PARAMETERS :
1131 *   @camera_handle: camera handle
1132 *   @ch_id        : channel handle
1133 *   @s_id         : stream handle
1134 *   @buf_type     : type of buffer to be mapped. could be following values:
1135 *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1136 *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1137 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1138 *   @buf_idx      : index of buffer within the stream buffers, only valid if
1139 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1140 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1141 *   @plane_idx    : plane index. If all planes share the same fd,
1142 *                   plane_idx = -1; otherwise, plean_idx is the
1143 *                   index to plane (0..num_of_planes)
1144 *   @fd           : file descriptor of the buffer
1145 *   @size         : size of the buffer
1146 *
1147 * RETURN     : int32_t type of status
1148 *              0  -- success
1149 *              -1 -- failure
1150 *==========================================================================*/
1151static int32_t mm_camera_intf_map_stream_buf(uint32_t camera_handle,
1152                                             uint32_t ch_id,
1153                                             uint32_t stream_id,
1154                                             uint8_t buf_type,
1155                                             uint32_t buf_idx,
1156                                             int32_t plane_idx,
1157                                             int fd,
1158                                             uint32_t size)
1159{
1160    int32_t rc = -1;
1161    mm_camera_obj_t * my_obj = NULL;
1162
1163    pthread_mutex_lock(&g_intf_lock);
1164    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
1165
1166    CDBG("%s :E camera_handle = %d, ch_id = %d, s_id = %d, buf_idx = %d, plane_idx = %d",
1167         __func__, camera_handle, ch_id, stream_id, buf_idx, plane_idx);
1168
1169    if(my_obj) {
1170        pthread_mutex_lock(&my_obj->cam_lock);
1171        pthread_mutex_unlock(&g_intf_lock);
1172        rc = mm_camera_map_stream_buf(my_obj, ch_id, stream_id,
1173                                      buf_type, buf_idx, plane_idx,
1174                                      fd, size);
1175    }else{
1176        pthread_mutex_unlock(&g_intf_lock);
1177    }
1178
1179    CDBG("%s :X rc = %d", __func__, rc);
1180    return rc;
1181}
1182
1183/*===========================================================================
1184 * FUNCTION   : mm_camera_intf_unmap_stream_buf
1185 *
1186 * DESCRIPTION: unmapping stream buffer via domain socket to server
1187 *
1188 * PARAMETERS :
1189 *   @camera_handle: camera handle
1190 *   @ch_id        : channel handle
1191 *   @s_id         : stream handle
1192 *   @buf_type     : type of buffer to be unmapped. could be following values:
1193 *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1194 *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1195 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1196 *   @buf_idx      : index of buffer within the stream buffers, only valid if
1197 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1198 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1199 *   @plane_idx    : plane index. If all planes share the same fd,
1200 *                   plane_idx = -1; otherwise, plean_idx is the
1201 *                   index to plane (0..num_of_planes)
1202 *
1203 * RETURN     : int32_t type of status
1204 *              0  -- success
1205 *              -1 -- failure
1206 *==========================================================================*/
1207static int32_t mm_camera_intf_unmap_stream_buf(uint32_t camera_handle,
1208                                               uint32_t ch_id,
1209                                               uint32_t stream_id,
1210                                               uint8_t buf_type,
1211                                               uint32_t buf_idx,
1212                                               int32_t plane_idx)
1213{
1214    int32_t rc = -1;
1215    mm_camera_obj_t * my_obj = NULL;
1216
1217    pthread_mutex_lock(&g_intf_lock);
1218    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
1219
1220    CDBG("%s :E camera_handle = %d, ch_id = %d, s_id = %d, buf_idx = %d, plane_idx = %d",
1221         __func__, camera_handle, ch_id, stream_id, buf_idx, plane_idx);
1222
1223    if(my_obj) {
1224        pthread_mutex_lock(&my_obj->cam_lock);
1225        pthread_mutex_unlock(&g_intf_lock);
1226        rc = mm_camera_unmap_stream_buf(my_obj, ch_id, stream_id,
1227                                        buf_type, buf_idx, plane_idx);
1228    }else{
1229        pthread_mutex_unlock(&g_intf_lock);
1230    }
1231
1232    CDBG("%s :X rc = %d", __func__, rc);
1233    return rc;
1234}
1235
1236/*===========================================================================
1237 * FUNCTION   : get_num_of_cameras
1238 *
1239 * DESCRIPTION: get number of cameras
1240 *
1241 * PARAMETERS :
1242 *
1243 * RETURN     : number of cameras supported
1244 *==========================================================================*/
1245uint8_t get_num_of_cameras()
1246{
1247    int rc = 0;
1248    int dev_fd = 0;
1249    struct media_device_info mdev_info;
1250    int num_media_devices = 0;
1251    uint8_t num_cameras = 0;
1252
1253    CDBG("%s : E", __func__);
1254    /* lock the mutex */
1255    pthread_mutex_lock(&g_intf_lock);
1256    while (1) {
1257        char dev_name[32];
1258        int num_entities;
1259        snprintf(dev_name, sizeof(dev_name), "/dev/media%d", num_media_devices);
1260        dev_fd = open(dev_name, O_RDWR | O_NONBLOCK);
1261        if (dev_fd <= 0) {
1262            CDBG("Done discovering media devices\n");
1263            break;
1264        }
1265        num_media_devices++;
1266        memset(&mdev_info, 0, sizeof(mdev_info));
1267        rc = ioctl(dev_fd, MEDIA_IOC_DEVICE_INFO, &mdev_info);
1268        if (rc < 0) {
1269            CDBG_ERROR("Error: ioctl media_dev failed: %s\n", strerror(errno));
1270            close(dev_fd);
1271            dev_fd = 0;
1272            num_cameras = 0;
1273            break;
1274        }
1275
1276        if(strncmp(mdev_info.model, MSM_CAMERA_NAME, sizeof(mdev_info.model)) != 0) {
1277            close(dev_fd);
1278            dev_fd = 0;
1279            continue;
1280        }
1281
1282        num_entities = 1;
1283        while (1) {
1284            struct media_entity_desc entity;
1285            memset(&entity, 0, sizeof(entity));
1286            entity.id = num_entities++;
1287            rc = ioctl(dev_fd, MEDIA_IOC_ENUM_ENTITIES, &entity);
1288            if (rc < 0) {
1289                CDBG("Done enumerating media entities\n");
1290                rc = 0;
1291                break;
1292            }
1293            if(entity.type == MEDIA_ENT_T_DEVNODE_V4L && entity.group_id == QCAMERA_VNODE_GROUP_ID) {
1294                strncpy(g_cam_ctrl.video_dev_name[num_cameras],
1295                     entity.name, sizeof(entity.name));
1296                break;
1297            }
1298        }
1299
1300        CDBG("%s: dev_info[id=%d,name='%s']\n",
1301            __func__, num_cameras, g_cam_ctrl.video_dev_name[num_cameras]);
1302
1303        num_cameras++;
1304        close(dev_fd);
1305        dev_fd = 0;
1306    }
1307    g_cam_ctrl.num_cam = num_cameras;
1308
1309    /* unlock the mutex */
1310    pthread_mutex_unlock(&g_intf_lock);
1311    CDBG("%s: num_cameras=%d\n", __func__, g_cam_ctrl.num_cam);
1312    return g_cam_ctrl.num_cam;
1313}
1314
1315/* camera ops v-table */
1316static mm_camera_ops_t mm_camera_ops = {
1317    .query_capability = mm_camera_intf_query_capability,
1318    .register_event_notify = mm_camera_intf_register_event_notify,
1319    .close_camera = mm_camera_intf_close,
1320    .set_parms = mm_camera_intf_set_parms,
1321    .get_parms = mm_camera_intf_get_parms,
1322    .do_auto_focus = mm_camera_intf_do_auto_focus,
1323    .cancel_auto_focus = mm_camera_intf_cancel_auto_focus,
1324    .prepare_snapshot = mm_camera_intf_prepare_snapshot,
1325    .start_zsl_snapshot = mm_camera_intf_start_zsl_snapshot,
1326    .stop_zsl_snapshot = mm_camera_intf_stop_zsl_snapshot,
1327    .map_buf = mm_camera_intf_map_buf,
1328    .unmap_buf = mm_camera_intf_unmap_buf,
1329    .add_channel = mm_camera_intf_add_channel,
1330    .delete_channel = mm_camera_intf_del_channel,
1331    .get_bundle_info = mm_camera_intf_get_bundle_info,
1332    .add_stream = mm_camera_intf_add_stream,
1333    .delete_stream = mm_camera_intf_del_stream,
1334    .config_stream = mm_camera_intf_config_stream,
1335    .qbuf = mm_camera_intf_qbuf,
1336    .map_stream_buf = mm_camera_intf_map_stream_buf,
1337    .unmap_stream_buf = mm_camera_intf_unmap_stream_buf,
1338    .set_stream_parms = mm_camera_intf_set_stream_parms,
1339    .get_stream_parms = mm_camera_intf_get_stream_parms,
1340    .start_channel = mm_camera_intf_start_channel,
1341    .stop_channel = mm_camera_intf_stop_channel,
1342    .request_super_buf = mm_camera_intf_request_super_buf,
1343    .cancel_super_buf_request = mm_camera_intf_cancel_super_buf_request,
1344    .flush_super_buf_queue = mm_camera_intf_flush_super_buf_queue,
1345    .configure_notify_mode = mm_camera_intf_configure_notify_mode
1346};
1347
1348/*===========================================================================
1349 * FUNCTION   : camera_open
1350 *
1351 * DESCRIPTION: open a camera by camera index
1352 *
1353 * PARAMETERS :
1354 *   @camera_idx : camera index. should within range of 0 to num_of_cameras
1355 *
1356 * RETURN     : ptr to a virtual table containing camera handle and operation table.
1357 *              NULL if failed.
1358 *==========================================================================*/
1359mm_camera_vtbl_t * camera_open(uint8_t camera_idx)
1360{
1361    int32_t rc = 0;
1362    mm_camera_obj_t* cam_obj = NULL;
1363
1364    CDBG("%s: E camera_idx = %d\n", __func__, camera_idx);
1365    if (camera_idx >= g_cam_ctrl.num_cam) {
1366        CDBG_ERROR("%s: Invalid camera_idx (%d)", __func__, camera_idx);
1367        return NULL;
1368    }
1369
1370    pthread_mutex_lock(&g_intf_lock);
1371    /* opened already */
1372    if(NULL != g_cam_ctrl.cam_obj[camera_idx]) {
1373        /* Add reference */
1374        g_cam_ctrl.cam_obj[camera_idx]->ref_count++;
1375        pthread_mutex_unlock(&g_intf_lock);
1376        CDBG("%s:  opened alreadyn", __func__);
1377        return &g_cam_ctrl.cam_obj[camera_idx]->vtbl;
1378    }
1379
1380    cam_obj = (mm_camera_obj_t *)malloc(sizeof(mm_camera_obj_t));
1381    if(NULL == cam_obj) {
1382        pthread_mutex_unlock(&g_intf_lock);
1383        CDBG("%s:  no mem", __func__);
1384        return NULL;
1385    }
1386
1387    /* initialize camera obj */
1388    memset(cam_obj, 0, sizeof(mm_camera_obj_t));
1389    cam_obj->ref_count++;
1390    cam_obj->my_hdl = mm_camera_util_generate_handler(camera_idx);
1391    cam_obj->vtbl.camera_handle = cam_obj->my_hdl; /* set handler */
1392    cam_obj->vtbl.ops = &mm_camera_ops;
1393    pthread_mutex_init(&cam_obj->cam_lock, NULL);
1394
1395    rc = mm_camera_open(cam_obj);
1396    if(rc != 0) {
1397        CDBG_ERROR("%s: mm_camera_open err = %d", __func__, rc);
1398        pthread_mutex_destroy(&cam_obj->cam_lock);
1399        g_cam_ctrl.cam_obj[camera_idx] = NULL;
1400        free(cam_obj);
1401        cam_obj = NULL;
1402        pthread_mutex_unlock(&g_intf_lock);
1403        return NULL;
1404    }else{
1405        CDBG("%s: Open succeded\n", __func__);
1406        g_cam_ctrl.cam_obj[camera_idx] = cam_obj;
1407        pthread_mutex_unlock(&g_intf_lock);
1408        return &cam_obj->vtbl;
1409    }
1410}
1411