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