mm_qcamera_app.c revision a1724bc599bec5b2fbe3f4a34d0eca2406ba4c5f
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 430static void notify_evt_cb(uint32_t camera_handle, 431 mm_camera_event_t *evt, 432 void *user_data) 433{ 434 mm_camera_test_obj_t *test_obj = 435 (mm_camera_test_obj_t *)user_data; 436 if (test_obj == NULL || test_obj->cam->camera_handle != camera_handle) { 437 CDBG_ERROR("%s: Not a valid test obj", __func__); 438 return; 439 } 440 441 CDBG("%s:E evt = %d", __func__, evt->server_event_type); 442 switch (evt->server_event_type) { 443 case CAM_EVENT_TYPE_AUTO_FOCUS_DONE: 444 CDBG("%s: rcvd auto focus done evt", __func__); 445 break; 446 case CAM_EVENT_TYPE_ZOOM_DONE: 447 CDBG("%s: rcvd zoom done evt", __func__); 448 break; 449 default: 450 break; 451 } 452 453 CDBG("%s:X", __func__); 454} 455 456int mm_app_open(mm_camera_app_t *cam_app, 457 uint8_t cam_id, 458 mm_camera_test_obj_t *test_obj) 459{ 460 int32_t rc; 461 cam_frame_len_offset_t offset_info; 462 463 CDBG("%s:BEGIN\n", __func__); 464 465 test_obj->cam = cam_app->hal_lib.mm_camera_open(cam_id); 466 if(test_obj->cam == NULL) { 467 CDBG_ERROR("%s:dev open error\n", __func__); 468 return -MM_CAMERA_E_GENERAL; 469 } 470 471 CDBG("Open Camera id = %d handle = %d", cam_id, test_obj->cam->camera_handle); 472 473 /* alloc ion mem for capability buf */ 474 memset(&offset_info, 0, sizeof(offset_info)); 475 offset_info.frame_len = sizeof(cam_capability_t); 476 rc = mm_app_alloc_bufs(&test_obj->cap_buf, 477 &offset_info, 478 1, 479 0); 480 if (rc != MM_CAMERA_OK) { 481 CDBG_ERROR("%s:alloc buf for capability error\n", __func__); 482 goto error_after_cam_open; 483 } 484 485 /* mapping capability buf */ 486 rc = test_obj->cam->ops->map_buf(test_obj->cam->camera_handle, 487 CAM_MAPPING_BUF_TYPE_CAPABILITY, 488 test_obj->cap_buf.mem_info.fd, 489 test_obj->cap_buf.mem_info.size); 490 if (rc != MM_CAMERA_OK) { 491 CDBG_ERROR("%s:map for capability error\n", __func__); 492 goto error_after_cap_buf_alloc; 493 } 494 495 /* alloc ion mem for getparm buf */ 496 memset(&offset_info, 0, sizeof(offset_info)); 497 offset_info.frame_len = sizeof(parm_buffer_t); 498 rc = mm_app_alloc_bufs(&test_obj->parm_buf, 499 &offset_info, 500 1, 501 0); 502 if (rc != MM_CAMERA_OK) { 503 CDBG_ERROR("%s:alloc buf for getparm_buf error\n", __func__); 504 goto error_after_cap_buf_map; 505 } 506 507 /* mapping getparm buf */ 508 rc = test_obj->cam->ops->map_buf(test_obj->cam->camera_handle, 509 CAM_MAPPING_BUF_TYPE_PARM_BUF, 510 test_obj->parm_buf.mem_info.fd, 511 test_obj->parm_buf.mem_info.size); 512 if (rc != MM_CAMERA_OK) { 513 CDBG_ERROR("%s:map getparm_buf error\n", __func__); 514 goto error_after_getparm_buf_alloc; 515 } 516 517 rc = test_obj->cam->ops->register_event_notify(test_obj->cam->camera_handle, 518 notify_evt_cb, 519 test_obj); 520 if (rc != MM_CAMERA_OK) { 521 CDBG_ERROR("%s: failed register_event_notify", __func__); 522 rc = -MM_CAMERA_E_GENERAL; 523 goto error_after_getparm_buf_map; 524 } 525 526 rc = test_obj->cam->ops->query_capability(test_obj->cam->camera_handle); 527 if (rc != MM_CAMERA_OK) { 528 CDBG_ERROR("%s: failed query_capability", __func__); 529 rc = -MM_CAMERA_E_GENERAL; 530 goto error_after_getparm_buf_map; 531 } 532 533 memset(&test_obj->jpeg_ops, 0, sizeof(mm_jpeg_ops_t)); 534 test_obj->jpeg_hdl = cam_app->hal_lib.jpeg_open(&test_obj->jpeg_ops); 535 if (test_obj->jpeg_hdl == 0) { 536 CDBG_ERROR("%s: jpeg lib open err", __func__); 537 rc = -MM_CAMERA_E_GENERAL; 538 goto error_after_getparm_buf_map; 539 } 540 541 return rc; 542 543error_after_getparm_buf_map: 544 test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle, 545 CAM_MAPPING_BUF_TYPE_PARM_BUF); 546error_after_getparm_buf_alloc: 547 mm_app_release_bufs(1, &test_obj->parm_buf); 548error_after_cap_buf_map: 549 test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle, 550 CAM_MAPPING_BUF_TYPE_CAPABILITY); 551error_after_cap_buf_alloc: 552 mm_app_release_bufs(1, &test_obj->cap_buf); 553error_after_cam_open: 554 test_obj->cam->ops->close_camera(test_obj->cam->camera_handle); 555 test_obj->cam = NULL; 556 return rc; 557} 558 559int mm_app_close(mm_camera_test_obj_t *test_obj) 560{ 561 uint32_t rc = MM_CAMERA_OK; 562 563 if (test_obj == NULL || test_obj->cam ==NULL) { 564 CDBG_ERROR("%s: cam not opened", __func__); 565 return -MM_CAMERA_E_GENERAL; 566 } 567 568 /* unmap capability buf */ 569 rc = test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle, 570 CAM_MAPPING_BUF_TYPE_CAPABILITY); 571 if (rc != MM_CAMERA_OK) { 572 CDBG_ERROR("%s: unmap capability buf failed, rc=%d", __func__, rc); 573 } 574 575 /* unmap parm buf */ 576 rc = test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle, 577 CAM_MAPPING_BUF_TYPE_PARM_BUF); 578 if (rc != MM_CAMERA_OK) { 579 CDBG_ERROR("%s: unmap setparm buf failed, rc=%d", __func__, rc); 580 } 581 582 rc = test_obj->cam->ops->close_camera(test_obj->cam->camera_handle); 583 if (rc != MM_CAMERA_OK) { 584 CDBG_ERROR("%s: close camera failed, rc=%d", __func__, rc); 585 } 586 test_obj->cam = NULL; 587 588 /* close jpeg client */ 589 if (test_obj->jpeg_hdl && test_obj->jpeg_ops.close) { 590 rc = test_obj->jpeg_ops.close(test_obj->jpeg_hdl); 591 test_obj->jpeg_hdl = 0; 592 if (rc != MM_CAMERA_OK) { 593 CDBG_ERROR("%s: close jpeg failed, rc=%d", __func__, rc); 594 } 595 } 596 597 /* dealloc capability buf */ 598 rc = mm_app_release_bufs(1, &test_obj->cap_buf); 599 if (rc != MM_CAMERA_OK) { 600 CDBG_ERROR("%s: release capability buf failed, rc=%d", __func__, rc); 601 } 602 603 /* dealloc parm buf */ 604 rc = mm_app_release_bufs(1, &test_obj->parm_buf); 605 if (rc != MM_CAMERA_OK) { 606 CDBG_ERROR("%s: release setparm buf failed, rc=%d", __func__, rc); 607 } 608 609 return MM_CAMERA_OK; 610} 611 612mm_camera_channel_t * mm_app_add_channel(mm_camera_test_obj_t *test_obj, 613 mm_camera_channel_type_t ch_type, 614 mm_camera_channel_attr_t *attr, 615 mm_camera_buf_notify_t channel_cb, 616 void *userdata) 617{ 618 uint32_t ch_id = 0; 619 mm_camera_channel_t *channel = NULL; 620 621 ch_id = test_obj->cam->ops->add_channel(test_obj->cam->camera_handle, 622 attr, 623 channel_cb, 624 userdata); 625 if (ch_id == 0) { 626 CDBG_ERROR("%s: add channel failed", __func__); 627 return NULL; 628 } 629 channel = &test_obj->channels[ch_type]; 630 channel->ch_id = ch_id; 631 return channel; 632} 633 634int mm_app_del_channel(mm_camera_test_obj_t *test_obj, 635 mm_camera_channel_t *channel) 636{ 637 test_obj->cam->ops->delete_channel(test_obj->cam->camera_handle, 638 channel->ch_id); 639 memset(channel, 0, sizeof(mm_camera_channel_t)); 640 return MM_CAMERA_OK; 641} 642 643mm_camera_stream_t * mm_app_add_stream(mm_camera_test_obj_t *test_obj, 644 mm_camera_channel_t *channel) 645{ 646 mm_camera_stream_t *stream = NULL; 647 int rc = MM_CAMERA_OK; 648 cam_frame_len_offset_t offset_info; 649 650 stream = &(channel->streams[channel->num_streams++]); 651 stream->s_id = test_obj->cam->ops->add_stream(test_obj->cam->camera_handle, 652 channel->ch_id); 653 if (stream->s_id == 0) { 654 CDBG_ERROR("%s: add stream failed", __func__); 655 return NULL; 656 } 657 658 /* alloc ion mem for stream_info buf */ 659 memset(&offset_info, 0, sizeof(offset_info)); 660 offset_info.frame_len = sizeof(cam_stream_info_t); 661 rc = mm_app_alloc_bufs(&stream->s_info_buf, 662 &offset_info, 663 1, 664 0); 665 if (rc != MM_CAMERA_OK) { 666 CDBG_ERROR("%s:alloc buf for stream_info error\n", __func__); 667 test_obj->cam->ops->delete_stream(test_obj->cam->camera_handle, 668 channel->ch_id, 669 stream->s_id); 670 stream->s_id = 0; 671 return NULL; 672 } 673 674 /* mapping streaminfo buf */ 675 rc = test_obj->cam->ops->map_stream_buf(test_obj->cam->camera_handle, 676 channel->ch_id, 677 stream->s_id, 678 CAM_MAPPING_BUF_TYPE_STREAM_INFO, 679 0, 680 -1, 681 stream->s_info_buf.mem_info.fd, 682 stream->s_info_buf.mem_info.size); 683 if (rc != MM_CAMERA_OK) { 684 CDBG_ERROR("%s:map setparm_buf error\n", __func__); 685 mm_app_deallocate_ion_memory(&stream->s_info_buf); 686 test_obj->cam->ops->delete_stream(test_obj->cam->camera_handle, 687 channel->ch_id, 688 stream->s_id); 689 stream->s_id = 0; 690 return NULL; 691 } 692 693 return stream; 694} 695 696int mm_app_del_stream(mm_camera_test_obj_t *test_obj, 697 mm_camera_channel_t *channel, 698 mm_camera_stream_t *stream) 699{ 700 test_obj->cam->ops->unmap_stream_buf(test_obj->cam->camera_handle, 701 channel->ch_id, 702 stream->s_id, 703 CAM_MAPPING_BUF_TYPE_STREAM_INFO, 704 0, 705 -1); 706 mm_app_deallocate_ion_memory(&stream->s_info_buf); 707 test_obj->cam->ops->delete_stream(test_obj->cam->camera_handle, 708 channel->ch_id, 709 stream->s_id); 710 memset(stream, 0, sizeof(mm_camera_stream_t)); 711 return MM_CAMERA_OK; 712} 713 714mm_camera_channel_t *mm_app_get_channel_by_type(mm_camera_test_obj_t *test_obj, 715 mm_camera_channel_type_t ch_type) 716{ 717 return &test_obj->channels[ch_type]; 718} 719 720int mm_app_config_stream(mm_camera_test_obj_t *test_obj, 721 mm_camera_channel_t *channel, 722 mm_camera_stream_t *stream, 723 mm_camera_stream_config_t *config) 724{ 725 return test_obj->cam->ops->config_stream(test_obj->cam->camera_handle, 726 channel->ch_id, 727 stream->s_id, 728 config); 729} 730 731int mm_app_start_channel(mm_camera_test_obj_t *test_obj, 732 mm_camera_channel_t *channel) 733{ 734 return test_obj->cam->ops->start_channel(test_obj->cam->camera_handle, 735 channel->ch_id); 736} 737 738int mm_app_stop_channel(mm_camera_test_obj_t *test_obj, 739 mm_camera_channel_t *channel) 740{ 741 return test_obj->cam->ops->stop_channel(test_obj->cam->camera_handle, 742 channel->ch_id); 743} 744 745int main(int argc, char **argv) 746{ 747 int c; 748 int rc; 749 int run_tc = 0; 750 int run_dual_tc = 0; 751 mm_camera_app_t my_cam_app; 752 753 CDBG("\nCamera Test Application\n"); 754 755 while ((c = getopt(argc, argv, "tdh")) != -1) { 756 switch (c) { 757 case 't': 758 run_tc = 1; 759 break; 760 case 'd': 761 run_dual_tc = 1; 762 break; 763 case 'h': 764 default: 765 printf("usage: %s [-t] [-d] \n", argv[0]); 766 printf("-t: Unit test \n"); 767 printf("-d: Dual camera test \n"); 768 return 0; 769 } 770 } 771 772 memset(&my_cam_app, 0, sizeof(mm_camera_app_t)); 773 if((mm_app_load_hal(&my_cam_app) != MM_CAMERA_OK)) { 774 CDBG_ERROR("%s:mm_app_init err\n", __func__); 775 return -1; 776 } 777 778 if(run_tc) { 779 printf("\tRunning unit test engine only\n"); 780 rc = mm_app_unit_test_entry(&my_cam_app); 781 printf("\tUnit test engine. EXIT(%d)!!!\n", rc); 782 return rc; 783 } 784#if 0 785 if(run_dual_tc) { 786 printf("\tRunning Dual camera test engine only\n"); 787 rc = mm_app_dual_test_entry(&my_cam_app); 788 printf("\t Dual camera engine. EXIT(%d)!!!\n", rc); 789 exit(rc); 790 } 791#endif 792 /* Clean up and exit. */ 793 CDBG("Exiting test app\n"); 794 return 0; 795} 796