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                 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