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