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 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