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