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 <pthread.h> 31 #include <errno.h> 32 #include <sys/ioctl.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <fcntl.h> 36 #include <poll.h> 37 38 #include <cam_semaphore.h> 39 40 #include "mm_camera_dbg.h" 41 #include "mm_camera_sock.h" 42 #include "mm_camera_interface.h" 43 #include "mm_camera.h" 44 45 #define SET_PARM_BIT32(parm, parm_arr) \ 46 (parm_arr[parm/32] |= (1<<(parm%32))) 47 48 #define GET_PARM_BIT32(parm, parm_arr) \ 49 ((parm_arr[parm/32]>>(parm%32))& 0x1) 50 51 /* internal function declare */ 52 int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj, 53 uint8_t reg_flag); 54 int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj, 55 mm_camera_event_t *event); 56 57 /*=========================================================================== 58 * FUNCTION : mm_camera_util_get_channel_by_handler 59 * 60 * DESCRIPTION: utility function to get a channel object from its handle 61 * 62 * PARAMETERS : 63 * @cam_obj: ptr to a camera object 64 * @handler: channel handle 65 * 66 * RETURN : ptr to a channel object. 67 * NULL if failed. 68 *==========================================================================*/ 69 mm_channel_t * mm_camera_util_get_channel_by_handler( 70 mm_camera_obj_t * cam_obj, 71 uint32_t handler) 72 { 73 int i; 74 mm_channel_t *ch_obj = NULL; 75 for(i = 0; i < MM_CAMERA_CHANNEL_MAX; i++) { 76 if (handler == cam_obj->ch[i].my_hdl) { 77 ch_obj = &cam_obj->ch[i]; 78 break; 79 } 80 } 81 return ch_obj; 82 } 83 84 /*=========================================================================== 85 * FUNCTION : mm_camera_util_chip_is_a_family 86 * 87 * DESCRIPTION: utility function to check if the host is A family chip 88 * 89 * PARAMETERS : 90 * 91 * RETURN : TRUE if A family. 92 * FALSE otherwise. 93 *==========================================================================*/ 94 uint8_t mm_camera_util_chip_is_a_family(void) 95 { 96 #ifdef USE_A_FAMILY 97 return TRUE; 98 #else 99 return FALSE; 100 #endif 101 } 102 103 /*=========================================================================== 104 * FUNCTION : mm_camera_dispatch_app_event 105 * 106 * DESCRIPTION: dispatch event to apps who regitster for event notify 107 * 108 * PARAMETERS : 109 * @cmd_cb: ptr to a struct storing event info 110 * @user_data: user data ptr (camera object) 111 * 112 * RETURN : none 113 *==========================================================================*/ 114 static void mm_camera_dispatch_app_event(mm_camera_cmdcb_t *cmd_cb, 115 void* user_data) 116 { 117 mm_camera_cmd_thread_name("mm_cam_event"); 118 int i; 119 mm_camera_event_t *event = &cmd_cb->u.evt; 120 mm_camera_obj_t * my_obj = (mm_camera_obj_t *)user_data; 121 if (NULL != my_obj) { 122 pthread_mutex_lock(&my_obj->cb_lock); 123 for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) { 124 if(my_obj->evt.evt[i].evt_cb) { 125 my_obj->evt.evt[i].evt_cb( 126 my_obj->my_hdl, 127 event, 128 my_obj->evt.evt[i].user_data); 129 } 130 } 131 pthread_mutex_unlock(&my_obj->cb_lock); 132 } 133 } 134 135 /*=========================================================================== 136 * FUNCTION : mm_camera_event_notify 137 * 138 * DESCRIPTION: callback to handle event notify from kernel. This call will 139 * dequeue event from kernel. 140 * 141 * PARAMETERS : 142 * @user_data: user data ptr (camera object) 143 * 144 * RETURN : none 145 *==========================================================================*/ 146 static void mm_camera_event_notify(void* user_data) 147 { 148 struct v4l2_event ev; 149 struct msm_v4l2_event_data *msm_evt = NULL; 150 int rc; 151 mm_camera_event_t evt; 152 memset(&evt, 0, sizeof(mm_camera_event_t)); 153 154 mm_camera_obj_t *my_obj = (mm_camera_obj_t*)user_data; 155 if (NULL != my_obj) { 156 /* read evt */ 157 memset(&ev, 0, sizeof(ev)); 158 rc = ioctl(my_obj->ctrl_fd, VIDIOC_DQEVENT, &ev); 159 160 if (rc >= 0 && ev.id == MSM_CAMERA_MSM_NOTIFY) { 161 msm_evt = (struct msm_v4l2_event_data *)ev.u.data; 162 switch (msm_evt->command) { 163 case CAM_EVENT_TYPE_DAEMON_PULL_REQ: 164 evt.server_event_type = CAM_EVENT_TYPE_DAEMON_PULL_REQ; 165 mm_camera_enqueue_evt(my_obj, &evt); 166 break; 167 case CAM_EVENT_TYPE_MAP_UNMAP_DONE: 168 pthread_mutex_lock(&my_obj->evt_lock); 169 my_obj->evt_rcvd.server_event_type = msm_evt->command; 170 my_obj->evt_rcvd.status = msm_evt->status; 171 pthread_cond_signal(&my_obj->evt_cond); 172 pthread_mutex_unlock(&my_obj->evt_lock); 173 break; 174 case MSM_CAMERA_PRIV_SHUTDOWN: 175 { 176 evt.server_event_type = CAM_EVENT_TYPE_DAEMON_DIED; 177 mm_camera_enqueue_evt(my_obj, &evt); 178 } 179 break; 180 default: 181 break; 182 } 183 } 184 } 185 } 186 187 /*=========================================================================== 188 * FUNCTION : mm_camera_enqueue_evt 189 * 190 * DESCRIPTION: enqueue received event into event queue to be processed by 191 * event thread. 192 * 193 * PARAMETERS : 194 * @my_obj : ptr to a camera object 195 * @event : event to be queued 196 * 197 * RETURN : int32_t type of status 198 * 0 -- success 199 * -1 -- failure 200 *==========================================================================*/ 201 int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj, 202 mm_camera_event_t *event) 203 { 204 int32_t rc = 0; 205 mm_camera_cmdcb_t *node = NULL; 206 207 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 208 if (NULL != node) { 209 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 210 node->cmd_type = MM_CAMERA_CMD_TYPE_EVT_CB; 211 node->u.evt = *event; 212 213 /* enqueue to evt cmd thread */ 214 cam_queue_enq(&(my_obj->evt_thread.cmd_queue), node); 215 /* wake up evt cmd thread */ 216 cam_sem_post(&(my_obj->evt_thread.cmd_sem)); 217 } else { 218 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 219 rc = -1; 220 } 221 222 return rc; 223 } 224 225 /*=========================================================================== 226 * FUNCTION : mm_camera_open 227 * 228 * DESCRIPTION: open a camera 229 * 230 * PARAMETERS : 231 * @my_obj : ptr to a camera object 232 * 233 * RETURN : int32_t type of status 234 * 0 -- success 235 * -1 -- failure 236 *==========================================================================*/ 237 int32_t mm_camera_open(mm_camera_obj_t *my_obj) 238 { 239 char dev_name[MM_CAMERA_DEV_NAME_LEN]; 240 int32_t rc = 0; 241 int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES; 242 uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP; 243 unsigned int cam_idx = 0; 244 245 CDBG("%s: begin\n", __func__); 246 247 if (NULL == my_obj) { 248 goto on_error; 249 } 250 snprintf(dev_name, sizeof(dev_name), "/dev/%s", 251 mm_camera_util_get_dev_name(my_obj->my_hdl)); 252 sscanf(dev_name, "/dev/video%u", &cam_idx); 253 CDBG_HIGH("%s: dev name = %s, cam_idx = %d", __func__, dev_name, cam_idx); 254 255 do{ 256 n_try--; 257 errno = 0; 258 my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK); 259 CDBG("%s: ctrl_fd = %d, errno == %d", __func__, my_obj->ctrl_fd, errno); 260 if((my_obj->ctrl_fd >= 0) || (errno != EIO && errno != ETIMEDOUT) || (n_try <= 0 )) { 261 CDBG_HIGH("%s: opened, break out while loop", __func__); 262 break; 263 } 264 ALOGE("%s:Failed with %s error, retrying after %d milli-seconds", 265 __func__, strerror(errno), sleep_msec); 266 usleep(sleep_msec * 1000); 267 }while (n_try > 0); 268 269 if (my_obj->ctrl_fd < 0) { 270 CDBG_ERROR("%s: cannot open control fd of '%s' (%s)\n", 271 __func__, dev_name, strerror(errno)); 272 rc = -1; 273 goto on_error; 274 } 275 276 /* open domain socket*/ 277 n_try = MM_CAMERA_DEV_OPEN_TRIES; 278 do { 279 n_try--; 280 my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP); 281 CDBG("%s: ds_fd = %d, errno = %d", __func__, my_obj->ds_fd, errno); 282 if((my_obj->ds_fd >= 0) || (n_try <= 0 )) { 283 CDBG("%s: opened, break out while loop", __func__); 284 break; 285 } 286 CDBG("%s:failed with I/O error retrying after %d milli-seconds", 287 __func__, sleep_msec); 288 usleep(sleep_msec * 1000); 289 } while (n_try > 0); 290 291 if (my_obj->ds_fd < 0) { 292 CDBG_ERROR("%s: cannot open domain socket fd of '%s'(%s)\n", 293 __func__, dev_name, strerror(errno)); 294 rc = -1; 295 goto on_error; 296 } 297 pthread_mutex_init(&my_obj->msg_lock, NULL); 298 299 pthread_mutex_init(&my_obj->cb_lock, NULL); 300 pthread_mutex_init(&my_obj->evt_lock, NULL); 301 pthread_cond_init(&my_obj->evt_cond, NULL); 302 303 CDBG("%s : Launch evt Thread in Cam Open",__func__); 304 mm_camera_cmd_thread_launch(&my_obj->evt_thread, 305 mm_camera_dispatch_app_event, 306 (void *)my_obj); 307 308 /* launch event poll thread 309 * we will add evt fd into event poll thread upon user first register for evt */ 310 CDBG("%s : Launch evt Poll Thread in Cam Open", __func__); 311 mm_camera_poll_thread_launch(&my_obj->evt_poll_thread, 312 MM_CAMERA_POLL_TYPE_EVT); 313 mm_camera_evt_sub(my_obj, TRUE); 314 315 CDBG("%s: end (rc = %d)\n", __func__, rc); 316 /* we do not need to unlock cam_lock here before return 317 * because for open, it's done within intf_lock */ 318 return rc; 319 320 on_error: 321 if (NULL == my_obj) { 322 CDBG_ERROR("%s: Invalid camera object\n", __func__); 323 rc = -1; 324 } else { 325 if (my_obj->ctrl_fd >= 0) { 326 close(my_obj->ctrl_fd); 327 my_obj->ctrl_fd = -1; 328 } 329 if (my_obj->ds_fd >= 0) { 330 mm_camera_socket_close(my_obj->ds_fd); 331 my_obj->ds_fd = -1; 332 } 333 } 334 335 /* we do not need to unlock cam_lock here before return 336 * because for open, it's done within intf_lock */ 337 return rc; 338 } 339 340 /*=========================================================================== 341 * FUNCTION : mm_camera_close 342 * 343 * DESCRIPTION: enqueue received event into event queue to be processed by 344 * event thread. 345 * 346 * PARAMETERS : 347 * @my_obj : ptr to a camera object 348 * @event : event to be queued 349 * 350 * RETURN : int32_t type of status 351 * 0 -- success 352 * -1 -- failure 353 *==========================================================================*/ 354 int32_t mm_camera_close(mm_camera_obj_t *my_obj) 355 { 356 CDBG("%s : unsubscribe evt", __func__); 357 mm_camera_evt_sub(my_obj, FALSE); 358 359 CDBG("%s : Close evt Poll Thread in Cam Close",__func__); 360 mm_camera_poll_thread_release(&my_obj->evt_poll_thread); 361 362 CDBG("%s : Close evt cmd Thread in Cam Close",__func__); 363 mm_camera_cmd_thread_release(&my_obj->evt_thread); 364 365 if(my_obj->ctrl_fd >= 0) { 366 close(my_obj->ctrl_fd); 367 my_obj->ctrl_fd = -1; 368 } 369 if(my_obj->ds_fd >= 0) { 370 mm_camera_socket_close(my_obj->ds_fd); 371 my_obj->ds_fd = -1; 372 } 373 pthread_mutex_destroy(&my_obj->msg_lock); 374 375 pthread_mutex_destroy(&my_obj->cb_lock); 376 pthread_mutex_destroy(&my_obj->evt_lock); 377 pthread_cond_destroy(&my_obj->evt_cond); 378 379 pthread_mutex_unlock(&my_obj->cam_lock); 380 return 0; 381 } 382 383 /*=========================================================================== 384 * FUNCTION : mm_camera_register_event_notify_internal 385 * 386 * DESCRIPTION: internal implementation for registering callback for event notify. 387 * 388 * PARAMETERS : 389 * @my_obj : ptr to a camera object 390 * @evt_cb : callback to be registered to handle event notify 391 * @user_data: user data ptr 392 * 393 * RETURN : int32_t type of status 394 * 0 -- success 395 * -1 -- failure 396 *==========================================================================*/ 397 int32_t mm_camera_register_event_notify_internal(mm_camera_obj_t *my_obj, 398 mm_camera_event_notify_t evt_cb, 399 void * user_data) 400 { 401 int i; 402 int rc = -1; 403 mm_camera_evt_obj_t *evt_array = NULL; 404 405 pthread_mutex_lock(&my_obj->cb_lock); 406 evt_array = &my_obj->evt; 407 if(evt_cb) { 408 /* this is reg case */ 409 for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) { 410 if(evt_array->evt[i].user_data == NULL) { 411 evt_array->evt[i].evt_cb = evt_cb; 412 evt_array->evt[i].user_data = user_data; 413 evt_array->reg_count++; 414 rc = 0; 415 break; 416 } 417 } 418 } else { 419 /* this is unreg case */ 420 for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) { 421 if(evt_array->evt[i].user_data == user_data) { 422 evt_array->evt[i].evt_cb = NULL; 423 evt_array->evt[i].user_data = NULL; 424 evt_array->reg_count--; 425 rc = 0; 426 break; 427 } 428 } 429 } 430 431 pthread_mutex_unlock(&my_obj->cb_lock); 432 return rc; 433 } 434 435 /*=========================================================================== 436 * FUNCTION : mm_camera_register_event_notify 437 * 438 * DESCRIPTION: registering a callback for event notify. 439 * 440 * PARAMETERS : 441 * @my_obj : ptr to a camera object 442 * @evt_cb : callback to be registered to handle event notify 443 * @user_data: user data ptr 444 * 445 * RETURN : int32_t type of status 446 * 0 -- success 447 * -1 -- failure 448 *==========================================================================*/ 449 int32_t mm_camera_register_event_notify(mm_camera_obj_t *my_obj, 450 mm_camera_event_notify_t evt_cb, 451 void * user_data) 452 { 453 int rc = -1; 454 rc = mm_camera_register_event_notify_internal(my_obj, 455 evt_cb, 456 user_data); 457 pthread_mutex_unlock(&my_obj->cam_lock); 458 return rc; 459 } 460 461 /*=========================================================================== 462 * FUNCTION : mm_camera_qbuf 463 * 464 * DESCRIPTION: enqueue buffer back to kernel 465 * 466 * PARAMETERS : 467 * @my_obj : camera object 468 * @ch_id : channel handle 469 * @buf : buf ptr to be enqueued 470 * 471 * RETURN : int32_t type of status 472 * 0 -- success 473 * -1 -- failure 474 *==========================================================================*/ 475 int32_t mm_camera_qbuf(mm_camera_obj_t *my_obj, 476 uint32_t ch_id, 477 mm_camera_buf_def_t *buf) 478 { 479 int rc = -1; 480 mm_channel_t * ch_obj = NULL; 481 ch_obj = mm_camera_util_get_channel_by_handler(my_obj, ch_id); 482 483 pthread_mutex_unlock(&my_obj->cam_lock); 484 485 /* we always assume qbuf will be done before channel/stream is fully stopped 486 * because qbuf is done within dataCB context 487 * in order to avoid deadlock, we are not locking ch_lock for qbuf */ 488 if (NULL != ch_obj) { 489 rc = mm_channel_qbuf(ch_obj, buf); 490 } 491 492 return rc; 493 } 494 495 /*=========================================================================== 496 * FUNCTION : mm_camera_query_capability 497 * 498 * DESCRIPTION: query camera capability 499 * 500 * PARAMETERS : 501 * @my_obj: camera object 502 * 503 * RETURN : int32_t type of status 504 * 0 -- success 505 * -1 -- failure 506 *==========================================================================*/ 507 int32_t mm_camera_query_capability(mm_camera_obj_t *my_obj) 508 { 509 int32_t rc = 0; 510 struct v4l2_capability cap; 511 512 /* get camera capabilities */ 513 memset(&cap, 0, sizeof(cap)); 514 rc = ioctl(my_obj->ctrl_fd, VIDIOC_QUERYCAP, &cap); 515 if (rc != 0) { 516 CDBG_ERROR("%s: cannot get camera capabilities, rc = %d\n", __func__, rc); 517 } 518 519 pthread_mutex_unlock(&my_obj->cam_lock); 520 return rc; 521 522 } 523 524 /*=========================================================================== 525 * FUNCTION : mm_camera_set_parms 526 * 527 * DESCRIPTION: set parameters per camera 528 * 529 * PARAMETERS : 530 * @my_obj : camera object 531 * @parms : ptr to a param struct to be set to server 532 * 533 * RETURN : int32_t type of status 534 * 0 -- success 535 * -1 -- failure 536 * NOTE : Assume the parms struct buf is already mapped to server via 537 * domain socket. Corresponding fields of parameters to be set 538 * are already filled in by upper layer caller. 539 *==========================================================================*/ 540 int32_t mm_camera_set_parms(mm_camera_obj_t *my_obj, 541 parm_buffer_t *parms) 542 { 543 int32_t rc = -1; 544 int32_t value = 0; 545 if (parms != NULL) { 546 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_PARM, &value); 547 } 548 pthread_mutex_unlock(&my_obj->cam_lock); 549 return rc; 550 } 551 552 /*=========================================================================== 553 * FUNCTION : mm_camera_get_parms 554 * 555 * DESCRIPTION: get parameters per camera 556 * 557 * PARAMETERS : 558 * @my_obj : camera object 559 * @parms : ptr to a param struct to be get from server 560 * 561 * RETURN : int32_t type of status 562 * 0 -- success 563 * -1 -- failure 564 * NOTE : Assume the parms struct buf is already mapped to server via 565 * domain socket. Parameters to be get from server are already 566 * filled in by upper layer caller. After this call, corresponding 567 * fields of requested parameters will be filled in by server with 568 * detailed information. 569 *==========================================================================*/ 570 int32_t mm_camera_get_parms(mm_camera_obj_t *my_obj, 571 parm_buffer_t *parms) 572 { 573 int32_t rc = -1; 574 int32_t value = 0; 575 if (parms != NULL) { 576 rc = mm_camera_util_g_ctrl(my_obj->ctrl_fd, CAM_PRIV_PARM, &value); 577 } 578 pthread_mutex_unlock(&my_obj->cam_lock); 579 return rc; 580 } 581 582 /*=========================================================================== 583 * FUNCTION : mm_camera_do_auto_focus 584 * 585 * DESCRIPTION: performing auto focus 586 * 587 * PARAMETERS : 588 * @camera_handle: camera handle 589 * 590 * RETURN : int32_t type of status 591 * 0 -- success 592 * -1 -- failure 593 * NOTE : if this call success, we will always assume there will 594 * be an auto_focus event following up. 595 *==========================================================================*/ 596 int32_t mm_camera_do_auto_focus(mm_camera_obj_t *my_obj) 597 { 598 int32_t rc = -1; 599 int32_t value = 0; 600 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_DO_AUTO_FOCUS, &value); 601 pthread_mutex_unlock(&my_obj->cam_lock); 602 return rc; 603 } 604 605 /*=========================================================================== 606 * FUNCTION : mm_camera_cancel_auto_focus 607 * 608 * DESCRIPTION: cancel auto focus 609 * 610 * PARAMETERS : 611 * @camera_handle: camera handle 612 * 613 * RETURN : int32_t type of status 614 * 0 -- success 615 * -1 -- failure 616 *==========================================================================*/ 617 int32_t mm_camera_cancel_auto_focus(mm_camera_obj_t *my_obj) 618 { 619 int32_t rc = -1; 620 int32_t value = 0; 621 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_CANCEL_AUTO_FOCUS, &value); 622 pthread_mutex_unlock(&my_obj->cam_lock); 623 return rc; 624 } 625 626 /*=========================================================================== 627 * FUNCTION : mm_camera_prepare_snapshot 628 * 629 * DESCRIPTION: prepare hardware for snapshot 630 * 631 * PARAMETERS : 632 * @my_obj : camera object 633 * @do_af_flag : flag indicating if AF is needed 634 * 635 * RETURN : int32_t type of status 636 * 0 -- success 637 * -1 -- failure 638 *==========================================================================*/ 639 int32_t mm_camera_prepare_snapshot(mm_camera_obj_t *my_obj, 640 int32_t do_af_flag) 641 { 642 int32_t rc = -1; 643 int32_t value = do_af_flag; 644 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_PREPARE_SNAPSHOT, &value); 645 pthread_mutex_unlock(&my_obj->cam_lock); 646 return rc; 647 } 648 649 /*=========================================================================== 650 * FUNCTION : mm_camera_start_zsl_snapshot 651 * 652 * DESCRIPTION: start zsl snapshot 653 * 654 * PARAMETERS : 655 * @my_obj : camera object 656 * 657 * RETURN : int32_t type of status 658 * 0 -- success 659 * -1 -- failure 660 *==========================================================================*/ 661 int32_t mm_camera_start_zsl_snapshot(mm_camera_obj_t *my_obj) 662 { 663 int32_t rc = -1; 664 int32_t value = 0; 665 666 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, 667 CAM_PRIV_START_ZSL_SNAPSHOT, &value); 668 return rc; 669 } 670 671 /*=========================================================================== 672 * FUNCTION : mm_camera_stop_zsl_snapshot 673 * 674 * DESCRIPTION: stop zsl capture 675 * 676 * PARAMETERS : 677 * @my_obj : camera object 678 * 679 * RETURN : int32_t type of status 680 * 0 -- success 681 * -1 -- failure 682 *==========================================================================*/ 683 int32_t mm_camera_stop_zsl_snapshot(mm_camera_obj_t *my_obj) 684 { 685 int32_t rc = -1; 686 int32_t value; 687 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, 688 CAM_PRIV_STOP_ZSL_SNAPSHOT, &value); 689 return rc; 690 } 691 692 /*=========================================================================== 693 * FUNCTION : mm_camera_add_channel 694 * 695 * DESCRIPTION: add a channel 696 * 697 * PARAMETERS : 698 * @my_obj : camera object 699 * @attr : bundle attribute of the channel if needed 700 * @channel_cb : callback function for bundle data notify 701 * @userdata : user data ptr 702 * 703 * RETURN : uint32_t type of channel handle 704 * 0 -- invalid channel handle, meaning the op failed 705 * >0 -- successfully added a channel with a valid handle 706 * NOTE : if no bundle data notify is needed, meaning each stream in the 707 * channel will have its own stream data notify callback, then 708 * attr, channel_cb, and userdata can be NULL. In this case, 709 * no matching logic will be performed in channel for the bundling. 710 *==========================================================================*/ 711 uint32_t mm_camera_add_channel(mm_camera_obj_t *my_obj, 712 mm_camera_channel_attr_t *attr, 713 mm_camera_buf_notify_t channel_cb, 714 void *userdata) 715 { 716 mm_channel_t *ch_obj = NULL; 717 uint8_t ch_idx = 0; 718 uint32_t ch_hdl = 0; 719 720 for(ch_idx = 0; ch_idx < MM_CAMERA_CHANNEL_MAX; ch_idx++) { 721 if (MM_CHANNEL_STATE_NOTUSED == my_obj->ch[ch_idx].state) { 722 ch_obj = &my_obj->ch[ch_idx]; 723 break; 724 } 725 } 726 727 if (NULL != ch_obj) { 728 /* initialize channel obj */ 729 memset(ch_obj, 0, sizeof(mm_channel_t)); 730 ch_hdl = mm_camera_util_generate_handler(ch_idx); 731 ch_obj->my_hdl = ch_hdl; 732 ch_obj->state = MM_CHANNEL_STATE_STOPPED; 733 ch_obj->cam_obj = my_obj; 734 pthread_mutex_init(&ch_obj->ch_lock, NULL); 735 mm_channel_init(ch_obj, attr, channel_cb, userdata); 736 } 737 738 pthread_mutex_unlock(&my_obj->cam_lock); 739 740 return ch_hdl; 741 } 742 743 /*=========================================================================== 744 * FUNCTION : mm_camera_del_channel 745 * 746 * DESCRIPTION: delete a channel by its handle 747 * 748 * PARAMETERS : 749 * @my_obj : camera object 750 * @ch_id : channel handle 751 * 752 * RETURN : int32_t type of status 753 * 0 -- success 754 * -1 -- failure 755 * NOTE : all streams in the channel should be stopped already before 756 * this channel can be deleted. 757 *==========================================================================*/ 758 int32_t mm_camera_del_channel(mm_camera_obj_t *my_obj, 759 uint32_t ch_id) 760 { 761 int32_t rc = -1; 762 mm_channel_t * ch_obj = 763 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 764 765 if (NULL != ch_obj) { 766 pthread_mutex_lock(&ch_obj->ch_lock); 767 pthread_mutex_unlock(&my_obj->cam_lock); 768 769 rc = mm_channel_fsm_fn(ch_obj, 770 MM_CHANNEL_EVT_DELETE, 771 NULL, 772 NULL); 773 774 pthread_mutex_destroy(&ch_obj->ch_lock); 775 memset(ch_obj, 0, sizeof(mm_channel_t)); 776 } else { 777 pthread_mutex_unlock(&my_obj->cam_lock); 778 } 779 return rc; 780 } 781 782 /*=========================================================================== 783 * FUNCTION : mm_camera_get_bundle_info 784 * 785 * DESCRIPTION: query bundle info of the channel 786 * 787 * PARAMETERS : 788 * @my_obj : camera object 789 * @ch_id : channel handle 790 * @bundle_info : bundle info to be filled in 791 * 792 * RETURN : int32_t type of status 793 * 0 -- success 794 * -1 -- failure 795 * NOTE : all streams in the channel should be stopped already before 796 * this channel can be deleted. 797 *==========================================================================*/ 798 int32_t mm_camera_get_bundle_info(mm_camera_obj_t *my_obj, 799 uint32_t ch_id, 800 cam_bundle_config_t *bundle_info) 801 { 802 int32_t rc = -1; 803 mm_channel_t * ch_obj = 804 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 805 806 if (NULL != ch_obj) { 807 pthread_mutex_lock(&ch_obj->ch_lock); 808 pthread_mutex_unlock(&my_obj->cam_lock); 809 810 rc = mm_channel_fsm_fn(ch_obj, 811 MM_CHANNEL_EVT_GET_BUNDLE_INFO, 812 (void *)bundle_info, 813 NULL); 814 } else { 815 pthread_mutex_unlock(&my_obj->cam_lock); 816 } 817 return rc; 818 } 819 820 /*=========================================================================== 821 * FUNCTION : mm_camera_add_stream 822 * 823 * DESCRIPTION: add a stream into a channel 824 * 825 * PARAMETERS : 826 * @my_obj : camera object 827 * @ch_id : channel handle 828 * 829 * RETURN : uint32_t type of stream handle 830 * 0 -- invalid stream handle, meaning the op failed 831 * >0 -- successfully added a stream with a valid handle 832 *==========================================================================*/ 833 uint32_t mm_camera_add_stream(mm_camera_obj_t *my_obj, 834 uint32_t ch_id) 835 { 836 uint32_t s_hdl = 0; 837 mm_channel_t * ch_obj = 838 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 839 840 if (NULL != ch_obj) { 841 pthread_mutex_lock(&ch_obj->ch_lock); 842 pthread_mutex_unlock(&my_obj->cam_lock); 843 844 mm_channel_fsm_fn(ch_obj, 845 MM_CHANNEL_EVT_ADD_STREAM, 846 NULL, 847 (void*)&s_hdl); 848 } else { 849 pthread_mutex_unlock(&my_obj->cam_lock); 850 } 851 852 return s_hdl; 853 } 854 855 /*=========================================================================== 856 * FUNCTION : mm_camera_del_stream 857 * 858 * DESCRIPTION: delete a stream by its handle 859 * 860 * PARAMETERS : 861 * @my_obj : camera object 862 * @ch_id : channel handle 863 * @stream_id : stream handle 864 * 865 * RETURN : int32_t type of status 866 * 0 -- success 867 * -1 -- failure 868 * NOTE : stream should be stopped already before it can be deleted. 869 *==========================================================================*/ 870 int32_t mm_camera_del_stream(mm_camera_obj_t *my_obj, 871 uint32_t ch_id, 872 uint32_t stream_id) 873 { 874 int32_t rc = -1; 875 mm_channel_t * ch_obj = 876 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 877 878 if (NULL != ch_obj) { 879 pthread_mutex_lock(&ch_obj->ch_lock); 880 pthread_mutex_unlock(&my_obj->cam_lock); 881 882 rc = mm_channel_fsm_fn(ch_obj, 883 MM_CHANNEL_EVT_DEL_STREAM, 884 (void*)stream_id, 885 NULL); 886 } else { 887 pthread_mutex_unlock(&my_obj->cam_lock); 888 } 889 890 return rc; 891 } 892 893 /*=========================================================================== 894 * FUNCTION : mm_camera_start_zsl_snapshot_ch 895 * 896 * DESCRIPTION: starts zsl snapshot for specific channel 897 * 898 * PARAMETERS : 899 * @my_obj : camera object 900 * @ch_id : channel handle 901 * 902 * RETURN : int32_t type of status 903 * 0 -- success 904 * -1 -- failure 905 *==========================================================================*/ 906 int32_t mm_camera_start_zsl_snapshot_ch(mm_camera_obj_t *my_obj, 907 uint32_t ch_id) 908 { 909 int32_t rc = -1; 910 mm_channel_t * ch_obj = 911 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 912 913 if (NULL != ch_obj) { 914 pthread_mutex_lock(&ch_obj->ch_lock); 915 pthread_mutex_unlock(&my_obj->cam_lock); 916 917 rc = mm_channel_fsm_fn(ch_obj, 918 MM_CHANNEL_EVT_START_ZSL_SNAPSHOT, 919 NULL, 920 NULL); 921 } else { 922 pthread_mutex_unlock(&my_obj->cam_lock); 923 } 924 925 return rc; 926 } 927 928 /*=========================================================================== 929 * FUNCTION : mm_camera_stop_zsl_snapshot_ch 930 * 931 * DESCRIPTION: stops zsl snapshot for specific channel 932 * 933 * PARAMETERS : 934 * @my_obj : camera object 935 * @ch_id : channel handle 936 * 937 * RETURN : int32_t type of status 938 * 0 -- success 939 * -1 -- failure 940 *==========================================================================*/ 941 int32_t mm_camera_stop_zsl_snapshot_ch(mm_camera_obj_t *my_obj, 942 uint32_t ch_id) 943 { 944 int32_t rc = -1; 945 mm_channel_t * ch_obj = 946 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 947 948 if (NULL != ch_obj) { 949 pthread_mutex_lock(&ch_obj->ch_lock); 950 pthread_mutex_unlock(&my_obj->cam_lock); 951 952 rc = mm_channel_fsm_fn(ch_obj, 953 MM_CHANNEL_EVT_STOP_ZSL_SNAPSHOT, 954 NULL, 955 NULL); 956 } else { 957 pthread_mutex_unlock(&my_obj->cam_lock); 958 } 959 960 return rc; 961 } 962 963 /*=========================================================================== 964 * FUNCTION : mm_camera_config_stream 965 * 966 * DESCRIPTION: configure a stream 967 * 968 * PARAMETERS : 969 * @my_obj : camera object 970 * @ch_id : channel handle 971 * @stream_id : stream handle 972 * @config : stream configuration 973 * 974 * RETURN : int32_t type of status 975 * 0 -- success 976 * -1 -- failure 977 *==========================================================================*/ 978 int32_t mm_camera_config_stream(mm_camera_obj_t *my_obj, 979 uint32_t ch_id, 980 uint32_t stream_id, 981 mm_camera_stream_config_t *config) 982 { 983 int32_t rc = -1; 984 mm_channel_t * ch_obj = 985 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 986 mm_evt_paylod_config_stream_t payload; 987 988 if (NULL != ch_obj) { 989 pthread_mutex_lock(&ch_obj->ch_lock); 990 pthread_mutex_unlock(&my_obj->cam_lock); 991 992 memset(&payload, 0, sizeof(mm_evt_paylod_config_stream_t)); 993 payload.stream_id = stream_id; 994 payload.config = config; 995 rc = mm_channel_fsm_fn(ch_obj, 996 MM_CHANNEL_EVT_CONFIG_STREAM, 997 (void*)&payload, 998 NULL); 999 } else { 1000 pthread_mutex_unlock(&my_obj->cam_lock); 1001 } 1002 1003 return rc; 1004 } 1005 1006 /*=========================================================================== 1007 * FUNCTION : mm_camera_start_channel 1008 * 1009 * DESCRIPTION: start a channel, which will start all streams in the channel 1010 * 1011 * PARAMETERS : 1012 * @my_obj : camera object 1013 * @ch_id : channel handle 1014 * 1015 * RETURN : int32_t type of status 1016 * 0 -- success 1017 * -1 -- failure 1018 *==========================================================================*/ 1019 int32_t mm_camera_start_channel(mm_camera_obj_t *my_obj, 1020 uint32_t ch_id) 1021 { 1022 int32_t rc = -1; 1023 mm_channel_t * ch_obj = 1024 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1025 1026 if (NULL != ch_obj) { 1027 pthread_mutex_lock(&ch_obj->ch_lock); 1028 pthread_mutex_unlock(&my_obj->cam_lock); 1029 1030 rc = mm_channel_fsm_fn(ch_obj, 1031 MM_CHANNEL_EVT_START, 1032 NULL, 1033 NULL); 1034 } else { 1035 pthread_mutex_unlock(&my_obj->cam_lock); 1036 } 1037 1038 return rc; 1039 } 1040 1041 /*=========================================================================== 1042 * FUNCTION : mm_camera_stop_channel 1043 * 1044 * DESCRIPTION: stop a channel, which will stop all streams in the channel 1045 * 1046 * PARAMETERS : 1047 * @my_obj : camera object 1048 * @ch_id : channel handle 1049 * 1050 * RETURN : int32_t type of status 1051 * 0 -- success 1052 * -1 -- failure 1053 *==========================================================================*/ 1054 int32_t mm_camera_stop_channel(mm_camera_obj_t *my_obj, 1055 uint32_t ch_id) 1056 { 1057 int32_t rc = 0; 1058 mm_channel_t * ch_obj = 1059 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1060 1061 if (NULL != ch_obj) { 1062 pthread_mutex_lock(&ch_obj->ch_lock); 1063 pthread_mutex_unlock(&my_obj->cam_lock); 1064 1065 rc = mm_channel_fsm_fn(ch_obj, 1066 MM_CHANNEL_EVT_STOP, 1067 NULL, 1068 NULL); 1069 } else { 1070 pthread_mutex_unlock(&my_obj->cam_lock); 1071 } 1072 return rc; 1073 } 1074 1075 /*=========================================================================== 1076 * FUNCTION : mm_camera_request_super_buf 1077 * 1078 * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched 1079 * frames from superbuf queue 1080 * 1081 * PARAMETERS : 1082 * @my_obj : camera object 1083 * @ch_id : channel handle 1084 * @num_buf_requested : number of matched frames needed 1085 * 1086 * RETURN : int32_t type of status 1087 * 0 -- success 1088 * -1 -- failure 1089 *==========================================================================*/ 1090 int32_t mm_camera_request_super_buf(mm_camera_obj_t *my_obj, 1091 uint32_t ch_id, 1092 uint32_t num_buf_requested, 1093 uint32_t num_retro_buf_requested) 1094 { 1095 int32_t rc = -1; 1096 mm_channel_t * ch_obj = 1097 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1098 1099 if (NULL != ch_obj) { 1100 pthread_mutex_lock(&ch_obj->ch_lock); 1101 pthread_mutex_unlock(&my_obj->cam_lock); 1102 1103 rc = mm_channel_fsm_fn(ch_obj, 1104 MM_CHANNEL_EVT_REQUEST_SUPER_BUF, 1105 (void*)num_buf_requested, 1106 (void*)num_retro_buf_requested); 1107 } else { 1108 pthread_mutex_unlock(&my_obj->cam_lock); 1109 } 1110 1111 return rc; 1112 } 1113 1114 /*=========================================================================== 1115 * FUNCTION : mm_camera_cancel_super_buf_request 1116 * 1117 * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount 1118 * of matched frames from superbuf queue 1119 * 1120 * PARAMETERS : 1121 * @my_obj : camera object 1122 * @ch_id : channel handle 1123 * 1124 * RETURN : int32_t type of status 1125 * 0 -- success 1126 * -1 -- failure 1127 *==========================================================================*/ 1128 int32_t mm_camera_cancel_super_buf_request(mm_camera_obj_t *my_obj, uint32_t ch_id) 1129 { 1130 int32_t rc = -1; 1131 mm_channel_t * ch_obj = 1132 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1133 1134 if (NULL != ch_obj) { 1135 pthread_mutex_lock(&ch_obj->ch_lock); 1136 pthread_mutex_unlock(&my_obj->cam_lock); 1137 1138 rc = mm_channel_fsm_fn(ch_obj, 1139 MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF, 1140 NULL, 1141 NULL); 1142 } else { 1143 pthread_mutex_unlock(&my_obj->cam_lock); 1144 } 1145 1146 return rc; 1147 } 1148 1149 /*=========================================================================== 1150 * FUNCTION : mm_camera_flush_super_buf_queue 1151 * 1152 * DESCRIPTION: flush out all frames in the superbuf queue 1153 * 1154 * PARAMETERS : 1155 * @my_obj : camera object 1156 * @ch_id : channel handle 1157 * 1158 * RETURN : int32_t type of status 1159 * 0 -- success 1160 * -1 -- failure 1161 *==========================================================================*/ 1162 int32_t mm_camera_flush_super_buf_queue(mm_camera_obj_t *my_obj, uint32_t ch_id, 1163 uint32_t frame_idx) 1164 { 1165 int32_t rc = -1; 1166 mm_channel_t * ch_obj = 1167 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1168 1169 if (NULL != ch_obj) { 1170 pthread_mutex_lock(&ch_obj->ch_lock); 1171 pthread_mutex_unlock(&my_obj->cam_lock); 1172 1173 rc = mm_channel_fsm_fn(ch_obj, 1174 MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE, 1175 (void *)frame_idx, 1176 NULL); 1177 } else { 1178 pthread_mutex_unlock(&my_obj->cam_lock); 1179 } 1180 1181 return rc; 1182 } 1183 1184 /*=========================================================================== 1185 * FUNCTION : mm_camera_config_channel_notify 1186 * 1187 * DESCRIPTION: configures the channel notification mode 1188 * 1189 * PARAMETERS : 1190 * @my_obj : camera object 1191 * @ch_id : channel handle 1192 * @notify_mode : notification mode 1193 * 1194 * RETURN : int32_t type of status 1195 * 0 -- success 1196 * -1 -- failure 1197 *==========================================================================*/ 1198 int32_t mm_camera_config_channel_notify(mm_camera_obj_t *my_obj, 1199 uint32_t ch_id, 1200 mm_camera_super_buf_notify_mode_t notify_mode) 1201 { 1202 int32_t rc = -1; 1203 mm_channel_t * ch_obj = 1204 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1205 1206 if (NULL != ch_obj) { 1207 pthread_mutex_lock(&ch_obj->ch_lock); 1208 pthread_mutex_unlock(&my_obj->cam_lock); 1209 1210 rc = mm_channel_fsm_fn(ch_obj, 1211 MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE, 1212 (void *)notify_mode, 1213 NULL); 1214 } else { 1215 pthread_mutex_unlock(&my_obj->cam_lock); 1216 } 1217 1218 return rc; 1219 } 1220 1221 /*=========================================================================== 1222 * FUNCTION : mm_camera_set_stream_parms 1223 * 1224 * DESCRIPTION: set parameters per stream 1225 * 1226 * PARAMETERS : 1227 * @my_obj : camera object 1228 * @ch_id : channel handle 1229 * @s_id : stream handle 1230 * @parms : ptr to a param struct to be set to server 1231 * 1232 * RETURN : int32_t type of status 1233 * 0 -- success 1234 * -1 -- failure 1235 * NOTE : Assume the parms struct buf is already mapped to server via 1236 * domain socket. Corresponding fields of parameters to be set 1237 * are already filled in by upper layer caller. 1238 *==========================================================================*/ 1239 int32_t mm_camera_set_stream_parms(mm_camera_obj_t *my_obj, 1240 uint32_t ch_id, 1241 uint32_t s_id, 1242 cam_stream_parm_buffer_t *parms) 1243 { 1244 int32_t rc = -1; 1245 mm_evt_paylod_set_get_stream_parms_t payload; 1246 mm_channel_t * ch_obj = 1247 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1248 1249 if (NULL != ch_obj) { 1250 pthread_mutex_lock(&ch_obj->ch_lock); 1251 pthread_mutex_unlock(&my_obj->cam_lock); 1252 1253 memset(&payload, 0, sizeof(payload)); 1254 payload.stream_id = s_id; 1255 payload.parms = parms; 1256 1257 rc = mm_channel_fsm_fn(ch_obj, 1258 MM_CHANNEL_EVT_SET_STREAM_PARM, 1259 (void *)&payload, 1260 NULL); 1261 } else { 1262 pthread_mutex_unlock(&my_obj->cam_lock); 1263 } 1264 1265 return rc; 1266 } 1267 1268 /*=========================================================================== 1269 * FUNCTION : mm_camera_get_stream_parms 1270 * 1271 * DESCRIPTION: get parameters per stream 1272 * 1273 * PARAMETERS : 1274 * @my_obj : camera object 1275 * @ch_id : channel handle 1276 * @s_id : stream handle 1277 * @parms : ptr to a param struct to be get from server 1278 * 1279 * RETURN : int32_t type of status 1280 * 0 -- success 1281 * -1 -- failure 1282 * NOTE : Assume the parms struct buf is already mapped to server via 1283 * domain socket. Parameters to be get from server are already 1284 * filled in by upper layer caller. After this call, corresponding 1285 * fields of requested parameters will be filled in by server with 1286 * detailed information. 1287 *==========================================================================*/ 1288 int32_t mm_camera_get_stream_parms(mm_camera_obj_t *my_obj, 1289 uint32_t ch_id, 1290 uint32_t s_id, 1291 cam_stream_parm_buffer_t *parms) 1292 { 1293 int32_t rc = -1; 1294 mm_evt_paylod_set_get_stream_parms_t payload; 1295 mm_channel_t * ch_obj = 1296 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1297 1298 if (NULL != ch_obj) { 1299 pthread_mutex_lock(&ch_obj->ch_lock); 1300 pthread_mutex_unlock(&my_obj->cam_lock); 1301 1302 memset(&payload, 0, sizeof(payload)); 1303 payload.stream_id = s_id; 1304 payload.parms = parms; 1305 1306 rc = mm_channel_fsm_fn(ch_obj, 1307 MM_CHANNEL_EVT_GET_STREAM_PARM, 1308 (void *)&payload, 1309 NULL); 1310 } else { 1311 pthread_mutex_unlock(&my_obj->cam_lock); 1312 } 1313 1314 return rc; 1315 } 1316 1317 /*=========================================================================== 1318 * FUNCTION : mm_camera_do_stream_action 1319 * 1320 * DESCRIPTION: request server to perform stream based action. Maybe removed later 1321 * if the functionality is included in mm_camera_set_parms 1322 * 1323 * PARAMETERS : 1324 * @my_obj : camera object 1325 * @ch_id : channel handle 1326 * @s_id : stream handle 1327 * @actions : ptr to an action struct buf to be performed by server 1328 * 1329 * RETURN : int32_t type of status 1330 * 0 -- success 1331 * -1 -- failure 1332 * NOTE : Assume the action struct buf is already mapped to server via 1333 * domain socket. Actions to be performed by server are already 1334 * filled in by upper layer caller. 1335 *==========================================================================*/ 1336 int32_t mm_camera_do_stream_action(mm_camera_obj_t *my_obj, 1337 uint32_t ch_id, 1338 uint32_t stream_id, 1339 void *actions) 1340 { 1341 int32_t rc = -1; 1342 mm_evt_paylod_do_stream_action_t payload; 1343 mm_channel_t * ch_obj = 1344 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1345 1346 if (NULL != ch_obj) { 1347 pthread_mutex_lock(&ch_obj->ch_lock); 1348 pthread_mutex_unlock(&my_obj->cam_lock); 1349 1350 memset(&payload, 0, sizeof(payload)); 1351 payload.stream_id = stream_id; 1352 payload.actions = actions; 1353 1354 rc = mm_channel_fsm_fn(ch_obj, 1355 MM_CHANNEL_EVT_DO_STREAM_ACTION, 1356 (void*)&payload, 1357 NULL); 1358 } else { 1359 pthread_mutex_unlock(&my_obj->cam_lock); 1360 } 1361 1362 return rc; 1363 } 1364 1365 /*=========================================================================== 1366 * FUNCTION : mm_camera_map_stream_buf 1367 * 1368 * DESCRIPTION: mapping stream buffer via domain socket to server 1369 * 1370 * PARAMETERS : 1371 * @my_obj : camera object 1372 * @ch_id : channel handle 1373 * @s_id : stream handle 1374 * @buf_type : type of buffer to be mapped. could be following values: 1375 * CAM_MAPPING_BUF_TYPE_STREAM_BUF 1376 * CAM_MAPPING_BUF_TYPE_STREAM_INFO 1377 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1378 * @buf_idx : index of buffer within the stream buffers, only valid if 1379 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or 1380 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1381 * @plane_idx : plane index. If all planes share the same fd, 1382 * plane_idx = -1; otherwise, plean_idx is the 1383 * index to plane (0..num_of_planes) 1384 * @fd : file descriptor of the buffer 1385 * @size : size of the buffer 1386 * 1387 * RETURN : int32_t type of status 1388 * 0 -- success 1389 * -1 -- failure 1390 *==========================================================================*/ 1391 int32_t mm_camera_map_stream_buf(mm_camera_obj_t *my_obj, 1392 uint32_t ch_id, 1393 uint32_t stream_id, 1394 uint8_t buf_type, 1395 uint32_t buf_idx, 1396 int32_t plane_idx, 1397 int fd, 1398 uint32_t size) 1399 { 1400 int32_t rc = -1; 1401 mm_evt_paylod_map_stream_buf_t payload; 1402 mm_channel_t * ch_obj = 1403 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1404 1405 if (NULL != ch_obj) { 1406 pthread_mutex_lock(&ch_obj->ch_lock); 1407 pthread_mutex_unlock(&my_obj->cam_lock); 1408 1409 memset(&payload, 0, sizeof(payload)); 1410 payload.stream_id = stream_id; 1411 payload.buf_type = buf_type; 1412 payload.buf_idx = buf_idx; 1413 payload.plane_idx = plane_idx; 1414 payload.fd = fd; 1415 payload.size = size; 1416 rc = mm_channel_fsm_fn(ch_obj, 1417 MM_CHANNEL_EVT_MAP_STREAM_BUF, 1418 (void*)&payload, 1419 NULL); 1420 } else { 1421 pthread_mutex_unlock(&my_obj->cam_lock); 1422 } 1423 1424 return rc; 1425 } 1426 1427 /*=========================================================================== 1428 * FUNCTION : mm_camera_unmap_stream_buf 1429 * 1430 * DESCRIPTION: unmapping stream buffer via domain socket to server 1431 * 1432 * PARAMETERS : 1433 * @my_obj : camera object 1434 * @ch_id : channel handle 1435 * @s_id : stream handle 1436 * @buf_type : type of buffer to be mapped. could be following values: 1437 * CAM_MAPPING_BUF_TYPE_STREAM_BUF 1438 * CAM_MAPPING_BUF_TYPE_STREAM_INFO 1439 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1440 * @buf_idx : index of buffer within the stream buffers, only valid if 1441 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or 1442 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1443 * @plane_idx : plane index. If all planes share the same fd, 1444 * plane_idx = -1; otherwise, plean_idx is the 1445 * index to plane (0..num_of_planes) 1446 * 1447 * RETURN : int32_t type of status 1448 * 0 -- success 1449 * -1 -- failure 1450 *==========================================================================*/ 1451 int32_t mm_camera_unmap_stream_buf(mm_camera_obj_t *my_obj, 1452 uint32_t ch_id, 1453 uint32_t stream_id, 1454 uint8_t buf_type, 1455 uint32_t buf_idx, 1456 int32_t plane_idx) 1457 { 1458 int32_t rc = -1; 1459 mm_evt_paylod_unmap_stream_buf_t payload; 1460 mm_channel_t * ch_obj = 1461 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1462 1463 if (NULL != ch_obj) { 1464 pthread_mutex_lock(&ch_obj->ch_lock); 1465 pthread_mutex_unlock(&my_obj->cam_lock); 1466 1467 memset(&payload, 0, sizeof(payload)); 1468 payload.stream_id = stream_id; 1469 payload.buf_type = buf_type; 1470 payload.buf_idx = buf_idx; 1471 payload.plane_idx = plane_idx; 1472 rc = mm_channel_fsm_fn(ch_obj, 1473 MM_CHANNEL_EVT_UNMAP_STREAM_BUF, 1474 (void*)&payload, 1475 NULL); 1476 } else { 1477 pthread_mutex_unlock(&my_obj->cam_lock); 1478 } 1479 1480 return rc; 1481 } 1482 1483 /*=========================================================================== 1484 * FUNCTION : mm_camera_evt_sub 1485 * 1486 * DESCRIPTION: subscribe/unsubscribe event notify from kernel 1487 * 1488 * PARAMETERS : 1489 * @my_obj : camera object 1490 * @reg_flag : 1 -- subscribe ; 0 -- unsubscribe 1491 * 1492 * RETURN : int32_t type of status 1493 * 0 -- success 1494 * -1 -- failure 1495 *==========================================================================*/ 1496 int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj, 1497 uint8_t reg_flag) 1498 { 1499 int32_t rc = 0; 1500 struct v4l2_event_subscription sub; 1501 1502 memset(&sub, 0, sizeof(sub)); 1503 sub.type = MSM_CAMERA_V4L2_EVENT_TYPE; 1504 sub.id = MSM_CAMERA_MSM_NOTIFY; 1505 if(FALSE == reg_flag) { 1506 /* unsubscribe */ 1507 rc = ioctl(my_obj->ctrl_fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); 1508 if (rc < 0) { 1509 CDBG_ERROR("%s: unsubscribe event rc = %d", __func__, rc); 1510 return rc; 1511 } 1512 /* remove evt fd from the polling thraed when unreg the last event */ 1513 rc = mm_camera_poll_thread_del_poll_fd(&my_obj->evt_poll_thread, 1514 my_obj->my_hdl, 1515 mm_camera_sync_call); 1516 } else { 1517 rc = ioctl(my_obj->ctrl_fd, VIDIOC_SUBSCRIBE_EVENT, &sub); 1518 if (rc < 0) { 1519 CDBG_ERROR("%s: subscribe event rc = %d", __func__, rc); 1520 return rc; 1521 } 1522 /* add evt fd to polling thread when subscribe the first event */ 1523 rc = mm_camera_poll_thread_add_poll_fd(&my_obj->evt_poll_thread, 1524 my_obj->my_hdl, 1525 my_obj->ctrl_fd, 1526 mm_camera_event_notify, 1527 (void*)my_obj, 1528 mm_camera_sync_call); 1529 } 1530 return rc; 1531 } 1532 1533 /*=========================================================================== 1534 * FUNCTION : mm_camera_util_wait_for_event 1535 * 1536 * DESCRIPTION: utility function to wait for certain events 1537 * 1538 * PARAMETERS : 1539 * @my_obj : camera object 1540 * @evt_mask : mask for events to be waited. Any of event in the mask would 1541 * trigger the wait to end 1542 * @status : status of the event 1543 * 1544 * RETURN : none 1545 *==========================================================================*/ 1546 void mm_camera_util_wait_for_event(mm_camera_obj_t *my_obj, 1547 uint32_t evt_mask, 1548 int32_t *status) 1549 { 1550 pthread_mutex_lock(&my_obj->evt_lock); 1551 while (!(my_obj->evt_rcvd.server_event_type & evt_mask)) { 1552 pthread_cond_wait(&my_obj->evt_cond, &my_obj->evt_lock); 1553 } 1554 *status = my_obj->evt_rcvd.status; 1555 /* reset local storage for recieved event for next event */ 1556 memset(&my_obj->evt_rcvd, 0, sizeof(mm_camera_event_t)); 1557 pthread_mutex_unlock(&my_obj->evt_lock); 1558 } 1559 1560 /*=========================================================================== 1561 * FUNCTION : mm_camera_util_sendmsg 1562 * 1563 * DESCRIPTION: utility function to send msg via domain socket 1564 * 1565 * PARAMETERS : 1566 * @my_obj : camera object 1567 * @msg : message to be sent 1568 * @buf_size : size of the message to be sent 1569 * @sendfd : >0 if any file descriptor need to be passed across process 1570 * 1571 * RETURN : int32_t type of status 1572 * 0 -- success 1573 * -1 -- failure 1574 *==========================================================================*/ 1575 int32_t mm_camera_util_sendmsg(mm_camera_obj_t *my_obj, 1576 void *msg, 1577 uint32_t buf_size, 1578 int sendfd) 1579 { 1580 int32_t rc = -1; 1581 int32_t status; 1582 1583 /* need to lock msg_lock, since sendmsg until reposonse back is deemed as one operation*/ 1584 pthread_mutex_lock(&my_obj->msg_lock); 1585 if(mm_camera_socket_sendmsg(my_obj->ds_fd, msg, buf_size, sendfd) > 0) { 1586 /* wait for event that mapping/unmapping is done */ 1587 mm_camera_util_wait_for_event(my_obj, CAM_EVENT_TYPE_MAP_UNMAP_DONE, &status); 1588 if (MSM_CAMERA_STATUS_SUCCESS == status) { 1589 rc = 0; 1590 } 1591 } 1592 pthread_mutex_unlock(&my_obj->msg_lock); 1593 return rc; 1594 } 1595 1596 /*=========================================================================== 1597 * FUNCTION : mm_camera_map_buf 1598 * 1599 * DESCRIPTION: mapping camera buffer via domain socket to server 1600 * 1601 * PARAMETERS : 1602 * @my_obj : camera object 1603 * @buf_type : type of buffer to be mapped. could be following values: 1604 * CAM_MAPPING_BUF_TYPE_CAPABILITY 1605 * CAM_MAPPING_BUF_TYPE_SETPARM_BUF 1606 * CAM_MAPPING_BUF_TYPE_GETPARM_BUF 1607 * @fd : file descriptor of the buffer 1608 * @size : size of the buffer 1609 * 1610 * RETURN : int32_t type of status 1611 * 0 -- success 1612 * -1 -- failure 1613 *==========================================================================*/ 1614 int32_t mm_camera_map_buf(mm_camera_obj_t *my_obj, 1615 uint8_t buf_type, 1616 int fd, 1617 uint32_t size) 1618 { 1619 int32_t rc = 0; 1620 cam_sock_packet_t packet; 1621 memset(&packet, 0, sizeof(cam_sock_packet_t)); 1622 packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING; 1623 packet.payload.buf_map.type = buf_type; 1624 packet.payload.buf_map.fd = fd; 1625 packet.payload.buf_map.size = size; 1626 rc = mm_camera_util_sendmsg(my_obj, 1627 &packet, 1628 sizeof(cam_sock_packet_t), 1629 fd); 1630 pthread_mutex_unlock(&my_obj->cam_lock); 1631 return rc; 1632 } 1633 1634 /*=========================================================================== 1635 * FUNCTION : mm_camera_unmap_buf 1636 * 1637 * DESCRIPTION: unmapping camera buffer via domain socket to server 1638 * 1639 * PARAMETERS : 1640 * @my_obj : camera object 1641 * @buf_type : type of buffer to be mapped. could be following values: 1642 * CAM_MAPPING_BUF_TYPE_CAPABILITY 1643 * CAM_MAPPING_BUF_TYPE_SETPARM_BUF 1644 * CAM_MAPPING_BUF_TYPE_GETPARM_BUF 1645 * 1646 * RETURN : int32_t type of status 1647 * 0 -- success 1648 * -1 -- failure 1649 *==========================================================================*/ 1650 int32_t mm_camera_unmap_buf(mm_camera_obj_t *my_obj, 1651 uint8_t buf_type) 1652 { 1653 int32_t rc = 0; 1654 cam_sock_packet_t packet; 1655 memset(&packet, 0, sizeof(cam_sock_packet_t)); 1656 packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING; 1657 packet.payload.buf_unmap.type = buf_type; 1658 rc = mm_camera_util_sendmsg(my_obj, 1659 &packet, 1660 sizeof(cam_sock_packet_t), 1661 0); 1662 pthread_mutex_unlock(&my_obj->cam_lock); 1663 return rc; 1664 } 1665 1666 /*=========================================================================== 1667 * FUNCTION : mm_camera_util_s_ctrl 1668 * 1669 * DESCRIPTION: utility function to send v4l2 ioctl for s_ctrl 1670 * 1671 * PARAMETERS : 1672 * @fd : file descritpor for sending ioctl 1673 * @id : control id 1674 * @value : value of the ioctl to be sent 1675 * 1676 * RETURN : int32_t type of status 1677 * 0 -- success 1678 * -1 -- failure 1679 *==========================================================================*/ 1680 int32_t mm_camera_util_s_ctrl(int32_t fd, uint32_t id, int32_t *value) 1681 { 1682 int rc = 0; 1683 struct v4l2_control control; 1684 1685 memset(&control, 0, sizeof(control)); 1686 control.id = id; 1687 if (value != NULL) { 1688 control.value = *value; 1689 } 1690 rc = ioctl(fd, VIDIOC_S_CTRL, &control); 1691 1692 CDBG("%s: fd=%d, S_CTRL, id=0x%x, value = 0x%x, rc = %d\n", 1693 __func__, fd, id, (uint32_t)value, rc); 1694 if (value != NULL) { 1695 *value = control.value; 1696 } 1697 return (rc >= 0)? 0 : -1; 1698 } 1699 1700 /*=========================================================================== 1701 * FUNCTION : mm_camera_util_g_ctrl 1702 * 1703 * DESCRIPTION: utility function to send v4l2 ioctl for g_ctrl 1704 * 1705 * PARAMETERS : 1706 * @fd : file descritpor for sending ioctl 1707 * @id : control id 1708 * @value : value of the ioctl to be sent 1709 * 1710 * RETURN : int32_t type of status 1711 * 0 -- success 1712 * -1 -- failure 1713 *==========================================================================*/ 1714 int32_t mm_camera_util_g_ctrl( int32_t fd, uint32_t id, int32_t *value) 1715 { 1716 int rc = 0; 1717 struct v4l2_control control; 1718 1719 memset(&control, 0, sizeof(control)); 1720 control.id = id; 1721 if (value != NULL) { 1722 control.value = *value; 1723 } 1724 rc = ioctl(fd, VIDIOC_G_CTRL, &control); 1725 CDBG("%s: fd=%d, G_CTRL, id=0x%x, rc = %d\n", __func__, fd, id, rc); 1726 if (value != NULL) { 1727 *value = control.value; 1728 } 1729 return (rc >= 0)? 0 : -1; 1730 } 1731 1732 /*=========================================================================== 1733 * FUNCTION : mm_camera_channel_advanced_capture 1734 * 1735 * DESCRIPTION: sets the channel advanced capture 1736 * 1737 * PARAMETERS : 1738 * @my_obj : camera object 1739 * @advanced_capture_type : advanced capture type. 1740 * @ch_id : channel handle 1741 * @start_flag : flag to indicate start/stop 1742 * 1743 * RETURN : int32_t type of status 1744 * 0 -- success 1745 * -1 -- failure 1746 *==========================================================================*/ 1747 int32_t mm_camera_channel_advanced_capture(mm_camera_obj_t *my_obj, 1748 mm_camera_advanced_capture_t advanced_capture_type, 1749 uint32_t ch_id, 1750 int32_t start_flag) 1751 { 1752 CDBG("%s: E",__func__); 1753 int32_t rc = -1; 1754 mm_channel_t * ch_obj = 1755 mm_camera_util_get_channel_by_handler(my_obj, ch_id); 1756 1757 if (NULL != ch_obj) { 1758 pthread_mutex_lock(&ch_obj->ch_lock); 1759 pthread_mutex_unlock(&my_obj->cam_lock); 1760 switch (advanced_capture_type) { 1761 case MM_CAMERA_AF_BRACKETING: 1762 rc = mm_channel_fsm_fn(ch_obj, 1763 MM_CHANNEL_EVT_AF_BRACKETING, 1764 (void *)start_flag, 1765 NULL); 1766 break; 1767 case MM_CAMERA_AE_BRACKETING: 1768 rc = mm_channel_fsm_fn(ch_obj, 1769 MM_CHANNEL_EVT_AE_BRACKETING, 1770 (void *)start_flag, 1771 NULL); 1772 break; 1773 case MM_CAMERA_FLASH_BRACKETING: 1774 rc = mm_channel_fsm_fn(ch_obj, 1775 MM_CHANNEL_EVT_FLASH_BRACKETING, 1776 (void *)start_flag, 1777 NULL); 1778 break; 1779 case MM_CAMERA_ZOOM_1X: 1780 rc = mm_channel_fsm_fn(ch_obj, 1781 MM_CHANNEL_EVT_ZOOM_1X, 1782 (void *)start_flag, 1783 NULL); 1784 break; 1785 default: 1786 break; 1787 } 1788 1789 } else { 1790 pthread_mutex_unlock(&my_obj->cam_lock); 1791 } 1792 1793 CDBG("%s: X",__func__); 1794 return rc; 1795 } 1796