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