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