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