Home | History | Annotate | Download | only in src
      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 
     39 static pthread_mutex_t app_mutex;
     40 static int thread_status = 0;
     41 static pthread_cond_t app_cond_v;
     42 
     43 #define MM_QCAMERA_APP_NANOSEC_SCALE 1000000000
     44 
     45 int 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 
     62 int 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 
     74 void 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 
     82 int 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 
    111 int 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_id_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 
    165 ION_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);
    169 ION_ALLOC_FAILED:
    170     close(main_ion_fd);
    171 ION_OPEN_FAILED:
    172     return -MM_CAMERA_E_GENERAL;
    173 }
    174 
    175 int 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 */
    198 int 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 
    235 void 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 
    261 void 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 
    274 int 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 
    316 int 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 
    331 int 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 
    406 int32_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 
    423 int32_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 
    430 int32_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 
    436 static 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 
    462 int 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 
    549 error_after_getparm_buf_map:
    550     test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle,
    551                                   CAM_MAPPING_BUF_TYPE_PARM_BUF);
    552 error_after_getparm_buf_alloc:
    553     mm_app_release_bufs(1, &test_obj->parm_buf);
    554 error_after_cap_buf_map:
    555     test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle,
    556                                   CAM_MAPPING_BUF_TYPE_CAPABILITY);
    557 error_after_cap_buf_alloc:
    558     mm_app_release_bufs(1, &test_obj->cap_buf);
    559 error_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 
    565 int 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 
    618 mm_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 
    640 int 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 
    649 mm_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 
    702 int 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 
    720 mm_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 
    726 int 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 
    737 int 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 
    744 int 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 
    751 int main(int argc, char **argv)
    752 {
    753     int c;
    754     int rc;
    755     int run_tc = 0;
    756 #if 0
    757     int run_dual_tc = 0;
    758 #endif
    759     mm_camera_app_t my_cam_app;
    760 
    761     CDBG("\nCamera Test Application\n");
    762 
    763     while ((c = getopt(argc, argv, "tdh")) != -1) {
    764         switch (c) {
    765            case 't':
    766                run_tc = 1;
    767                break;
    768            case 'd':
    769 #if 0
    770                run_dual_tc = 1;
    771 #endif
    772                break;
    773            case 'h':
    774            default:
    775                printf("usage: %s [-t] [-d] \n", argv[0]);
    776                printf("-t:   Unit test        \n");
    777                printf("-d:   Dual camera test \n");
    778                return 0;
    779         }
    780     }
    781 
    782     memset(&my_cam_app, 0, sizeof(mm_camera_app_t));
    783     if((mm_app_load_hal(&my_cam_app) != MM_CAMERA_OK)) {
    784         CDBG_ERROR("%s:mm_app_init err\n", __func__);
    785         return -1;
    786     }
    787 
    788     if(run_tc) {
    789         printf("\tRunning unit test engine only\n");
    790         rc = mm_app_unit_test_entry(&my_cam_app);
    791         printf("\tUnit test engine. EXIT(%d)!!!\n", rc);
    792         return rc;
    793     }
    794 #if 0
    795     if(run_dual_tc) {
    796         printf("\tRunning Dual camera test engine only\n");
    797         rc = mm_app_dual_test_entry(&my_cam_app);
    798         printf("\t Dual camera engine. EXIT(%d)!!!\n", rc);
    799         exit(rc);
    800     }
    801 #endif
    802     /* Clean up and exit. */
    803     CDBG("Exiting test app\n");
    804     return 0;
    805 }
    806