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