1 /* Copyright (c) 2012-2014, 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 <sys/prctl.h> 36 #include <fcntl.h> 37 #include <poll.h> 38 #include <cam_semaphore.h> 39 40 #include "mm_camera_dbg.h" 41 #include "mm_camera_interface.h" 42 #include "mm_camera.h" 43 44 typedef enum { 45 /* poll entries updated */ 46 MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED, 47 /* poll entries updated asynchronous */ 48 MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC, 49 /* commit updates */ 50 MM_CAMERA_PIPE_CMD_COMMIT, 51 /* exit */ 52 MM_CAMERA_PIPE_CMD_EXIT, 53 /* max count */ 54 MM_CAMERA_PIPE_CMD_MAX 55 } mm_camera_pipe_cmd_type_t; 56 57 typedef enum { 58 MM_CAMERA_POLL_TASK_STATE_STOPPED, 59 MM_CAMERA_POLL_TASK_STATE_POLL, /* polling pid in polling state. */ 60 MM_CAMERA_POLL_TASK_STATE_MAX 61 } mm_camera_poll_task_state_type_t; 62 63 typedef struct { 64 uint32_t cmd; 65 mm_camera_event_t event; 66 } mm_camera_sig_evt_t; 67 68 69 /*=========================================================================== 70 * FUNCTION : mm_camera_poll_sig_async 71 * 72 * DESCRIPTION: Asynchoronous call to send a command through pipe. 73 * 74 * PARAMETERS : 75 * @poll_cb : ptr to poll thread object 76 * @cmd : command to be sent 77 * 78 * RETURN : int32_t type of status 79 * 0 -- success 80 * -1 -- failure 81 *==========================================================================*/ 82 static int32_t mm_camera_poll_sig_async(mm_camera_poll_thread_t *poll_cb, 83 uint32_t cmd) 84 { 85 /* send through pipe */ 86 /* get the mutex */ 87 mm_camera_sig_evt_t cmd_evt; 88 89 CDBG("%s: E cmd = %d", __func__,cmd); 90 memset(&cmd_evt, 0, sizeof(cmd_evt)); 91 cmd_evt.cmd = cmd; 92 pthread_mutex_lock(&poll_cb->mutex); 93 /* reset the statue to false */ 94 poll_cb->status = FALSE; 95 96 /* send cmd to worker */ 97 ssize_t len = write(poll_cb->pfds[1], &cmd_evt, sizeof(cmd_evt)); 98 if (len < 1) { 99 CDBG_ERROR("%s: len = %lld, errno = %d", __func__, 100 (long long int)len, errno); 101 /* Avoid waiting for the signal */ 102 pthread_mutex_unlock(&poll_cb->mutex); 103 return 0; 104 } 105 CDBG("%s: begin IN mutex write done, len = %lld", __func__, 106 (long long int)len); 107 pthread_mutex_unlock(&poll_cb->mutex); 108 CDBG("%s: X", __func__); 109 return 0; 110 } 111 112 113 114 115 /*=========================================================================== 116 * FUNCTION : mm_camera_poll_sig 117 * 118 * DESCRIPTION: synchorinzed call to send a command through pipe. 119 * 120 * PARAMETERS : 121 * @poll_cb : ptr to poll thread object 122 * @cmd : command to be sent 123 * 124 * RETURN : int32_t type of status 125 * 0 -- success 126 * -1 -- failure 127 *==========================================================================*/ 128 static int32_t mm_camera_poll_sig(mm_camera_poll_thread_t *poll_cb, 129 uint32_t cmd) 130 { 131 /* send through pipe */ 132 /* get the mutex */ 133 mm_camera_sig_evt_t cmd_evt; 134 135 CDBG("%s: E cmd = %d", __func__,cmd); 136 memset(&cmd_evt, 0, sizeof(cmd_evt)); 137 cmd_evt.cmd = cmd; 138 pthread_mutex_lock(&poll_cb->mutex); 139 /* reset the statue to false */ 140 poll_cb->status = FALSE; 141 /* send cmd to worker */ 142 143 ssize_t len = write(poll_cb->pfds[1], &cmd_evt, sizeof(cmd_evt)); 144 if(len < 1) { 145 CDBG_ERROR("%s: len = %lld, errno = %d", __func__, 146 (long long int)len, errno); 147 /* Avoid waiting for the signal */ 148 pthread_mutex_unlock(&poll_cb->mutex); 149 return 0; 150 } 151 CDBG("%s: begin IN mutex write done, len = %lld", __func__, 152 (long long int)len); 153 /* wait till worker task gives positive signal */ 154 if (FALSE == poll_cb->status) { 155 CDBG("%s: wait", __func__); 156 pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex); 157 } 158 /* done */ 159 pthread_mutex_unlock(&poll_cb->mutex); 160 CDBG("%s: X", __func__); 161 return 0; 162 } 163 164 /*=========================================================================== 165 * FUNCTION : mm_camera_poll_sig 166 * 167 * DESCRIPTION: signal the status of done 168 * 169 * PARAMETERS : 170 * @poll_cb : ptr to poll thread object 171 * 172 * RETURN : none 173 *==========================================================================*/ 174 static void mm_camera_poll_sig_done(mm_camera_poll_thread_t *poll_cb) 175 { 176 pthread_mutex_lock(&poll_cb->mutex); 177 poll_cb->status = TRUE; 178 pthread_cond_signal(&poll_cb->cond_v); 179 CDBG("%s: done, in mutex", __func__); 180 pthread_mutex_unlock(&poll_cb->mutex); 181 } 182 183 /*=========================================================================== 184 * FUNCTION : mm_camera_poll_set_state 185 * 186 * DESCRIPTION: set a polling state 187 * 188 * PARAMETERS : 189 * @poll_cb : ptr to poll thread object 190 * @state : polling state (stopped/polling) 191 * 192 * RETURN : none 193 *==========================================================================*/ 194 static void mm_camera_poll_set_state(mm_camera_poll_thread_t *poll_cb, 195 mm_camera_poll_task_state_type_t state) 196 { 197 poll_cb->state = state; 198 } 199 200 /*=========================================================================== 201 * FUNCTION : mm_camera_poll_proc_pipe 202 * 203 * DESCRIPTION: polling thread routine to process pipe 204 * 205 * PARAMETERS : 206 * @poll_cb : ptr to poll thread object 207 * 208 * RETURN : none 209 *==========================================================================*/ 210 static void mm_camera_poll_proc_pipe(mm_camera_poll_thread_t *poll_cb) 211 { 212 ssize_t read_len; 213 int i; 214 mm_camera_sig_evt_t cmd_evt; 215 read_len = read(poll_cb->pfds[0], &cmd_evt, sizeof(cmd_evt)); 216 CDBG("%s: read_fd = %d, read_len = %d, expect_len = %d cmd = %d", 217 __func__, poll_cb->pfds[0], (int)read_len, (int)sizeof(cmd_evt), cmd_evt.cmd); 218 switch (cmd_evt.cmd) { 219 case MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED: 220 case MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC: 221 /* we always have index 0 for pipe read */ 222 poll_cb->num_fds = 0; 223 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->pfds[0]; 224 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI; 225 poll_cb->num_fds++; 226 227 if (MM_CAMERA_POLL_TYPE_EVT == poll_cb->poll_type && 228 poll_cb->num_fds < MAX_STREAM_NUM_IN_BUNDLE) { 229 if (poll_cb->poll_entries[0].fd > 0) { 230 /* fd is valid, we update poll_fds */ 231 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[0].fd; 232 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI; 233 poll_cb->num_fds++; 234 } 235 } else if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type && 236 poll_cb->num_fds <= MAX_STREAM_NUM_IN_BUNDLE) { 237 for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 238 if(poll_cb->poll_entries[i].fd > 0) { 239 /* fd is valid, we update poll_fds to this fd */ 240 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[i].fd; 241 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI; 242 poll_cb->num_fds++; 243 } else { 244 /* fd is invalid, we set the entry to -1 to prevent polling. 245 * According to spec, polling will not poll on entry with fd=-1. 246 * If this is not the case, we need to skip these invalid fds 247 * when updating this array. 248 * We still keep fd=-1 in this array because this makes easier to 249 * map cb associated with this fd once incoming data avail by directly 250 * using the index-1(0 is reserved for pipe read, so need to reduce index by 1) */ 251 poll_cb->poll_fds[poll_cb->num_fds].fd = -1; 252 poll_cb->poll_fds[poll_cb->num_fds].events = 0; 253 poll_cb->num_fds++; 254 } 255 } 256 } 257 if (cmd_evt.cmd != MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC) 258 mm_camera_poll_sig_done(poll_cb); 259 break; 260 261 case MM_CAMERA_PIPE_CMD_COMMIT: 262 mm_camera_poll_sig_done(poll_cb); 263 break; 264 case MM_CAMERA_PIPE_CMD_EXIT: 265 default: 266 mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_STOPPED); 267 mm_camera_poll_sig_done(poll_cb); 268 break; 269 } 270 } 271 272 /*=========================================================================== 273 * FUNCTION : mm_camera_poll_fn 274 * 275 * DESCRIPTION: polling thread routine 276 * 277 * PARAMETERS : 278 * @poll_cb : ptr to poll thread object 279 * 280 * RETURN : none 281 *==========================================================================*/ 282 static void *mm_camera_poll_fn(mm_camera_poll_thread_t *poll_cb) 283 { 284 int rc = 0, i; 285 286 if (NULL == poll_cb) { 287 CDBG_ERROR("%s: poll_cb is NULL!\n", __func__); 288 return NULL; 289 } 290 CDBG("%s: poll type = %d, num_fd = %d poll_cb = %p\n", 291 __func__, poll_cb->poll_type, poll_cb->num_fds,poll_cb); 292 do { 293 for(i = 0; i < poll_cb->num_fds; i++) { 294 poll_cb->poll_fds[i].events = POLLIN|POLLRDNORM|POLLPRI; 295 } 296 297 rc = poll(poll_cb->poll_fds, poll_cb->num_fds, poll_cb->timeoutms); 298 if(rc > 0) { 299 if ((poll_cb->poll_fds[0].revents & POLLIN) && 300 (poll_cb->poll_fds[0].revents & POLLRDNORM)) { 301 /* if we have data on pipe, we only process pipe in this iteration */ 302 CDBG("%s: cmd received on pipe\n", __func__); 303 mm_camera_poll_proc_pipe(poll_cb); 304 } else { 305 for(i=1; i<poll_cb->num_fds; i++) { 306 /* Checking for ctrl events */ 307 if ((poll_cb->poll_type == MM_CAMERA_POLL_TYPE_EVT) && 308 (poll_cb->poll_fds[i].revents & POLLPRI)) { 309 CDBG("%s: mm_camera_evt_notify\n", __func__); 310 if (NULL != poll_cb->poll_entries[i-1].notify_cb) { 311 poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data); 312 } 313 } 314 315 if ((MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) && 316 (poll_cb->poll_fds[i].revents & POLLIN) && 317 (poll_cb->poll_fds[i].revents & POLLRDNORM)) { 318 CDBG("%s: mm_stream_data_notify\n", __func__); 319 if (NULL != poll_cb->poll_entries[i-1].notify_cb) { 320 poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data); 321 } 322 } 323 } 324 } 325 } else { 326 /* in error case sleep 10 us and then continue. hard coded here */ 327 usleep(10); 328 continue; 329 } 330 } while ((poll_cb != NULL) && (poll_cb->state == MM_CAMERA_POLL_TASK_STATE_POLL)); 331 return NULL; 332 } 333 334 /*=========================================================================== 335 * FUNCTION : mm_camera_poll_thread 336 * 337 * DESCRIPTION: polling thread entry function 338 * 339 * PARAMETERS : 340 * @data : ptr to poll thread object 341 * 342 * RETURN : none 343 *==========================================================================*/ 344 static void *mm_camera_poll_thread(void *data) 345 { 346 prctl(PR_SET_NAME, (unsigned long)"mm_cam_poll_th", 0, 0, 0); 347 mm_camera_poll_thread_t *poll_cb = (mm_camera_poll_thread_t *)data; 348 349 /* add pipe read fd into poll first */ 350 poll_cb->poll_fds[poll_cb->num_fds++].fd = poll_cb->pfds[0]; 351 352 mm_camera_poll_sig_done(poll_cb); 353 mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_POLL); 354 return mm_camera_poll_fn(poll_cb); 355 } 356 357 /*=========================================================================== 358 * FUNCTION : mm_camera_poll_thread 359 * 360 * DESCRIPTION: notify the polling thread that entries for polling fd have 361 * been updated 362 * 363 * PARAMETERS : 364 * @poll_cb : ptr to poll thread object 365 * 366 * RETURN : none 367 *==========================================================================*/ 368 int32_t mm_camera_poll_thread_notify_entries_updated(mm_camera_poll_thread_t * poll_cb) 369 { 370 /* send poll entries updated signal to poll thread */ 371 return mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED); 372 } 373 374 /*=========================================================================== 375 * FUNCTION : mm_camera_poll_thread_commit_updates 376 * 377 * DESCRIPTION: sync with all previously pending async updates 378 * 379 * PARAMETERS : 380 * @poll_cb : ptr to poll thread object 381 * 382 * RETURN : int32_t type of status 383 * 0 -- success 384 * -1 -- failure 385 *==========================================================================*/ 386 int32_t mm_camera_poll_thread_commit_updates(mm_camera_poll_thread_t * poll_cb) 387 { 388 return mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_COMMIT); 389 } 390 391 /*=========================================================================== 392 * FUNCTION : mm_camera_poll_thread_add_poll_fd 393 * 394 * DESCRIPTION: add a new fd into polling thread 395 * 396 * PARAMETERS : 397 * @poll_cb : ptr to poll thread object 398 * @handler : stream handle if channel data polling thread, 399 * 0 if event polling thread 400 * @fd : file descriptor need to be added into polling thread 401 * @notify_cb : callback function to handle if any notify from fd 402 * @userdata : user data ptr 403 * @call_type : Whether its Synchronous or Asynchronous call 404 * 405 * RETURN : none 406 *==========================================================================*/ 407 int32_t mm_camera_poll_thread_add_poll_fd(mm_camera_poll_thread_t * poll_cb, 408 uint32_t handler, 409 int32_t fd, 410 mm_camera_poll_notify_t notify_cb, 411 void* userdata, 412 mm_camera_call_type_t call_type) 413 { 414 int32_t rc = -1; 415 uint8_t idx = 0; 416 417 if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) { 418 /* get stream idx from handler if CH type */ 419 idx = mm_camera_util_get_index_by_handler(handler); 420 } else { 421 /* for EVT type, only idx=0 is valid */ 422 idx = 0; 423 } 424 425 if (MAX_STREAM_NUM_IN_BUNDLE > idx) { 426 poll_cb->poll_entries[idx].fd = fd; 427 poll_cb->poll_entries[idx].handler = handler; 428 poll_cb->poll_entries[idx].notify_cb = notify_cb; 429 poll_cb->poll_entries[idx].user_data = userdata; 430 /* send poll entries updated signal to poll thread */ 431 if (call_type == mm_camera_sync_call ) { 432 rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED); 433 } else { 434 rc = mm_camera_poll_sig_async(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC ); 435 } 436 } else { 437 CDBG_ERROR("%s: invalid handler %d (%d)", 438 __func__, handler, idx); 439 } 440 return rc; 441 } 442 443 /*=========================================================================== 444 * FUNCTION : mm_camera_poll_thread_del_poll_fd 445 * 446 * DESCRIPTION: delete a fd from polling thread 447 * 448 * PARAMETERS : 449 * @poll_cb : ptr to poll thread object 450 * @handler : stream handle if channel data polling thread, 451 * 0 if event polling thread 452 * 453 * RETURN : int32_t type of status 454 * 0 -- success 455 * -1 -- failure 456 *==========================================================================*/ 457 int32_t mm_camera_poll_thread_del_poll_fd(mm_camera_poll_thread_t * poll_cb, 458 uint32_t handler, 459 mm_camera_call_type_t call_type) 460 { 461 int32_t rc = -1; 462 uint8_t idx = 0; 463 464 if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) { 465 /* get stream idx from handler if CH type */ 466 idx = mm_camera_util_get_index_by_handler(handler); 467 } else { 468 /* for EVT type, only idx=0 is valid */ 469 idx = 0; 470 } 471 472 if ((MAX_STREAM_NUM_IN_BUNDLE > idx) && 473 (handler == poll_cb->poll_entries[idx].handler)) { 474 /* reset poll entry */ 475 poll_cb->poll_entries[idx].fd = -1; /* set fd to invalid */ 476 poll_cb->poll_entries[idx].handler = 0; 477 poll_cb->poll_entries[idx].notify_cb = NULL; 478 479 /* send poll entries updated signal to poll thread */ 480 if (call_type == mm_camera_sync_call ) { 481 rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED); 482 } else { 483 rc = mm_camera_poll_sig_async(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC ); 484 } 485 } else { 486 CDBG_ERROR("%s: invalid handler %d (%d)", 487 __func__, handler, idx); 488 return -1; 489 } 490 491 return rc; 492 } 493 494 int32_t mm_camera_poll_thread_launch(mm_camera_poll_thread_t * poll_cb, 495 mm_camera_poll_thread_type_t poll_type) 496 { 497 int32_t rc = 0; 498 poll_cb->poll_type = poll_type; 499 500 poll_cb->pfds[0] = -1; 501 poll_cb->pfds[1] = -1; 502 rc = pipe(poll_cb->pfds); 503 if(rc < 0) { 504 CDBG_ERROR("%s: pipe open rc=%d\n", __func__, rc); 505 return -1; 506 } 507 508 poll_cb->timeoutms = -1; /* Infinite seconds */ 509 510 CDBG("%s: poll_type = %d, read fd = %d, write fd = %d timeout = %d", 511 __func__, poll_cb->poll_type, 512 poll_cb->pfds[0], poll_cb->pfds[1],poll_cb->timeoutms); 513 514 pthread_mutex_init(&poll_cb->mutex, NULL); 515 pthread_cond_init(&poll_cb->cond_v, NULL); 516 517 /* launch the thread */ 518 pthread_mutex_lock(&poll_cb->mutex); 519 poll_cb->status = 0; 520 pthread_create(&poll_cb->pid, NULL, mm_camera_poll_thread, (void *)poll_cb); 521 if(!poll_cb->status) { 522 pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex); 523 } 524 if (!poll_cb->threadName) { 525 pthread_setname_np(poll_cb->pid, "CAM_poll"); 526 } else { 527 pthread_setname_np(poll_cb->pid, poll_cb->threadName); 528 } 529 pthread_mutex_unlock(&poll_cb->mutex); 530 CDBG("%s: End",__func__); 531 return rc; 532 } 533 534 int32_t mm_camera_poll_thread_release(mm_camera_poll_thread_t *poll_cb) 535 { 536 int32_t rc = 0; 537 if(MM_CAMERA_POLL_TASK_STATE_STOPPED == poll_cb->state) { 538 CDBG_ERROR("%s: err, poll thread is not running.\n", __func__); 539 return rc; 540 } 541 542 /* send exit signal to poll thread */ 543 mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_EXIT); 544 /* wait until poll thread exits */ 545 if (pthread_join(poll_cb->pid, NULL) != 0) { 546 CDBG_ERROR("%s: pthread dead already\n", __func__); 547 } 548 549 /* close pipe */ 550 if(poll_cb->pfds[0] >= 0) { 551 close(poll_cb->pfds[0]); 552 } 553 if(poll_cb->pfds[1] >= 0) { 554 close(poll_cb->pfds[1]); 555 } 556 557 pthread_mutex_destroy(&poll_cb->mutex); 558 pthread_cond_destroy(&poll_cb->cond_v); 559 memset(poll_cb, 0, sizeof(mm_camera_poll_thread_t)); 560 poll_cb->pfds[0] = -1; 561 poll_cb->pfds[1] = -1; 562 return rc; 563 } 564 565 static void *mm_camera_cmd_thread(void *data) 566 { 567 int running = 1; 568 int ret; 569 mm_camera_cmd_thread_t *cmd_thread = 570 (mm_camera_cmd_thread_t *)data; 571 mm_camera_cmdcb_t* node = NULL; 572 573 do { 574 do { 575 ret = cam_sem_wait(&cmd_thread->cmd_sem); 576 if (ret != 0 && errno != EINVAL) { 577 CDBG_ERROR("%s: cam_sem_wait error (%s)", 578 __func__, strerror(errno)); 579 return NULL; 580 } 581 } while (ret != 0); 582 583 /* we got notified about new cmd avail in cmd queue */ 584 node = (mm_camera_cmdcb_t*)cam_queue_deq(&cmd_thread->cmd_queue); 585 while (node != NULL) { 586 switch (node->cmd_type) { 587 case MM_CAMERA_CMD_TYPE_EVT_CB: 588 case MM_CAMERA_CMD_TYPE_DATA_CB: 589 case MM_CAMERA_CMD_TYPE_REQ_DATA_CB: 590 case MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB: 591 case MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY: 592 case MM_CAMERA_CMD_TYPE_START_ZSL: 593 case MM_CAMERA_CMD_TYPE_STOP_ZSL: 594 case MM_CAMERA_CMD_TYPE_GENERAL: 595 case MM_CAMERA_CMD_TYPE_FLUSH_QUEUE: 596 if (NULL != cmd_thread->cb) { 597 cmd_thread->cb(node, cmd_thread->user_data); 598 } 599 break; 600 case MM_CAMERA_CMD_TYPE_EXIT: 601 default: 602 running = 0; 603 break; 604 } 605 free(node); 606 node = (mm_camera_cmdcb_t*)cam_queue_deq(&cmd_thread->cmd_queue); 607 } /* (node != NULL) */ 608 } while (running); 609 return NULL; 610 } 611 612 int32_t mm_camera_cmd_thread_launch(mm_camera_cmd_thread_t * cmd_thread, 613 mm_camera_cmd_cb_t cb, 614 void* user_data) 615 { 616 int32_t rc = 0; 617 618 cam_sem_init(&cmd_thread->cmd_sem, 0); 619 cam_queue_init(&cmd_thread->cmd_queue); 620 cmd_thread->cb = cb; 621 cmd_thread->user_data = user_data; 622 623 /* launch the thread */ 624 pthread_create(&cmd_thread->cmd_pid, 625 NULL, 626 mm_camera_cmd_thread, 627 (void *)cmd_thread); 628 629 if (!cmd_thread->threadName) { 630 pthread_setname_np(cmd_thread->cmd_pid, "CAM_launch"); 631 } else { 632 pthread_setname_np(cmd_thread->cmd_pid, cmd_thread->threadName); 633 } 634 return rc; 635 } 636 637 int32_t mm_camera_cmd_thread_name(const char* name) 638 { 639 int32_t rc = 0; 640 /* name the thread */ 641 prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); 642 return rc; 643 } 644 645 646 int32_t mm_camera_cmd_thread_stop(mm_camera_cmd_thread_t * cmd_thread) 647 { 648 int32_t rc = 0; 649 mm_camera_cmdcb_t* node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 650 if (NULL == node) { 651 CDBG_ERROR("%s: No memory for mm_camera_cmdcb_t", __func__); 652 return -1; 653 } 654 655 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 656 node->cmd_type = MM_CAMERA_CMD_TYPE_EXIT; 657 658 cam_queue_enq(&cmd_thread->cmd_queue, node); 659 cam_sem_post(&cmd_thread->cmd_sem); 660 661 /* wait until cmd thread exits */ 662 if (pthread_join(cmd_thread->cmd_pid, NULL) != 0) { 663 CDBG("%s: pthread dead already\n", __func__); 664 } 665 return rc; 666 } 667 668 int32_t mm_camera_cmd_thread_destroy(mm_camera_cmd_thread_t * cmd_thread) 669 { 670 int32_t rc = 0; 671 cam_queue_deinit(&cmd_thread->cmd_queue); 672 cam_sem_destroy(&cmd_thread->cmd_sem); 673 memset(cmd_thread, 0, sizeof(mm_camera_cmd_thread_t)); 674 return rc; 675 } 676 677 int32_t mm_camera_cmd_thread_release(mm_camera_cmd_thread_t * cmd_thread) 678 { 679 int32_t rc = 0; 680 rc = mm_camera_cmd_thread_stop(cmd_thread); 681 if (0 == rc) { 682 rc = mm_camera_cmd_thread_destroy(cmd_thread); 683 } 684 return rc; 685 } 686