1/*
2Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7    * Redistributions of source code must retain the above copyright
8      notice, this list of conditions and the following disclaimer.
9    * Redistributions in binary form must reproduce the above
10      copyright notice, this list of conditions and the following
11      disclaimer in the documentation and/or other materials provided
12      with the distribution.
13    * Neither the name of The Linux Foundation nor the names of its
14      contributors may be used to endorse or promote products derived
15      from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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#include <semaphore.h>
39
40#include "mm_camera_dbg.h"
41#include "mm_camera_interface.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, 0, 0}, 0, 0}}, 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/* utility function to generate handler */
52uint32_t mm_camera_util_generate_handler(uint8_t index)
53{
54    uint32_t handler = 0;
55    pthread_mutex_lock(&g_handler_lock);
56    g_handler_history_count++;
57    if (0 == g_handler_history_count) {
58        g_handler_history_count++;
59    }
60    handler = g_handler_history_count;
61    handler = (handler<<8) | index;
62    pthread_mutex_unlock(&g_handler_lock);
63    return handler;
64}
65
66uint8_t mm_camera_util_get_index_by_handler(uint32_t handler)
67{
68    return (handler&0x000000ff);
69}
70
71const char *mm_camera_util_get_dev_name(uint32_t cam_handler)
72{
73    char *dev_name = NULL;
74    uint8_t cam_idx = mm_camera_util_get_index_by_handler(cam_handler);
75    dev_name = g_cam_ctrl.camera[cam_idx].video_dev_name;
76    return dev_name;
77}
78
79mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler)
80{
81    mm_camera_obj_t *cam_obj = NULL;
82    uint8_t cam_idx = mm_camera_util_get_index_by_handler(cam_handler);
83
84    if ((NULL != g_cam_ctrl.cam_obj[cam_idx]) &&
85        (cam_handler == g_cam_ctrl.cam_obj[cam_idx]->my_hdl)) {
86        cam_obj = g_cam_ctrl.cam_obj[cam_idx];
87    }
88    return cam_obj;
89}
90
91static int32_t mm_camera_intf_sync(uint32_t camera_handler)
92{
93    int32_t rc = -1;
94    mm_camera_obj_t * my_obj = NULL;
95
96    CDBG("%s E: camera_handler = %d ",__func__,camera_handler);
97
98    pthread_mutex_lock(&g_intf_lock);
99    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
100
101    if(my_obj) {
102        pthread_mutex_lock(&my_obj->cam_lock);
103        pthread_mutex_unlock(&g_intf_lock);
104        rc = mm_camera_sync(my_obj);
105    } else {
106        pthread_mutex_unlock(&g_intf_lock);
107    }
108    CDBG("%s :X rc = %d",__func__,rc);
109    return rc;
110}
111
112/* check if the parm is supported */
113static int32_t mm_camera_intf_is_parm_supported(uint32_t camera_handler,
114                                   mm_camera_parm_type_t parm_type,
115                                   uint8_t *support_set_parm,
116                                   uint8_t *support_get_parm)
117{
118    int32_t rc = -1;
119    mm_camera_obj_t * my_obj = NULL;
120
121    pthread_mutex_lock(&g_intf_lock);
122    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
123    *support_set_parm = 0;
124    *support_get_parm = 0;
125
126    if(my_obj) {
127        pthread_mutex_lock(&my_obj->cam_lock);
128        pthread_mutex_unlock(&g_intf_lock);
129        rc = mm_camera_is_parm_supported(my_obj, parm_type, support_set_parm, support_get_parm);
130    } else {
131        pthread_mutex_unlock(&g_intf_lock);
132    }
133    return rc;
134}
135
136/* set a parm�s current value */
137static int32_t mm_camera_intf_set_parm(uint32_t camera_handler,
138                                   mm_camera_parm_type_t parm_type,
139                                   void* p_value)
140{
141    int32_t rc = -1;
142    mm_camera_obj_t * my_obj = NULL;
143
144    pthread_mutex_lock(&g_intf_lock);
145    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
146
147    if(my_obj) {
148        pthread_mutex_lock(&my_obj->cam_lock);
149        pthread_mutex_unlock(&g_intf_lock);
150        rc = mm_camera_set_parm(my_obj, parm_type, p_value);
151    } else {
152        pthread_mutex_unlock(&g_intf_lock);
153    }
154    return rc;
155}
156
157/* get a parm�s current value */
158static int32_t mm_camera_intf_get_parm(uint32_t camera_handler,
159                                mm_camera_parm_type_t parm_type,
160                                void* p_value)
161{
162    int32_t rc = -1;
163    mm_camera_obj_t * my_obj = NULL;
164
165    pthread_mutex_lock(&g_intf_lock);
166    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
167
168    if(my_obj) {
169        pthread_mutex_lock(&my_obj->cam_lock);
170        pthread_mutex_unlock(&g_intf_lock);
171        rc = mm_camera_get_parm(my_obj, parm_type, p_value);
172    } else {
173        pthread_mutex_unlock(&g_intf_lock);
174    }
175    return rc;
176}
177
178static void mm_camera_intf_close(uint32_t camera_handler)
179{
180    int32_t rc = -1;
181    uint8_t cam_idx = camera_handler & 0x00ff;
182    mm_camera_obj_t * my_obj = NULL;
183
184    CDBG("%s E: camera_handler = %d ",__func__,camera_handler);
185    pthread_mutex_lock(&g_intf_lock);
186    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
187
188    if (my_obj){
189        my_obj->ref_count--;
190
191        if(my_obj->ref_count > 0) {
192            /* still have reference to obj, return here */
193            CDBG("%s: ref_count=%d\n", __func__, my_obj->ref_count);
194            pthread_mutex_unlock(&g_intf_lock);
195            return;
196        }
197
198        /* need close camera here as no other reference
199         * first empty g_cam_ctrl's referent to cam_obj */
200        g_cam_ctrl.cam_obj[cam_idx] = NULL;
201
202        pthread_mutex_lock(&my_obj->cam_lock);
203        pthread_mutex_unlock(&g_intf_lock);
204
205        mm_camera_close(my_obj);
206
207        pthread_mutex_destroy(&my_obj->cam_lock);
208        free(my_obj);
209
210    } else {
211        pthread_mutex_unlock(&g_intf_lock);
212    }
213}
214
215static uint32_t mm_camera_intf_add_channel(uint32_t camera_handler)
216{
217    uint32_t ch_id = 0;
218    mm_camera_obj_t * my_obj = NULL;
219
220    CDBG("%s :E camera_handler = %d",__func__,camera_handler);
221    pthread_mutex_lock(&g_intf_lock);
222    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
223
224    if(my_obj) {
225        pthread_mutex_lock(&my_obj->cam_lock);
226        pthread_mutex_unlock(&g_intf_lock);
227        ch_id = mm_camera_add_channel(my_obj);
228    } else {
229        pthread_mutex_unlock(&g_intf_lock);
230    }
231    CDBG("%s :X ch_id = %d",__func__,ch_id);
232    return ch_id;
233}
234
235static void mm_camera_intf_del_channel(uint32_t camera_handler, uint32_t ch_id)
236{
237    mm_camera_obj_t * my_obj = NULL;
238
239    CDBG("%s :E ch_id = %d",__func__,ch_id);
240    pthread_mutex_lock(&g_intf_lock);
241    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
242
243    if(my_obj) {
244        pthread_mutex_lock(&my_obj->cam_lock);
245        pthread_mutex_unlock(&g_intf_lock);
246        mm_camera_del_channel(my_obj, ch_id);
247    } else {
248        pthread_mutex_unlock(&g_intf_lock);
249    }
250    CDBG("%s :X",__func__);
251}
252
253static uint8_t mm_camera_intf_is_event_supported(uint32_t camera_handler,
254                                    mm_camera_event_type_t evt_type)
255{
256    switch(evt_type) {
257    case MM_CAMERA_EVT_TYPE_CH:
258    case MM_CAMERA_EVT_TYPE_CTRL:
259    case MM_CAMERA_EVT_TYPE_STATS:
260    case MM_CAMERA_EVT_TYPE_INFO:
261        return 1;
262    default:
263        return 0;
264    }
265    return 0;
266}
267
268static int32_t mm_camera_intf_register_event_notify(
269                                    uint32_t camera_handler,
270                                    mm_camera_event_notify_t evt_cb,
271                                    void * user_data,
272                                    mm_camera_event_type_t evt_type)
273{
274    int32_t rc = -1;
275    mm_camera_obj_t * my_obj = NULL;
276
277    CDBG("%s :E evt_type = %d",__func__,evt_type);
278    pthread_mutex_lock(&g_intf_lock);
279    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
280
281    if(my_obj) {
282        pthread_mutex_lock(&my_obj->cam_lock);
283        pthread_mutex_unlock(&g_intf_lock);
284        rc = mm_camera_register_event_notify(my_obj, evt_cb, user_data, evt_type);
285    } else {
286        pthread_mutex_unlock(&g_intf_lock);
287    }
288    CDBG("%s :E rc = %d",__func__,rc);
289    return rc;
290}
291
292static mm_camera_2nd_sensor_t * mm_camera_intf_query_2nd_sensor_info(uint32_t camera_handler)
293{
294    mm_camera_2nd_sensor_t *sensor_info = NULL;
295    mm_camera_obj_t * my_obj = NULL;
296
297    CDBG("%s :E camera_handler = %d",__func__,camera_handler);
298    pthread_mutex_lock(&g_intf_lock);
299    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
300
301    if(my_obj) {
302        pthread_mutex_lock(&my_obj->cam_lock);
303        pthread_mutex_unlock(&g_intf_lock);
304        sensor_info = mm_camera_query_2nd_sensor_info(my_obj);
305    } else {
306        pthread_mutex_unlock(&g_intf_lock);
307    }
308    CDBG("%s :X",__func__);
309    return sensor_info;
310}
311
312static int32_t mm_camera_intf_qbuf(uint32_t camera_handler,
313                                    uint32_t ch_id,
314                                    mm_camera_buf_def_t *buf)
315{
316    int32_t rc = -1;
317    mm_camera_obj_t * my_obj = NULL;
318
319    pthread_mutex_lock(&g_intf_lock);
320    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
321
322    if(my_obj) {
323        pthread_mutex_lock(&my_obj->cam_lock);
324        pthread_mutex_unlock(&g_intf_lock);
325        rc = mm_camera_qbuf(my_obj, ch_id, buf);
326    } else {
327        pthread_mutex_unlock(&g_intf_lock);
328    }
329    CDBG("%s :X evt_type = %d",__func__,rc);
330    return rc;
331}
332
333static uint32_t mm_camera_intf_add_stream(
334                                    uint32_t camera_handler,
335                                    uint32_t ch_id,
336                                    mm_camera_buf_notify_t buf_cb, void *user_data,
337                                    uint32_t ext_image_mode, uint32_t sensor_idx)
338{
339    uint32_t stream_id = 0;
340    mm_camera_obj_t * my_obj = NULL;
341
342    CDBG("%s : E handle = %d ch_id = %d",__func__,camera_handler,
343         ch_id);
344
345    pthread_mutex_lock(&g_intf_lock);
346    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
347
348    if(my_obj) {
349        pthread_mutex_lock(&my_obj->cam_lock);
350        pthread_mutex_unlock(&g_intf_lock);
351        stream_id = mm_camera_add_stream(my_obj, ch_id, buf_cb,
352                                  user_data, ext_image_mode, sensor_idx);
353    } else {
354        pthread_mutex_unlock(&g_intf_lock);
355    }
356    CDBG("%s :X stream_id = %d",__func__,stream_id);
357    return stream_id;
358}
359
360static int32_t mm_camera_intf_del_stream(
361                                    uint32_t camera_handler,
362                                    uint32_t ch_id,
363                                    uint32_t stream_id)
364{
365    int32_t rc = -1;
366    mm_camera_obj_t * my_obj = NULL;
367
368    CDBG("%s : E handle = %d ch_id = %d stream_id = %d",__func__,camera_handler,
369         ch_id,stream_id);
370
371    pthread_mutex_lock(&g_intf_lock);
372    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
373
374    if(my_obj) {
375        pthread_mutex_lock(&my_obj->cam_lock);
376        pthread_mutex_unlock(&g_intf_lock);
377        rc = mm_camera_del_stream(my_obj, ch_id, stream_id);
378    } else {
379        pthread_mutex_unlock(&g_intf_lock);
380    }
381    CDBG("%s :X rc = %d",__func__,rc);
382    return rc;
383}
384
385static int32_t mm_camera_intf_config_stream(
386                                    uint32_t camera_handler,
387                                    uint32_t ch_id,
388                                    uint32_t stream_id,
389                                    mm_camera_stream_config_t *config)
390{
391    int32_t rc = -1;
392    mm_camera_obj_t * my_obj = NULL;
393
394    CDBG("%s :E handle = %d, ch_id = %d,stream_id = %d",__func__,
395         camera_handler,ch_id,stream_id);
396
397    pthread_mutex_lock(&g_intf_lock);
398    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
399
400    CDBG("%s :mm_camera_intf_config_stream stream_id = %d",__func__,stream_id);
401
402    if(my_obj) {
403        pthread_mutex_lock(&my_obj->cam_lock);
404        pthread_mutex_unlock(&g_intf_lock);
405        rc = mm_camera_config_stream(my_obj, ch_id, stream_id, config);
406    } else {
407        pthread_mutex_unlock(&g_intf_lock);
408    }
409    CDBG("%s :X rc = %d",__func__,rc);
410    return rc;
411}
412
413static int32_t mm_camera_intf_bundle_streams(
414                                    uint32_t camera_handler,
415                                    uint32_t ch_id,
416                                    mm_camera_buf_notify_t super_frame_notify_cb,
417                                    void *user_data,
418                                    mm_camera_bundle_attr_t *attr,
419                                    uint8_t num_streams,
420                                    uint32_t *stream_ids)
421{
422    int32_t rc = -1;
423    mm_camera_obj_t * my_obj = NULL;
424
425    CDBG("%s :E handle = %d, ch_id = %d",__func__,
426         camera_handler,ch_id);
427
428    if (MM_CAMEAR_MAX_STRAEM_BUNDLE < num_streams) {
429        CDBG_ERROR("%s: number of streams (%d) exceeds max (%d)",
430                   __func__, num_streams, MM_CAMEAR_MAX_STRAEM_BUNDLE);
431        return rc;
432    }
433
434    pthread_mutex_lock(&g_intf_lock);
435    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
436
437    if(my_obj) {
438        pthread_mutex_lock(&my_obj->cam_lock);
439        pthread_mutex_unlock(&g_intf_lock);
440        rc = mm_camera_bundle_streams(my_obj, ch_id,
441                                      super_frame_notify_cb,
442                                      user_data, attr,
443                                      num_streams, stream_ids);
444    } else {
445        pthread_mutex_unlock(&g_intf_lock);
446    }
447    CDBG("%s :X rc = %d",__func__,rc);
448    return rc;
449}
450
451static int32_t mm_camera_intf_destroy_bundle(uint32_t camera_handler,
452                                    uint32_t ch_id)
453{
454    int32_t rc = -1;
455    mm_camera_obj_t * my_obj = NULL;
456
457    CDBG("%s :E handle = %d, ch_id = %d",__func__,
458         camera_handler,ch_id);
459    pthread_mutex_lock(&g_intf_lock);
460    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
461
462    if(my_obj) {
463        pthread_mutex_lock(&my_obj->cam_lock);
464        pthread_mutex_unlock(&g_intf_lock);
465        rc = mm_camera_destroy_bundle(my_obj, ch_id);
466    } else {
467        pthread_mutex_unlock(&g_intf_lock);
468    }
469    CDBG("%s :X rc = %d",__func__,rc);
470    return rc;
471}
472
473static int32_t mm_camera_intf_start_streams(
474                                    uint32_t camera_handler,
475                                    uint32_t ch_id,
476                                    uint8_t num_streams,
477                                    uint32_t *stream_ids)
478{
479    int32_t rc = -1;
480    mm_camera_obj_t * my_obj = NULL;
481
482    CDBG("%s :E camera_handler = %d,ch_id = %d, num_streams = %d",
483         __func__,camera_handler,ch_id,num_streams);
484    if (MM_CAMEAR_STRAEM_NUM_MAX < num_streams) {
485        CDBG_ERROR("%s: num of streams (%d) exceeds MAX (%d)",
486                   __func__, num_streams, MM_CAMEAR_STRAEM_NUM_MAX);
487        return rc;
488    }
489
490    pthread_mutex_lock(&g_intf_lock);
491    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
492
493    if(my_obj) {
494        pthread_mutex_lock(&my_obj->cam_lock);
495        pthread_mutex_unlock(&g_intf_lock);
496        rc = mm_camera_start_streams(my_obj, ch_id, num_streams, stream_ids);
497    } else {
498        pthread_mutex_unlock(&g_intf_lock);
499    }
500    CDBG("%s :X rc = %d",__func__,rc);
501    return rc;
502}
503
504static int32_t mm_camera_intf_stop_streams(
505                                    uint32_t camera_handler,
506                                    uint32_t ch_id,
507                                    uint8_t num_streams,
508                                    uint32_t *stream_ids)
509{
510    int32_t rc = -1;
511    mm_camera_obj_t * my_obj = NULL;
512
513    CDBG("%s :E camera_handler = %d,ch_id = %d, num_streams = %d",
514         __func__,camera_handler,ch_id,num_streams);
515
516    if (MM_CAMEAR_STRAEM_NUM_MAX < num_streams) {
517        CDBG_ERROR("%s: num of streams (%d) exceeds MAX (%d)",
518                   __func__, num_streams, MM_CAMEAR_STRAEM_NUM_MAX);
519        return rc;
520    }
521
522    pthread_mutex_lock(&g_intf_lock);
523    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
524
525    if(my_obj) {
526        pthread_mutex_lock(&my_obj->cam_lock);
527        pthread_mutex_unlock(&g_intf_lock);
528        rc = mm_camera_stop_streams(my_obj, ch_id,
529                                    num_streams, stream_ids);
530    } else {
531        pthread_mutex_unlock(&g_intf_lock);
532    }
533    CDBG("%s :X rc = %d",__func__,rc);
534    return rc;
535}
536
537static int32_t mm_camera_intf_async_teardown_streams(
538                                    uint32_t camera_handler,
539                                    uint32_t ch_id,
540                                    uint8_t num_streams,
541                                    uint32_t *stream_ids)
542{
543    int32_t rc = -1;
544    mm_camera_obj_t * my_obj = NULL;
545
546    CDBG("%s :E camera_handler = %d,ch_id = %d, num_streams = %d",
547         __func__,camera_handler,ch_id,num_streams);
548
549    if (MM_CAMEAR_STRAEM_NUM_MAX < num_streams) {
550        CDBG_ERROR("%s: num of streams (%d) exceeds MAX (%d)",
551                   __func__, num_streams, MM_CAMEAR_STRAEM_NUM_MAX);
552        return rc;
553    }
554
555    pthread_mutex_lock(&g_intf_lock);
556    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
557
558    if(my_obj) {
559        pthread_mutex_lock(&my_obj->cam_lock);
560        pthread_mutex_unlock(&g_intf_lock);
561        rc = mm_camera_async_teardown_streams(my_obj, ch_id,
562                                              num_streams, stream_ids);
563    } else {
564        pthread_mutex_unlock(&g_intf_lock);
565    }
566    CDBG("%s :X rc = %d",__func__,rc);
567    return rc;
568}
569
570static int32_t mm_camera_intf_request_super_buf(
571                                    uint32_t camera_handler,
572                                    uint32_t ch_id)
573{
574    int32_t rc = -1;
575    CDBG("%s :E camera_handler = %d,ch_id = %d",
576         __func__,camera_handler,ch_id);
577    mm_camera_obj_t * my_obj = NULL;
578
579    pthread_mutex_lock(&g_intf_lock);
580    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
581
582    if(my_obj) {
583        pthread_mutex_lock(&my_obj->cam_lock);
584        pthread_mutex_unlock(&g_intf_lock);
585        rc = mm_camera_request_super_buf(my_obj, ch_id);
586    } else {
587        pthread_mutex_unlock(&g_intf_lock);
588    }
589    CDBG("%s :X rc = %d",__func__,rc);
590    return rc;
591}
592
593static int32_t mm_camera_intf_cancel_super_buf_request(
594                                    uint32_t camera_handler,
595                                    uint32_t ch_id)
596{
597    int32_t rc = -1;
598    mm_camera_obj_t * my_obj = NULL;
599
600    CDBG("%s :E camera_handler = %d,ch_id = %d",
601         __func__,camera_handler,ch_id);
602    pthread_mutex_lock(&g_intf_lock);
603    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
604
605    if(my_obj) {
606        pthread_mutex_lock(&my_obj->cam_lock);
607        pthread_mutex_unlock(&g_intf_lock);
608        rc = mm_camera_cancel_super_buf_request(my_obj, ch_id);
609    } else {
610        pthread_mutex_unlock(&g_intf_lock);
611    }
612    CDBG("%s :X rc = %d",__func__,rc);
613    return rc;
614}
615
616static int32_t mm_camera_intf_start_focus(
617                                    uint32_t camera_handler,
618                                    uint32_t ch_id,
619                                    uint32_t sensor_idx,
620                                    uint32_t focus_mode)
621{
622    int32_t rc = -1;
623    mm_camera_obj_t * my_obj = NULL;
624
625    CDBG("%s :E camera_handler = %d,ch_id = %d, focus_mode = %d",
626         __func__,camera_handler,ch_id,focus_mode);
627    pthread_mutex_lock(&g_intf_lock);
628    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
629
630    if(my_obj) {
631        pthread_mutex_lock(&my_obj->cam_lock);
632        pthread_mutex_unlock(&g_intf_lock);
633        rc = mm_camera_start_focus(my_obj, ch_id, sensor_idx, focus_mode);
634    } else {
635        pthread_mutex_unlock(&g_intf_lock);
636    }
637    CDBG("%s :X rc = %d",__func__,rc);
638    return rc;
639}
640
641static int32_t mm_camera_intf_abort_focus(
642                                    uint32_t camera_handler,
643                                    uint32_t ch_id,
644                                    uint32_t sensor_idx)
645{
646    int32_t rc = -1;
647    mm_camera_obj_t * my_obj = NULL;
648
649    pthread_mutex_lock(&g_intf_lock);
650    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
651
652    if(my_obj) {
653        pthread_mutex_lock(&my_obj->cam_lock);
654        pthread_mutex_unlock(&g_intf_lock);
655        rc = mm_camera_abort_focus(my_obj, ch_id, sensor_idx);
656    } else {
657        pthread_mutex_unlock(&g_intf_lock);
658    }
659    CDBG("%s :X rc = %d",__func__,rc);
660    return rc;
661}
662
663static int32_t mm_camera_intf_prepare_snapshot(
664                                    uint32_t camera_handler,
665                                    uint32_t ch_id,
666                                    uint32_t sensor_idx)
667{
668    int32_t rc = -1;
669    mm_camera_obj_t * my_obj = NULL;
670
671    pthread_mutex_lock(&g_intf_lock);
672    my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
673
674    if(my_obj) {
675        pthread_mutex_lock(&my_obj->cam_lock);
676        pthread_mutex_unlock(&g_intf_lock);
677        rc = mm_camera_prepare_snapshot(my_obj, ch_id, sensor_idx);
678    } else {
679        pthread_mutex_unlock(&g_intf_lock);
680    }
681    CDBG("%s :X rc = %d",__func__,rc);
682    return rc;
683}
684
685static int32_t mm_camera_intf_set_stream_parm(
686                                     uint32_t camera_handle,
687                                     uint32_t ch_id,
688                                     uint32_t s_id,
689                                     mm_camera_stream_parm_t parm_type,
690                                     void* p_value)
691{
692    int32_t rc = -1;
693    mm_camera_obj_t * my_obj = NULL;
694
695    pthread_mutex_lock(&g_intf_lock);
696    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
697
698    CDBG("%s :E camera_handle = %d,ch_id = %d,s_id = %d,parm_type = %d",__func__,
699            camera_handle,ch_id,s_id,parm_type);
700
701    if(my_obj) {
702        pthread_mutex_lock(&my_obj->cam_lock);
703        pthread_mutex_unlock(&g_intf_lock);
704        rc = mm_camera_set_stream_parm(my_obj,ch_id,s_id,
705                                       parm_type,
706                                       p_value);
707    }else{
708        pthread_mutex_unlock(&g_intf_lock);
709    }
710    CDBG("%s :X rc = %d",__func__,rc);
711    return rc;
712}
713
714static int32_t mm_camera_intf_get_stream_parm(
715                                     uint32_t camera_handle,
716                                     uint32_t ch_id,
717                                     uint32_t s_id,
718                                     mm_camera_stream_parm_t parm_type,
719                                     void* p_value)
720{
721    int32_t rc = -1;
722    mm_camera_obj_t * my_obj = NULL;
723
724    pthread_mutex_lock(&g_intf_lock);
725    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
726
727    CDBG("%s :E camera_handle = %d,ch_id = %d,s_id = %d,parm_type = %d",__func__,
728            camera_handle,ch_id,s_id,parm_type);
729
730    if(my_obj) {
731        pthread_mutex_lock(&my_obj->cam_lock);
732        pthread_mutex_unlock(&g_intf_lock);
733        rc = mm_camera_get_stream_parm(my_obj,ch_id,s_id,
734                                       parm_type,
735                                       p_value);
736    }else{
737        pthread_mutex_unlock(&g_intf_lock);
738    }
739
740    CDBG("%s :X rc = %d",__func__,rc);
741    return rc;
742}
743mm_camera_info_t * camera_query(uint8_t *num_cameras)
744{
745    int i = 0, rc = 0;
746    int dev_fd = 0;
747    struct media_device_info mdev_info;
748    int num_media_devices = 0;
749    if (!num_cameras) {
750        CDBG_ERROR("%s: num_cameras is NULL\n", __func__);
751        return NULL;
752    }
753
754    CDBG("%s : E",__func__);
755    /* lock the mutex */
756    pthread_mutex_lock(&g_intf_lock);
757    *num_cameras = 0;
758    while (1) {
759        char dev_name[32];
760        snprintf(dev_name, sizeof(dev_name), "/dev/media%d", num_media_devices);
761        dev_fd = open(dev_name, O_RDWR | O_NONBLOCK);
762        if (dev_fd < 0) {
763            CDBG("Done discovering media devices\n");
764            break;
765        }
766        num_media_devices++;
767        rc = ioctl(dev_fd, MEDIA_IOC_DEVICE_INFO, &mdev_info);
768        if (rc < 0) {
769            CDBG_ERROR("Error: ioctl media_dev failed: %s\n", strerror(errno));
770            close(dev_fd);
771            break;
772        }
773
774        if(strncmp(mdev_info.model, QCAMERA_NAME, sizeof(mdev_info.model) != 0)) {
775            close(dev_fd);
776            continue;
777        }
778
779        char * mdev_cfg;
780        int cam_type = 0, mount_angle = 0, info_index = 0;
781        mdev_cfg = strtok(mdev_info.serial, "-");
782        while(mdev_cfg != NULL) {
783            if(info_index == 0) {
784                if(strcmp(mdev_cfg, QCAMERA_NAME))
785                  break;
786            } else if(info_index == 1) {
787                mount_angle = atoi(mdev_cfg);
788            } else if(info_index == 2) {
789                cam_type = atoi(mdev_cfg);
790            }
791            mdev_cfg = strtok(NULL, "-");
792            info_index++;
793        }
794
795        if(info_index == 0) {
796            close(dev_fd);
797            continue;
798        }
799
800        int num_entities = 1;
801        while (1) {
802            struct media_entity_desc entity;
803            memset(&entity, 0, sizeof(entity));
804            entity.id = num_entities++;
805            rc = ioctl(dev_fd, MEDIA_IOC_ENUM_ENTITIES, &entity);
806            if (rc < 0) {
807                CDBG("Done enumerating media entities\n");
808                rc = 0;
809                break;
810            }
811            if(entity.type == MEDIA_ENT_T_DEVNODE_V4L && entity.group_id == QCAMERA_VNODE_GROUP_ID) {
812                strncpy(g_cam_ctrl.video_dev_name[*num_cameras],
813                     entity.name, sizeof(entity.name));
814                g_cam_ctrl.camera[*num_cameras].video_dev_name =
815                    &g_cam_ctrl.video_dev_name[*num_cameras][0];
816                break;
817            }
818        }
819
820        //g_cam_ctrl.camera[*num_cameras].camera_info.camera_id = *num_cameras;
821        g_cam_ctrl.camera[*num_cameras].camera_id = *num_cameras;
822
823        g_cam_ctrl.camera[*num_cameras].
824            camera_info.modes_supported = CAMERA_MODE_2D;
825
826        if(cam_type > 1) {
827            g_cam_ctrl.camera[*num_cameras].
828                camera_info.modes_supported |= CAMERA_MODE_3D;
829        }
830
831        g_cam_ctrl.camera[*num_cameras].camera_info.position =
832            (cam_type == 1) ? FRONT_CAMERA : BACK_CAMERA;
833
834        g_cam_ctrl.camera[*num_cameras].camera_info.sensor_mount_angle =
835            mount_angle;
836
837        g_cam_ctrl.camera[*num_cameras].main_sensor_type = 0;
838
839        CDBG("%s: dev_info[id=%d,name='%s',pos=%d,modes=0x%x,sensor=%d mount_angle = %d]\n",
840            __func__, *num_cameras,
841            g_cam_ctrl.camera[*num_cameras].video_dev_name,
842            g_cam_ctrl.camera[*num_cameras].camera_info.position,
843            g_cam_ctrl.camera[*num_cameras].camera_info.modes_supported,
844            g_cam_ctrl.camera[*num_cameras].main_sensor_type,
845            g_cam_ctrl.camera[*num_cameras].camera_info.sensor_mount_angle);
846
847        *num_cameras += 1;
848        if (dev_fd > 0) {
849            close(dev_fd);
850        }
851    }
852    *num_cameras = *num_cameras;
853    g_cam_ctrl.num_cam = *num_cameras;
854
855    /* unlock the mutex */
856    pthread_mutex_unlock(&g_intf_lock);
857    CDBG("%s: num_cameras=%d\n", __func__, g_cam_ctrl.num_cam);
858    if(rc == 0)
859        return &g_cam_ctrl.camera[0];
860    else
861        return NULL;
862}
863
864/* camera ops v-table */
865static mm_camera_ops_t mm_camera_ops = {
866    .sync = mm_camera_intf_sync,
867    .is_event_supported = mm_camera_intf_is_event_supported,
868    .register_event_notify = mm_camera_intf_register_event_notify,
869    .qbuf = mm_camera_intf_qbuf,
870    .camera_close = mm_camera_intf_close,
871    .query_2nd_sensor_info = mm_camera_intf_query_2nd_sensor_info,
872    .is_parm_supported = mm_camera_intf_is_parm_supported,
873    .set_parm = mm_camera_intf_set_parm,
874    .get_parm = mm_camera_intf_get_parm,
875    .ch_acquire = mm_camera_intf_add_channel,
876    .ch_release = mm_camera_intf_del_channel,
877    .add_stream = mm_camera_intf_add_stream,
878    .del_stream = mm_camera_intf_del_stream,
879    .config_stream = mm_camera_intf_config_stream,
880    .init_stream_bundle = mm_camera_intf_bundle_streams,
881    .destroy_stream_bundle = mm_camera_intf_destroy_bundle,
882    .start_streams = mm_camera_intf_start_streams,
883    .stop_streams = mm_camera_intf_stop_streams,
884    .async_teardown_streams = mm_camera_intf_async_teardown_streams,
885    .request_super_buf = mm_camera_intf_request_super_buf,
886    .cancel_super_buf_request = mm_camera_intf_cancel_super_buf_request,
887    .start_focus = mm_camera_intf_start_focus,
888    .abort_focus = mm_camera_intf_abort_focus,
889    .prepare_snapshot = mm_camera_intf_prepare_snapshot,
890    .set_stream_parm = mm_camera_intf_set_stream_parm,
891    .get_stream_parm = mm_camera_intf_get_stream_parm
892};
893
894/* open camera. */
895mm_camera_vtbl_t * camera_open(uint8_t camera_idx,
896                               mm_camear_mem_vtbl_t *mem_vtbl)
897{
898    int32_t rc = 0;
899    mm_camera_obj_t* cam_obj = NULL;
900
901    CDBG("%s: E camera_idx = %d\n", __func__,camera_idx);
902    if (MSM_MAX_CAMERA_SENSORS <= camera_idx) {
903        CDBG_ERROR("%s: Invalid camera_idx (%d)", __func__, camera_idx);
904        return NULL;
905    }
906
907    pthread_mutex_lock(&g_intf_lock);
908    /* opened already */
909    if(NULL != g_cam_ctrl.cam_obj[camera_idx]) {
910        /* Add reference */
911        g_cam_ctrl.cam_obj[camera_idx]->ref_count++;
912        pthread_mutex_unlock(&g_intf_lock);
913        CDBG("%s:  opened alreadyn", __func__);
914        return &cam_obj->vtbl;
915    }
916
917    cam_obj = (mm_camera_obj_t *)malloc(sizeof(mm_camera_obj_t));
918    if(NULL == cam_obj) {
919        pthread_mutex_unlock(&g_intf_lock);
920        CDBG("%s:  no mem", __func__);
921        return NULL;
922    }
923
924    /* initialize camera obj */
925    memset(cam_obj, 0, sizeof(mm_camera_obj_t));
926    cam_obj->ctrl_fd = -1;
927    cam_obj->ds_fd = -1;
928    cam_obj->ref_count++;
929    cam_obj->my_hdl = mm_camera_util_generate_handler(camera_idx);
930    cam_obj->vtbl.camera_handle = cam_obj->my_hdl; /* set handler */
931    cam_obj->vtbl.camera_info = &g_cam_ctrl.camera[camera_idx];
932    cam_obj->vtbl.ops = &mm_camera_ops;
933    cam_obj->mem_vtbl = mem_vtbl; /* save mem_vtbl */
934    pthread_mutex_init(&cam_obj->cam_lock, NULL);
935
936    rc = mm_camera_open(cam_obj);
937    if(rc != 0) {
938        CDBG_ERROR("%s: mm_camera_open err = %d", __func__, rc);
939        pthread_mutex_destroy(&cam_obj->cam_lock);
940        g_cam_ctrl.cam_obj[camera_idx] = NULL;
941        free(cam_obj);
942        cam_obj = NULL;
943        pthread_mutex_unlock(&g_intf_lock);
944        return NULL;
945    }else{
946        CDBG("%s: Open succeded\n", __func__);
947        g_cam_ctrl.cam_obj[camera_idx] = cam_obj;
948        pthread_mutex_unlock(&g_intf_lock);
949        return &cam_obj->vtbl;
950    }
951}
952