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