Home | History | Annotate | Download | only in src
      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             if (poll_cb->poll_entries[0].fd > 0) {
    227                 /* fd is valid, we update poll_fds */
    228                 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[0].fd;
    229                 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
    230                 poll_cb->num_fds++;
    231             }
    232         } else if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) {
    233             for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
    234                 if(poll_cb->poll_entries[i].fd > 0) {
    235                     /* fd is valid, we update poll_fds to this fd */
    236                     poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[i].fd;
    237                     poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
    238                     poll_cb->num_fds++;
    239                 } else {
    240                     /* fd is invalid, we set the entry to -1 to prevent polling.
    241                      * According to spec, polling will not poll on entry with fd=-1.
    242                      * If this is not the case, we need to skip these invalid fds
    243                      * when updating this array.
    244                      * We still keep fd=-1 in this array because this makes easier to
    245                      * map cb associated with this fd once incoming data avail by directly
    246                      * using the index-1(0 is reserved for pipe read, so need to reduce index by 1) */
    247                     poll_cb->poll_fds[poll_cb->num_fds].fd = -1;
    248                     poll_cb->poll_fds[poll_cb->num_fds].events = 0;
    249                     poll_cb->num_fds++;
    250                 }
    251             }
    252         }
    253         if (cmd_evt.cmd != MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC)
    254             mm_camera_poll_sig_done(poll_cb);
    255         break;
    256 
    257     case MM_CAMERA_PIPE_CMD_COMMIT:
    258         mm_camera_poll_sig_done(poll_cb);
    259         break;
    260     case MM_CAMERA_PIPE_CMD_EXIT:
    261     default:
    262         mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_STOPPED);
    263         mm_camera_poll_sig_done(poll_cb);
    264         break;
    265     }
    266 }
    267 
    268 /*===========================================================================
    269  * FUNCTION   : mm_camera_poll_fn
    270  *
    271  * DESCRIPTION: polling thread routine
    272  *
    273  * PARAMETERS :
    274  *   @poll_cb : ptr to poll thread object
    275  *
    276  * RETURN     : none
    277  *==========================================================================*/
    278 static void *mm_camera_poll_fn(mm_camera_poll_thread_t *poll_cb)
    279 {
    280     int rc = 0, i;
    281 
    282     CDBG("%s: poll type = %d, num_fd = %d poll_cb = %p\n",
    283          __func__, poll_cb->poll_type, poll_cb->num_fds,poll_cb);
    284     do {
    285          for(i = 0; i < poll_cb->num_fds; i++) {
    286             poll_cb->poll_fds[i].events = POLLIN|POLLRDNORM|POLLPRI;
    287          }
    288 
    289          rc = poll(poll_cb->poll_fds, poll_cb->num_fds, poll_cb->timeoutms);
    290          if(rc > 0) {
    291             if ((poll_cb->poll_fds[0].revents & POLLIN) &&
    292                 (poll_cb->poll_fds[0].revents & POLLRDNORM)) {
    293                 /* if we have data on pipe, we only process pipe in this iteration */
    294                 CDBG("%s: cmd received on pipe\n", __func__);
    295                 mm_camera_poll_proc_pipe(poll_cb);
    296             } else {
    297                 for(i=1; i<poll_cb->num_fds; i++) {
    298                     /* Checking for ctrl events */
    299                     if ((poll_cb->poll_type == MM_CAMERA_POLL_TYPE_EVT) &&
    300                         (poll_cb->poll_fds[i].revents & POLLPRI)) {
    301                         CDBG("%s: mm_camera_evt_notify\n", __func__);
    302                         if (NULL != poll_cb->poll_entries[i-1].notify_cb) {
    303                             poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data);
    304                         }
    305                     }
    306 
    307                     if ((MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) &&
    308                         (poll_cb->poll_fds[i].revents & POLLIN) &&
    309                         (poll_cb->poll_fds[i].revents & POLLRDNORM)) {
    310                         CDBG("%s: mm_stream_data_notify\n", __func__);
    311                         if (NULL != poll_cb->poll_entries[i-1].notify_cb) {
    312                             poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data);
    313                         }
    314                     }
    315                 }
    316             }
    317         } else {
    318             /* in error case sleep 10 us and then continue. hard coded here */
    319             usleep(10);
    320             continue;
    321         }
    322     } while (poll_cb->state == MM_CAMERA_POLL_TASK_STATE_POLL);
    323     return NULL;
    324 }
    325 
    326 /*===========================================================================
    327  * FUNCTION   : mm_camera_poll_thread
    328  *
    329  * DESCRIPTION: polling thread entry function
    330  *
    331  * PARAMETERS :
    332  *   @data    : ptr to poll thread object
    333  *
    334  * RETURN     : none
    335  *==========================================================================*/
    336 static void *mm_camera_poll_thread(void *data)
    337 {
    338     prctl(PR_SET_NAME, (unsigned long)"mm_cam_poll_th", 0, 0, 0);
    339     mm_camera_poll_thread_t *poll_cb = (mm_camera_poll_thread_t *)data;
    340 
    341     /* add pipe read fd into poll first */
    342     poll_cb->poll_fds[poll_cb->num_fds++].fd = poll_cb->pfds[0];
    343 
    344     mm_camera_poll_sig_done(poll_cb);
    345     mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_POLL);
    346     return mm_camera_poll_fn(poll_cb);
    347 }
    348 
    349 /*===========================================================================
    350  * FUNCTION   : mm_camera_poll_thread
    351  *
    352  * DESCRIPTION: notify the polling thread that entries for polling fd have
    353  *              been updated
    354  *
    355  * PARAMETERS :
    356  *   @poll_cb : ptr to poll thread object
    357  *
    358  * RETURN     : none
    359  *==========================================================================*/
    360 int32_t mm_camera_poll_thread_notify_entries_updated(mm_camera_poll_thread_t * poll_cb)
    361 {
    362     /* send poll entries updated signal to poll thread */
    363     return mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
    364 }
    365 
    366 /*===========================================================================
    367  * FUNCTION   : mm_camera_poll_thread_commit_updates
    368  *
    369  * DESCRIPTION: sync with all previously pending async updates
    370  *
    371  * PARAMETERS :
    372  *   @poll_cb : ptr to poll thread object
    373  *
    374  * RETURN     : int32_t type of status
    375  *              0  -- success
    376  *              -1 -- failure
    377  *==========================================================================*/
    378 int32_t mm_camera_poll_thread_commit_updates(mm_camera_poll_thread_t * poll_cb)
    379 {
    380     return mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_COMMIT);
    381 }
    382 
    383 /*===========================================================================
    384  * FUNCTION   : mm_camera_poll_thread_add_poll_fd
    385  *
    386  * DESCRIPTION: add a new fd into polling thread
    387  *
    388  * PARAMETERS :
    389  *   @poll_cb   : ptr to poll thread object
    390  *   @handler   : stream handle if channel data polling thread,
    391  *                0 if event polling thread
    392  *   @fd        : file descriptor need to be added into polling thread
    393  *   @notify_cb : callback function to handle if any notify from fd
    394  *   @userdata  : user data ptr
    395  *   @call_type : Whether its Synchronous or Asynchronous call
    396  *
    397  * RETURN     : none
    398  *==========================================================================*/
    399 int32_t mm_camera_poll_thread_add_poll_fd(mm_camera_poll_thread_t * poll_cb,
    400                                           uint32_t handler,
    401                                           int32_t fd,
    402                                           mm_camera_poll_notify_t notify_cb,
    403                                           void* userdata,
    404                                           mm_camera_call_type_t call_type)
    405 {
    406     int32_t rc = -1;
    407     uint8_t idx = 0;
    408 
    409     if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) {
    410         /* get stream idx from handler if CH type */
    411         idx = mm_camera_util_get_index_by_handler(handler);
    412     } else {
    413         /* for EVT type, only idx=0 is valid */
    414         idx = 0;
    415     }
    416 
    417     if (MAX_STREAM_NUM_IN_BUNDLE > idx) {
    418         poll_cb->poll_entries[idx].fd = fd;
    419         poll_cb->poll_entries[idx].handler = handler;
    420         poll_cb->poll_entries[idx].notify_cb = notify_cb;
    421         poll_cb->poll_entries[idx].user_data = userdata;
    422         /* send poll entries updated signal to poll thread */
    423         if (call_type == mm_camera_sync_call ) {
    424             rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
    425         } else {
    426             rc = mm_camera_poll_sig_async(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC );
    427         }
    428     } else {
    429         CDBG_ERROR("%s: invalid handler %d (%d)",
    430                    __func__, handler, idx);
    431     }
    432     return rc;
    433 }
    434 
    435 /*===========================================================================
    436  * FUNCTION   : mm_camera_poll_thread_del_poll_fd
    437  *
    438  * DESCRIPTION: delete a fd from polling thread
    439  *
    440  * PARAMETERS :
    441  *   @poll_cb   : ptr to poll thread object
    442  *   @handler   : stream handle if channel data polling thread,
    443  *                0 if event polling thread
    444  *
    445  * RETURN     : int32_t type of status
    446  *              0  -- success
    447  *              -1 -- failure
    448  *==========================================================================*/
    449 int32_t mm_camera_poll_thread_del_poll_fd(mm_camera_poll_thread_t * poll_cb,
    450                                           uint32_t handler,
    451                                           mm_camera_call_type_t call_type)
    452 {
    453     int32_t rc = -1;
    454     uint8_t idx = 0;
    455 
    456     if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) {
    457         /* get stream idx from handler if CH type */
    458         idx = mm_camera_util_get_index_by_handler(handler);
    459     } else {
    460         /* for EVT type, only idx=0 is valid */
    461         idx = 0;
    462     }
    463 
    464     if ((MAX_STREAM_NUM_IN_BUNDLE > idx) &&
    465         (handler == poll_cb->poll_entries[idx].handler)) {
    466         /* reset poll entry */
    467         poll_cb->poll_entries[idx].fd = -1; /* set fd to invalid */
    468         poll_cb->poll_entries[idx].handler = 0;
    469         poll_cb->poll_entries[idx].notify_cb = NULL;
    470 
    471         /* send poll entries updated signal to poll thread */
    472         if (call_type == mm_camera_sync_call ) {
    473             rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
    474         } else {
    475             rc = mm_camera_poll_sig_async(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC );
    476         }
    477     } else {
    478         CDBG_ERROR("%s: invalid handler %d (%d)",
    479                    __func__, handler, idx);
    480         return -1;
    481     }
    482 
    483     return rc;
    484 }
    485 
    486 static pthread_mutex_t constr_destr_lock = PTHREAD_MUTEX_INITIALIZER;
    487 
    488 int32_t mm_camera_poll_thread_launch(mm_camera_poll_thread_t * poll_cb,
    489                                      mm_camera_poll_thread_type_t poll_type)
    490 {
    491     int32_t rc = 0;
    492 
    493     pthread_mutex_lock(&constr_destr_lock);
    494 
    495     poll_cb->poll_type = poll_type;
    496 
    497     poll_cb->pfds[0] = -1;
    498     poll_cb->pfds[1] = -1;
    499     rc = pipe(poll_cb->pfds);
    500     if(rc < 0) {
    501         CDBG_ERROR("%s: pipe open rc=%d\n", __func__, rc);
    502         pthread_mutex_unlock(&constr_destr_lock);
    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     pthread_mutex_unlock(&constr_destr_lock);
    525     return rc;
    526 }
    527 
    528 int32_t mm_camera_poll_thread_release(mm_camera_poll_thread_t *poll_cb)
    529 {
    530     int32_t rc = 0;
    531 
    532     pthread_mutex_lock(&constr_destr_lock);
    533 
    534     if(MM_CAMERA_POLL_TASK_STATE_STOPPED == poll_cb->state) {
    535         CDBG_ERROR("%s: err, poll thread is not running.\n", __func__);
    536         goto done;
    537     }
    538 
    539     /* send exit signal to poll thread */
    540     mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_EXIT);
    541     /* wait until poll thread exits */
    542     if (pthread_join(poll_cb->pid, NULL) != 0) {
    543         CDBG_ERROR("%s: pthread dead already\n", __func__);
    544     }
    545 
    546     /* close pipe */
    547     if(poll_cb->pfds[0] >= 0) {
    548         close(poll_cb->pfds[0]);
    549     }
    550     if(poll_cb->pfds[1] >= 0) {
    551         close(poll_cb->pfds[1]);
    552     }
    553 
    554     pthread_mutex_destroy(&poll_cb->mutex);
    555     pthread_cond_destroy(&poll_cb->cond_v);
    556     memset(poll_cb, 0, sizeof(mm_camera_poll_thread_t));
    557 done:
    558     pthread_mutex_unlock(&constr_destr_lock);
    559     poll_cb->pfds[0] = -1;
    560     poll_cb->pfds[1] = -1;
    561     return rc;
    562 }
    563 
    564 static void *mm_camera_cmd_thread(void *data)
    565 {
    566     int running = 1;
    567     int ret;
    568     mm_camera_cmd_thread_t *cmd_thread =
    569                 (mm_camera_cmd_thread_t *)data;
    570     mm_camera_cmdcb_t* node = NULL;
    571 
    572     do {
    573         do {
    574             ret = cam_sem_wait(&cmd_thread->cmd_sem);
    575             if (ret != 0 && errno != EINVAL) {
    576                 CDBG_ERROR("%s: cam_sem_wait error (%s)",
    577                            __func__, strerror(errno));
    578                 return NULL;
    579             }
    580         } while (ret != 0);
    581 
    582         /* we got notified about new cmd avail in cmd queue */
    583         node = (mm_camera_cmdcb_t*)cam_queue_deq(&cmd_thread->cmd_queue);
    584         while (node != NULL) {
    585             switch (node->cmd_type) {
    586             case MM_CAMERA_CMD_TYPE_EVT_CB:
    587             case MM_CAMERA_CMD_TYPE_DATA_CB:
    588             case MM_CAMERA_CMD_TYPE_REQ_DATA_CB:
    589             case MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB:
    590             case MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY:
    591             case MM_CAMERA_CMD_TYPE_FLUSH_QUEUE:
    592                 if (NULL != cmd_thread->cb) {
    593                     cmd_thread->cb(node, cmd_thread->user_data);
    594                 }
    595                 break;
    596             case MM_CAMERA_CMD_TYPE_EXIT:
    597             default:
    598                 running = 0;
    599                 break;
    600             }
    601             free(node);
    602             node = (mm_camera_cmdcb_t*)cam_queue_deq(&cmd_thread->cmd_queue);
    603         } /* (node != NULL) */
    604     } while (running);
    605     return NULL;
    606 }
    607 
    608 int32_t mm_camera_cmd_thread_launch(mm_camera_cmd_thread_t * cmd_thread,
    609                                     mm_camera_cmd_cb_t cb,
    610                                     void* user_data)
    611 {
    612     int32_t rc = 0;
    613 
    614     cam_sem_init(&cmd_thread->cmd_sem, 0);
    615     cam_queue_init(&cmd_thread->cmd_queue);
    616     cmd_thread->cb = cb;
    617     cmd_thread->user_data = user_data;
    618 
    619     /* launch the thread */
    620     pthread_create(&cmd_thread->cmd_pid,
    621                    NULL,
    622                    mm_camera_cmd_thread,
    623                    (void *)cmd_thread);
    624     return rc;
    625 }
    626 
    627 int32_t mm_camera_cmd_thread_name(const char* name)
    628 {
    629     int32_t rc = 0;
    630     /* name the thread */
    631     prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
    632     return rc;
    633 }
    634 
    635 
    636 int32_t mm_camera_cmd_thread_stop(mm_camera_cmd_thread_t * cmd_thread)
    637 {
    638     int32_t rc = 0;
    639     mm_camera_cmdcb_t* node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    640     if (NULL == node) {
    641         CDBG_ERROR("%s: No memory for mm_camera_cmdcb_t", __func__);
    642         return -1;
    643     }
    644 
    645     memset(node, 0, sizeof(mm_camera_cmdcb_t));
    646     node->cmd_type = MM_CAMERA_CMD_TYPE_EXIT;
    647 
    648     cam_queue_enq(&cmd_thread->cmd_queue, node);
    649     cam_sem_post(&cmd_thread->cmd_sem);
    650 
    651     /* wait until cmd thread exits */
    652     if (pthread_join(cmd_thread->cmd_pid, NULL) != 0) {
    653         CDBG("%s: pthread dead already\n", __func__);
    654     }
    655     return rc;
    656 }
    657 
    658 int32_t mm_camera_cmd_thread_destroy(mm_camera_cmd_thread_t * cmd_thread)
    659 {
    660     int32_t rc = 0;
    661     cam_queue_deinit(&cmd_thread->cmd_queue);
    662     cam_sem_destroy(&cmd_thread->cmd_sem);
    663     memset(cmd_thread, 0, sizeof(mm_camera_cmd_thread_t));
    664     return rc;
    665 }
    666 
    667 int32_t mm_camera_cmd_thread_release(mm_camera_cmd_thread_t * cmd_thread)
    668 {
    669     int32_t rc = 0;
    670     rc = mm_camera_cmd_thread_stop(cmd_thread);
    671     if (0 == rc) {
    672         rc = mm_camera_cmd_thread_destroy(cmd_thread);
    673     }
    674     return rc;
    675 }
    676