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