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 <cutils/properties.h>
31#include <fcntl.h>
32#include <dlfcn.h>
33#include <linux/msm_ion.h>
34#include <sys/mman.h>
35
36#include "mm_qcamera_dbg.h"
37#include "mm_qcamera_app.h"
38
39static pthread_mutex_t app_mutex;
40static int thread_status = 0;
41static pthread_cond_t app_cond_v;
42
43#define MM_QCAMERA_APP_NANOSEC_SCALE 1000000000
44
45int mm_camera_app_timedwait(uint8_t seconds)
46{
47    int rc = 0;
48    pthread_mutex_lock(&app_mutex);
49    if(FALSE == thread_status) {
50        struct timespec tw;
51        memset(&tw, 0, sizeof tw);
52        tw.tv_sec = 0;
53        tw.tv_nsec = time(0) + seconds * MM_QCAMERA_APP_NANOSEC_SCALE;
54
55        rc = pthread_cond_timedwait(&app_cond_v, &app_mutex,&tw);
56        thread_status = FALSE;
57    }
58    pthread_mutex_unlock(&app_mutex);
59    return rc;
60}
61
62int mm_camera_app_wait()
63{
64    int rc = 0;
65    pthread_mutex_lock(&app_mutex);
66    if(FALSE == thread_status){
67        pthread_cond_wait(&app_cond_v, &app_mutex);
68        thread_status = FALSE;
69    }
70    pthread_mutex_unlock(&app_mutex);
71    return rc;
72}
73
74void mm_camera_app_done()
75{
76  pthread_mutex_lock(&app_mutex);
77  thread_status = TRUE;
78  pthread_cond_signal(&app_cond_v);
79  pthread_mutex_unlock(&app_mutex);
80}
81
82int mm_app_load_hal(mm_camera_app_t *my_cam_app)
83{
84    memset(&my_cam_app->hal_lib, 0, sizeof(hal_interface_lib_t));
85    my_cam_app->hal_lib.ptr = dlopen("libmmcamera_interface.so", RTLD_NOW);
86    my_cam_app->hal_lib.ptr_jpeg = dlopen("libmmjpeg_interface.so", RTLD_NOW);
87    if (!my_cam_app->hal_lib.ptr || !my_cam_app->hal_lib.ptr_jpeg) {
88        CDBG_ERROR("%s Error opening HAL library %s\n", __func__, dlerror());
89        return -MM_CAMERA_E_GENERAL;
90    }
91    *(void **)&(my_cam_app->hal_lib.get_num_of_cameras) =
92        dlsym(my_cam_app->hal_lib.ptr, "get_num_of_cameras");
93    *(void **)&(my_cam_app->hal_lib.mm_camera_open) =
94        dlsym(my_cam_app->hal_lib.ptr, "camera_open");
95    *(void **)&(my_cam_app->hal_lib.jpeg_open) =
96        dlsym(my_cam_app->hal_lib.ptr_jpeg, "jpeg_open");
97
98    if (my_cam_app->hal_lib.get_num_of_cameras == NULL ||
99        my_cam_app->hal_lib.mm_camera_open == NULL ||
100        my_cam_app->hal_lib.jpeg_open == NULL) {
101        CDBG_ERROR("%s Error loading HAL sym %s\n", __func__, dlerror());
102        return -MM_CAMERA_E_GENERAL;
103    }
104
105    my_cam_app->num_cameras = my_cam_app->hal_lib.get_num_of_cameras();
106    CDBG("%s: num_cameras = %d\n", __func__, my_cam_app->num_cameras);
107
108    return MM_CAMERA_OK;
109}
110
111int mm_app_allocate_ion_memory(mm_camera_app_buf_t *buf, int ion_type)
112{
113    int rc = MM_CAMERA_OK;
114    struct ion_handle_data handle_data;
115    struct ion_allocation_data alloc;
116    struct ion_fd_data ion_info_fd;
117    int main_ion_fd = 0;
118    void *data = NULL;
119
120    main_ion_fd = open("/dev/ion", O_RDONLY);
121    if (main_ion_fd <= 0) {
122        CDBG_ERROR("Ion dev open failed %s\n", strerror(errno));
123        goto ION_OPEN_FAILED;
124    }
125
126    memset(&alloc, 0, sizeof(alloc));
127    alloc.len = buf->mem_info.size;
128    /* to make it page size aligned */
129    alloc.len = (alloc.len + 4095) & (~4095);
130    alloc.align = 4096;
131    alloc.flags = ION_FLAG_CACHED;
132    alloc.heap_mask = ion_type;
133    rc = ioctl(main_ion_fd, ION_IOC_ALLOC, &alloc);
134    if (rc < 0) {
135        CDBG_ERROR("ION allocation failed\n");
136        goto ION_ALLOC_FAILED;
137    }
138
139    memset(&ion_info_fd, 0, sizeof(ion_info_fd));
140    ion_info_fd.handle = alloc.handle;
141    rc = ioctl(main_ion_fd, ION_IOC_SHARE, &ion_info_fd);
142    if (rc < 0) {
143        CDBG_ERROR("ION map failed %s\n", strerror(errno));
144        goto ION_MAP_FAILED;
145    }
146
147    data = mmap(NULL,
148                alloc.len,
149                PROT_READ  | PROT_WRITE,
150                MAP_SHARED,
151                ion_info_fd.fd,
152                0);
153
154    if (data == MAP_FAILED) {
155        CDBG_ERROR("ION_MMAP_FAILED: %s (%d)\n", strerror(errno), errno);
156        goto ION_MAP_FAILED;
157    }
158    buf->mem_info.main_ion_fd = main_ion_fd;
159    buf->mem_info.fd = ion_info_fd.fd;
160    buf->mem_info.handle = ion_info_fd.handle;
161    buf->mem_info.size = alloc.len;
162    buf->mem_info.data = data;
163    return MM_CAMERA_OK;
164
165ION_MAP_FAILED:
166    memset(&handle_data, 0, sizeof(handle_data));
167    handle_data.handle = ion_info_fd.handle;
168    ioctl(main_ion_fd, ION_IOC_FREE, &handle_data);
169ION_ALLOC_FAILED:
170    close(main_ion_fd);
171ION_OPEN_FAILED:
172    return -MM_CAMERA_E_GENERAL;
173}
174
175int mm_app_deallocate_ion_memory(mm_camera_app_buf_t *buf)
176{
177  struct ion_handle_data handle_data;
178  int rc = 0;
179
180  rc = munmap(buf->mem_info.data, buf->mem_info.size);
181
182  if (buf->mem_info.fd > 0) {
183      close(buf->mem_info.fd);
184      buf->mem_info.fd = 0;
185  }
186
187  if (buf->mem_info.main_ion_fd > 0) {
188      memset(&handle_data, 0, sizeof(handle_data));
189      handle_data.handle = buf->mem_info.handle;
190      ioctl(buf->mem_info.main_ion_fd, ION_IOC_FREE, &handle_data);
191      close(buf->mem_info.main_ion_fd);
192      buf->mem_info.main_ion_fd = 0;
193  }
194  return rc;
195}
196
197/* cmd = ION_IOC_CLEAN_CACHES, ION_IOC_INV_CACHES, ION_IOC_CLEAN_INV_CACHES */
198int mm_app_cache_ops(mm_camera_app_meminfo_t *mem_info,
199                     unsigned int cmd)
200{
201    struct ion_flush_data cache_inv_data;
202    struct ion_custom_data custom_data;
203    int ret = MM_CAMERA_OK;
204
205#ifdef USE_ION
206    if (NULL == mem_info) {
207        CDBG_ERROR("%s: mem_info is NULL, return here", __func__);
208        return -MM_CAMERA_E_GENERAL;
209    }
210
211    memset(&cache_inv_data, 0, sizeof(cache_inv_data));
212    memset(&custom_data, 0, sizeof(custom_data));
213    cache_inv_data.vaddr = mem_info->data;
214    cache_inv_data.fd = mem_info->fd;
215    cache_inv_data.handle = mem_info->handle;
216    cache_inv_data.length = mem_info->size;
217    custom_data.cmd = cmd;
218    custom_data.arg = (unsigned long)&cache_inv_data;
219
220    CDBG("addr = %p, fd = %d, handle = %p length = %d, ION Fd = %d",
221         cache_inv_data.vaddr, cache_inv_data.fd,
222         cache_inv_data.handle, cache_inv_data.length,
223         mem_info->main_ion_fd);
224    if(mem_info->main_ion_fd > 0) {
225        if(ioctl(mem_info->main_ion_fd, ION_IOC_CUSTOM, &custom_data) < 0) {
226            ALOGE("%s: Cache Invalidate failed\n", __func__);
227            ret = -MM_CAMERA_E_GENERAL;
228        }
229    }
230#endif
231
232    return ret;
233}
234
235void mm_app_dump_frame(mm_camera_buf_def_t *frame,
236                       char *name,
237                       char *ext,
238                       int frame_idx)
239{
240    char file_name[64];
241    int file_fd;
242    int i;
243    if ( frame != NULL) {
244        snprintf(file_name, sizeof(file_name), "/data/%s_%d.%s", name, frame_idx, ext);
245        file_fd = open(file_name, O_RDWR | O_CREAT, 0777);
246        if (file_fd < 0) {
247            CDBG_ERROR("%s: cannot open file %s \n", __func__, file_name);
248        } else {
249            for (i = 0; i < frame->num_planes; i++) {
250                write(file_fd,
251                      (uint8_t *)frame->buffer + frame->planes[i].data_offset,
252                      frame->planes[i].length);
253            }
254
255            close(file_fd);
256            CDBG("dump %s", file_name);
257        }
258    }
259}
260
261void mm_app_dump_jpeg_frame(const void * data, uint32_t size, char* name, char* ext, int index)
262{
263    char buf[32];
264    int file_fd;
265    if ( data != NULL) {
266        snprintf(buf, sizeof(buf), "/data/%s_%d.%s", name, index, ext);
267        CDBG("%s: %s size =%d, jobId=%d", __func__, buf, size, index);
268        file_fd = open(buf, O_RDWR | O_CREAT, 0777);
269        write(file_fd, data, size);
270        close(file_fd);
271    }
272}
273
274int mm_app_alloc_bufs(mm_camera_app_buf_t* app_bufs,
275                      cam_frame_len_offset_t *frame_offset_info,
276                      uint8_t num_bufs,
277                      uint8_t is_streambuf)
278{
279    int i, j;
280    int ion_type = 0x1 << CAMERA_ION_FALLBACK_HEAP_ID;
281
282    if (is_streambuf) {
283        ion_type |= 0x1 << CAMERA_ION_HEAP_ID;
284    }
285
286    for (i = 0; i < num_bufs ; i++) {
287        app_bufs[i].mem_info.size = frame_offset_info->frame_len;
288        mm_app_allocate_ion_memory(&app_bufs[i], ion_type);
289
290        app_bufs[i].buf.buf_idx = i;
291        app_bufs[i].buf.num_planes = frame_offset_info->num_planes;
292        app_bufs[i].buf.fd = app_bufs[i].mem_info.fd;
293        app_bufs[i].buf.frame_len = app_bufs[i].mem_info.size;
294        app_bufs[i].buf.buffer = app_bufs[i].mem_info.data;
295        app_bufs[i].buf.mem_info = (void *)&app_bufs[i].mem_info;
296
297        /* Plane 0 needs to be set seperately. Set other planes
298             * in a loop. */
299        app_bufs[i].buf.planes[0].length = frame_offset_info->mp[0].len;
300        app_bufs[i].buf.planes[0].m.userptr = app_bufs[i].buf.fd;
301        app_bufs[i].buf.planes[0].data_offset = frame_offset_info->mp[0].offset;
302        app_bufs[i].buf.planes[0].reserved[0] = 0;
303        for (j = 1; j < frame_offset_info->num_planes; j++) {
304            app_bufs[i].buf.planes[j].length = frame_offset_info->mp[j].len;
305            app_bufs[i].buf.planes[j].m.userptr = app_bufs[i].buf.fd;
306            app_bufs[i].buf.planes[j].data_offset = frame_offset_info->mp[j].offset;
307            app_bufs[i].buf.planes[j].reserved[0] =
308                app_bufs[i].buf.planes[j-1].reserved[0] +
309                app_bufs[i].buf.planes[j-1].length;
310        }
311    }
312    CDBG("%s: X", __func__);
313    return MM_CAMERA_OK;
314}
315
316int mm_app_release_bufs(uint8_t num_bufs,
317                        mm_camera_app_buf_t* app_bufs)
318{
319    int i, rc = MM_CAMERA_OK;
320
321    CDBG("%s: E", __func__);
322
323    for (i = 0; i < num_bufs; i++) {
324        rc = mm_app_deallocate_ion_memory(&app_bufs[i]);
325    }
326    memset(app_bufs, 0, num_bufs * sizeof(mm_camera_app_buf_t));
327    CDBG("%s: X", __func__);
328    return rc;
329}
330
331int mm_app_stream_initbuf(cam_frame_len_offset_t *frame_offset_info,
332                          uint8_t *num_bufs,
333                          uint8_t **initial_reg_flag,
334                          mm_camera_buf_def_t **bufs,
335                          mm_camera_map_unmap_ops_tbl_t *ops_tbl,
336                          void *user_data)
337{
338    mm_camera_stream_t *stream = (mm_camera_stream_t *)user_data;
339    mm_camera_buf_def_t *pBufs = NULL;
340    uint8_t *reg_flags = NULL;
341    int i, rc;
342
343    stream->offset = *frame_offset_info;
344    CDBG("%s: alloc buf for stream_id %d, len=%d",
345         __func__, stream->s_id, frame_offset_info->frame_len);
346
347    pBufs = (mm_camera_buf_def_t *)malloc(sizeof(mm_camera_buf_def_t) * stream->num_of_bufs);
348    reg_flags = (uint8_t *)malloc(sizeof(uint8_t) * stream->num_of_bufs);
349    if (pBufs == NULL || reg_flags == NULL) {
350        CDBG_ERROR("%s: No mem for bufs", __func__);
351        if (pBufs != NULL) {
352            free(pBufs);
353        }
354        if (reg_flags != NULL) {
355            free(reg_flags);
356        }
357        return -1;
358    }
359
360    rc = mm_app_alloc_bufs(&stream->s_bufs[0],
361                           frame_offset_info,
362                           stream->num_of_bufs,
363                           1);
364
365    if (rc != MM_CAMERA_OK) {
366        CDBG_ERROR("%s: mm_stream_alloc_bufs err = %d", __func__, rc);
367        free(pBufs);
368        free(reg_flags);
369        return rc;
370    }
371
372    for (i = 0; i < stream->num_of_bufs; i++) {
373        /* mapping stream bufs first */
374        pBufs[i] = stream->s_bufs[i].buf;
375        reg_flags[i] = 1;
376        rc = ops_tbl->map_ops(pBufs[i].buf_idx,
377                              -1,
378                              pBufs[i].fd,
379                              pBufs[i].frame_len,
380                              ops_tbl->userdata);
381        if (rc != MM_CAMERA_OK) {
382            CDBG_ERROR("%s: mapping buf[%d] err = %d", __func__, i, rc);
383            break;
384        }
385    }
386
387    if (rc != MM_CAMERA_OK) {
388        int j;
389        for (j=0; j>i; j++) {
390            ops_tbl->unmap_ops(pBufs[j].buf_idx, -1, ops_tbl->userdata);
391        }
392        mm_app_release_bufs(stream->num_of_bufs, &stream->s_bufs[0]);
393        free(pBufs);
394        free(reg_flags);
395        return rc;
396    }
397
398    *num_bufs = stream->num_of_bufs;
399    *bufs = pBufs;
400    *initial_reg_flag = reg_flags;
401
402    CDBG("%s: X",__func__);
403    return rc;
404}
405
406int32_t mm_app_stream_deinitbuf(mm_camera_map_unmap_ops_tbl_t *ops_tbl,
407                                void *user_data)
408{
409    mm_camera_stream_t *stream = (mm_camera_stream_t *)user_data;
410    int i;
411
412    for (i = 0; i < stream->num_of_bufs ; i++) {
413        /* mapping stream bufs first */
414        ops_tbl->unmap_ops(stream->s_bufs[i].buf.buf_idx, -1, ops_tbl->userdata);
415    }
416
417    mm_app_release_bufs(stream->num_of_bufs, &stream->s_bufs[0]);
418
419    CDBG("%s: X",__func__);
420    return 0;
421}
422
423int32_t mm_app_stream_clean_invalidate_buf(int index, void *user_data)
424{
425    mm_camera_stream_t *stream = (mm_camera_stream_t *)user_data;
426    return mm_app_cache_ops(&stream->s_bufs[index].mem_info,
427      ION_IOC_CLEAN_INV_CACHES);
428}
429
430int32_t mm_app_stream_invalidate_buf(int index, void *user_data)
431{
432    mm_camera_stream_t *stream = (mm_camera_stream_t *)user_data;
433    return mm_app_cache_ops(&stream->s_bufs[index].mem_info, ION_IOC_INV_CACHES);
434}
435
436static void notify_evt_cb(uint32_t camera_handle,
437                          mm_camera_event_t *evt,
438                          void *user_data)
439{
440    mm_camera_test_obj_t *test_obj =
441        (mm_camera_test_obj_t *)user_data;
442    if (test_obj == NULL || test_obj->cam->camera_handle != camera_handle) {
443        CDBG_ERROR("%s: Not a valid test obj", __func__);
444        return;
445    }
446
447    CDBG("%s:E evt = %d", __func__, evt->server_event_type);
448    switch (evt->server_event_type) {
449       case CAM_EVENT_TYPE_AUTO_FOCUS_DONE:
450           CDBG("%s: rcvd auto focus done evt", __func__);
451           break;
452       case CAM_EVENT_TYPE_ZOOM_DONE:
453           CDBG("%s: rcvd zoom done evt", __func__);
454           break;
455       default:
456           break;
457    }
458
459    CDBG("%s:X", __func__);
460}
461
462int mm_app_open(mm_camera_app_t *cam_app,
463                uint8_t cam_id,
464                mm_camera_test_obj_t *test_obj)
465{
466    int32_t rc;
467    cam_frame_len_offset_t offset_info;
468
469    CDBG("%s:BEGIN\n", __func__);
470
471    test_obj->cam = cam_app->hal_lib.mm_camera_open(cam_id);
472    if(test_obj->cam == NULL) {
473        CDBG_ERROR("%s:dev open error\n", __func__);
474        return -MM_CAMERA_E_GENERAL;
475    }
476
477    CDBG("Open Camera id = %d handle = %d", cam_id, test_obj->cam->camera_handle);
478
479    /* alloc ion mem for capability buf */
480    memset(&offset_info, 0, sizeof(offset_info));
481    offset_info.frame_len = sizeof(cam_capability_t);
482    rc = mm_app_alloc_bufs(&test_obj->cap_buf,
483                           &offset_info,
484                           1,
485                           0);
486    if (rc != MM_CAMERA_OK) {
487        CDBG_ERROR("%s:alloc buf for capability error\n", __func__);
488        goto error_after_cam_open;
489    }
490
491    /* mapping capability buf */
492    rc = test_obj->cam->ops->map_buf(test_obj->cam->camera_handle,
493                                     CAM_MAPPING_BUF_TYPE_CAPABILITY,
494                                     test_obj->cap_buf.mem_info.fd,
495                                     test_obj->cap_buf.mem_info.size);
496    if (rc != MM_CAMERA_OK) {
497        CDBG_ERROR("%s:map for capability error\n", __func__);
498        goto error_after_cap_buf_alloc;
499    }
500
501    /* alloc ion mem for getparm buf */
502    memset(&offset_info, 0, sizeof(offset_info));
503    offset_info.frame_len = sizeof(parm_buffer_t);
504    rc = mm_app_alloc_bufs(&test_obj->parm_buf,
505                           &offset_info,
506                           1,
507                           0);
508    if (rc != MM_CAMERA_OK) {
509        CDBG_ERROR("%s:alloc buf for getparm_buf error\n", __func__);
510        goto error_after_cap_buf_map;
511    }
512
513    /* mapping getparm buf */
514    rc = test_obj->cam->ops->map_buf(test_obj->cam->camera_handle,
515                                     CAM_MAPPING_BUF_TYPE_PARM_BUF,
516                                     test_obj->parm_buf.mem_info.fd,
517                                     test_obj->parm_buf.mem_info.size);
518    if (rc != MM_CAMERA_OK) {
519        CDBG_ERROR("%s:map getparm_buf error\n", __func__);
520        goto error_after_getparm_buf_alloc;
521    }
522
523    rc = test_obj->cam->ops->register_event_notify(test_obj->cam->camera_handle,
524                                                   notify_evt_cb,
525                                                   test_obj);
526    if (rc != MM_CAMERA_OK) {
527        CDBG_ERROR("%s: failed register_event_notify", __func__);
528        rc = -MM_CAMERA_E_GENERAL;
529        goto error_after_getparm_buf_map;
530    }
531
532    rc = test_obj->cam->ops->query_capability(test_obj->cam->camera_handle);
533    if (rc != MM_CAMERA_OK) {
534        CDBG_ERROR("%s: failed query_capability", __func__);
535        rc = -MM_CAMERA_E_GENERAL;
536        goto error_after_getparm_buf_map;
537    }
538
539    memset(&test_obj->jpeg_ops, 0, sizeof(mm_jpeg_ops_t));
540    test_obj->jpeg_hdl = cam_app->hal_lib.jpeg_open(&test_obj->jpeg_ops);
541    if (test_obj->jpeg_hdl == 0) {
542        CDBG_ERROR("%s: jpeg lib open err", __func__);
543        rc = -MM_CAMERA_E_GENERAL;
544        goto error_after_getparm_buf_map;
545    }
546
547    return rc;
548
549error_after_getparm_buf_map:
550    test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle,
551                                  CAM_MAPPING_BUF_TYPE_PARM_BUF);
552error_after_getparm_buf_alloc:
553    mm_app_release_bufs(1, &test_obj->parm_buf);
554error_after_cap_buf_map:
555    test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle,
556                                  CAM_MAPPING_BUF_TYPE_CAPABILITY);
557error_after_cap_buf_alloc:
558    mm_app_release_bufs(1, &test_obj->cap_buf);
559error_after_cam_open:
560    test_obj->cam->ops->close_camera(test_obj->cam->camera_handle);
561    test_obj->cam = NULL;
562    return rc;
563}
564
565int mm_app_close(mm_camera_test_obj_t *test_obj)
566{
567    uint32_t rc = MM_CAMERA_OK;
568
569    if (test_obj == NULL || test_obj->cam ==NULL) {
570        CDBG_ERROR("%s: cam not opened", __func__);
571        return -MM_CAMERA_E_GENERAL;
572    }
573
574    /* unmap capability buf */
575    rc = test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle,
576                                       CAM_MAPPING_BUF_TYPE_CAPABILITY);
577    if (rc != MM_CAMERA_OK) {
578        CDBG_ERROR("%s: unmap capability buf failed, rc=%d", __func__, rc);
579    }
580
581    /* unmap parm buf */
582    rc = test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle,
583                                       CAM_MAPPING_BUF_TYPE_PARM_BUF);
584    if (rc != MM_CAMERA_OK) {
585        CDBG_ERROR("%s: unmap setparm buf failed, rc=%d", __func__, rc);
586    }
587
588    rc = test_obj->cam->ops->close_camera(test_obj->cam->camera_handle);
589    if (rc != MM_CAMERA_OK) {
590        CDBG_ERROR("%s: close camera failed, rc=%d", __func__, rc);
591    }
592    test_obj->cam = NULL;
593
594    /* close jpeg client */
595    if (test_obj->jpeg_hdl && test_obj->jpeg_ops.close) {
596        rc = test_obj->jpeg_ops.close(test_obj->jpeg_hdl);
597        test_obj->jpeg_hdl = 0;
598        if (rc != MM_CAMERA_OK) {
599            CDBG_ERROR("%s: close jpeg failed, rc=%d", __func__, rc);
600        }
601    }
602
603    /* dealloc capability buf */
604    rc = mm_app_release_bufs(1, &test_obj->cap_buf);
605    if (rc != MM_CAMERA_OK) {
606        CDBG_ERROR("%s: release capability buf failed, rc=%d", __func__, rc);
607    }
608
609    /* dealloc parm buf */
610    rc = mm_app_release_bufs(1, &test_obj->parm_buf);
611    if (rc != MM_CAMERA_OK) {
612        CDBG_ERROR("%s: release setparm buf failed, rc=%d", __func__, rc);
613    }
614
615    return MM_CAMERA_OK;
616}
617
618mm_camera_channel_t * mm_app_add_channel(mm_camera_test_obj_t *test_obj,
619                                         mm_camera_channel_type_t ch_type,
620                                         mm_camera_channel_attr_t *attr,
621                                         mm_camera_buf_notify_t channel_cb,
622                                         void *userdata)
623{
624    uint32_t ch_id = 0;
625    mm_camera_channel_t *channel = NULL;
626
627    ch_id = test_obj->cam->ops->add_channel(test_obj->cam->camera_handle,
628                                            attr,
629                                            channel_cb,
630                                            userdata);
631    if (ch_id == 0) {
632        CDBG_ERROR("%s: add channel failed", __func__);
633        return NULL;
634    }
635    channel = &test_obj->channels[ch_type];
636    channel->ch_id = ch_id;
637    return channel;
638}
639
640int mm_app_del_channel(mm_camera_test_obj_t *test_obj,
641                       mm_camera_channel_t *channel)
642{
643    test_obj->cam->ops->delete_channel(test_obj->cam->camera_handle,
644                                       channel->ch_id);
645    memset(channel, 0, sizeof(mm_camera_channel_t));
646    return MM_CAMERA_OK;
647}
648
649mm_camera_stream_t * mm_app_add_stream(mm_camera_test_obj_t *test_obj,
650                                       mm_camera_channel_t *channel)
651{
652    mm_camera_stream_t *stream = NULL;
653    int rc = MM_CAMERA_OK;
654    cam_frame_len_offset_t offset_info;
655
656    stream = &(channel->streams[channel->num_streams++]);
657    stream->s_id = test_obj->cam->ops->add_stream(test_obj->cam->camera_handle,
658                                                  channel->ch_id);
659    if (stream->s_id == 0) {
660        CDBG_ERROR("%s: add stream failed", __func__);
661        return NULL;
662    }
663
664    /* alloc ion mem for stream_info buf */
665    memset(&offset_info, 0, sizeof(offset_info));
666    offset_info.frame_len = sizeof(cam_stream_info_t);
667    rc = mm_app_alloc_bufs(&stream->s_info_buf,
668                           &offset_info,
669                           1,
670                           0);
671    if (rc != MM_CAMERA_OK) {
672        CDBG_ERROR("%s:alloc buf for stream_info error\n", __func__);
673        test_obj->cam->ops->delete_stream(test_obj->cam->camera_handle,
674                                          channel->ch_id,
675                                          stream->s_id);
676        stream->s_id = 0;
677        return NULL;
678    }
679
680    /* mapping streaminfo buf */
681    rc = test_obj->cam->ops->map_stream_buf(test_obj->cam->camera_handle,
682                                            channel->ch_id,
683                                            stream->s_id,
684                                            CAM_MAPPING_BUF_TYPE_STREAM_INFO,
685                                            0,
686                                            -1,
687                                            stream->s_info_buf.mem_info.fd,
688                                            stream->s_info_buf.mem_info.size);
689    if (rc != MM_CAMERA_OK) {
690        CDBG_ERROR("%s:map setparm_buf error\n", __func__);
691        mm_app_deallocate_ion_memory(&stream->s_info_buf);
692        test_obj->cam->ops->delete_stream(test_obj->cam->camera_handle,
693                                          channel->ch_id,
694                                          stream->s_id);
695        stream->s_id = 0;
696        return NULL;
697    }
698
699    return stream;
700}
701
702int mm_app_del_stream(mm_camera_test_obj_t *test_obj,
703                      mm_camera_channel_t *channel,
704                      mm_camera_stream_t *stream)
705{
706    test_obj->cam->ops->unmap_stream_buf(test_obj->cam->camera_handle,
707                                         channel->ch_id,
708                                         stream->s_id,
709                                         CAM_MAPPING_BUF_TYPE_STREAM_INFO,
710                                         0,
711                                         -1);
712    mm_app_deallocate_ion_memory(&stream->s_info_buf);
713    test_obj->cam->ops->delete_stream(test_obj->cam->camera_handle,
714                                      channel->ch_id,
715                                      stream->s_id);
716    memset(stream, 0, sizeof(mm_camera_stream_t));
717    return MM_CAMERA_OK;
718}
719
720mm_camera_channel_t *mm_app_get_channel_by_type(mm_camera_test_obj_t *test_obj,
721                                                mm_camera_channel_type_t ch_type)
722{
723    return &test_obj->channels[ch_type];
724}
725
726int mm_app_config_stream(mm_camera_test_obj_t *test_obj,
727                         mm_camera_channel_t *channel,
728                         mm_camera_stream_t *stream,
729                         mm_camera_stream_config_t *config)
730{
731    return test_obj->cam->ops->config_stream(test_obj->cam->camera_handle,
732                                             channel->ch_id,
733                                             stream->s_id,
734                                             config);
735}
736
737int mm_app_start_channel(mm_camera_test_obj_t *test_obj,
738                         mm_camera_channel_t *channel)
739{
740    return test_obj->cam->ops->start_channel(test_obj->cam->camera_handle,
741                                             channel->ch_id);
742}
743
744int mm_app_stop_channel(mm_camera_test_obj_t *test_obj,
745                        mm_camera_channel_t *channel)
746{
747    return test_obj->cam->ops->stop_channel(test_obj->cam->camera_handle,
748                                            channel->ch_id);
749}
750
751int main(int argc, char **argv)
752{
753    int c;
754    int rc;
755    int run_tc = 0;
756    int run_dual_tc = 0;
757    mm_camera_app_t my_cam_app;
758
759    CDBG("\nCamera Test Application\n");
760
761    while ((c = getopt(argc, argv, "tdh")) != -1) {
762        switch (c) {
763           case 't':
764               run_tc = 1;
765               break;
766           case 'd':
767               run_dual_tc = 1;
768               break;
769           case 'h':
770           default:
771               printf("usage: %s [-t] [-d] \n", argv[0]);
772               printf("-t:   Unit test        \n");
773               printf("-d:   Dual camera test \n");
774               return 0;
775        }
776    }
777
778    memset(&my_cam_app, 0, sizeof(mm_camera_app_t));
779    if((mm_app_load_hal(&my_cam_app) != MM_CAMERA_OK)) {
780        CDBG_ERROR("%s:mm_app_init err\n", __func__);
781        return -1;
782    }
783
784    if(run_tc) {
785        printf("\tRunning unit test engine only\n");
786        rc = mm_app_unit_test_entry(&my_cam_app);
787        printf("\tUnit test engine. EXIT(%d)!!!\n", rc);
788        return rc;
789    }
790#if 0
791    if(run_dual_tc) {
792        printf("\tRunning Dual camera test engine only\n");
793        rc = mm_app_dual_test_entry(&my_cam_app);
794        printf("\t Dual camera engine. EXIT(%d)!!!\n", rc);
795        exit(rc);
796    }
797#endif
798    /* Clean up and exit. */
799    CDBG("Exiting test app\n");
800    return 0;
801}
802