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