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