Home | History | Annotate | Download | only in src
      1 /*
      2 Copyright (c) 2012, The Linux Foundation. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, are permitted provided that the following conditions are
      6 met:
      7     * Redistributions of source code must retain the above copyright
      8       notice, this list of conditions and the following disclaimer.
      9     * Redistributions in binary form must reproduce the above
     10       copyright notice, this list of conditions and the following
     11       disclaimer in the documentation and/or other materials provided
     12       with the distribution.
     13     * Neither the name of The Linux Foundation nor the names of its
     14       contributors may be used to endorse or promote products derived
     15       from this software without specific prior written permission.
     16 
     17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     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 <fcntl.h>
     36 #include <poll.h>
     37 #include <semaphore.h>
     38 
     39 #include "mm_camera_dbg.h"
     40 #include "mm_camera_interface.h"
     41 #include "mm_camera.h"
     42 
     43 typedef enum {
     44     /* poll entries updated */
     45     MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED,
     46     /* exit */
     47     MM_CAMERA_PIPE_CMD_EXIT,
     48     /* max count */
     49     MM_CAMERA_PIPE_CMD_MAX
     50 } mm_camera_pipe_cmd_type_t;
     51 
     52 typedef enum {
     53     MM_CAMERA_POLL_TASK_STATE_STOPPED,
     54     MM_CAMERA_POLL_TASK_STATE_POLL,     /* polling pid in polling state. */
     55     MM_CAMERA_POLL_TASK_STATE_MAX
     56 } mm_camera_poll_task_state_type_t;
     57 
     58 typedef struct {
     59     uint8_t cmd;
     60     mm_camera_event_t event;
     61 } mm_camera_sig_evt_t;
     62 
     63 static int32_t mm_camera_poll_sig(mm_camera_poll_thread_t *poll_cb,
     64                                   uint32_t cmd)
     65 {
     66     /* send through pipe */
     67     /* get the mutex */
     68     mm_camera_sig_evt_t cmd_evt;
     69     int len;
     70 
     71     CDBG("%s: E cmd = %d", __func__,cmd);
     72     memset(&cmd_evt, 0, sizeof(cmd_evt));
     73     cmd_evt.cmd = cmd;
     74     pthread_mutex_lock(&poll_cb->mutex);
     75     /* reset the statue to false */
     76     poll_cb->status = FALSE;
     77     /* send cmd to worker */
     78 
     79     len = write(poll_cb->pfds[1], &cmd_evt, sizeof(cmd_evt));
     80     if(len < 1) {
     81         CDBG_ERROR("%s: len = %d, errno = %d", __func__, len, errno);
     82     }
     83     CDBG("%s: begin IN mutex write done, len = %d", __func__, len);
     84     /* wait till worker task gives positive signal */
     85     if (FALSE == poll_cb->status) {
     86         CDBG("%s: wait", __func__);
     87         pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex);
     88     }
     89     /* done */
     90     pthread_mutex_unlock(&poll_cb->mutex);
     91     CDBG("%s: X", __func__);
     92     return 0;
     93 }
     94 
     95 static void mm_camera_poll_sig_done(mm_camera_poll_thread_t *poll_cb)
     96 {
     97     pthread_mutex_lock(&poll_cb->mutex);
     98     poll_cb->status = TRUE;
     99     pthread_cond_signal(&poll_cb->cond_v);
    100     CDBG("%s: done, in mutex", __func__);
    101     pthread_mutex_unlock(&poll_cb->mutex);
    102 }
    103 
    104 static void mm_camera_poll_set_state(mm_camera_poll_thread_t *poll_cb,
    105                                      mm_camera_poll_task_state_type_t state)
    106 {
    107     poll_cb->state = state;
    108 }
    109 
    110 static void mm_camera_poll_proc_pipe(mm_camera_poll_thread_t *poll_cb)
    111 {
    112     ssize_t read_len;
    113     int i;
    114     mm_camera_sig_evt_t cmd_evt;
    115     read_len = read(poll_cb->pfds[0], &cmd_evt, sizeof(cmd_evt));
    116     CDBG("%s: read_fd = %d, read_len = %d, expect_len = %d cmd = %d",
    117          __func__, poll_cb->pfds[0], (int)read_len, (int)sizeof(cmd_evt), cmd_evt.cmd);
    118     switch (cmd_evt.cmd) {
    119     case MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED:
    120         /* we always have index 0 for pipe read */
    121         poll_cb->num_fds = 0;
    122         poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->pfds[0];
    123         poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
    124         poll_cb->num_fds++;
    125 
    126         if (MM_CAMERA_POLL_TYPE_EVT == poll_cb->poll_type) {
    127             if (poll_cb->poll_entries[0].fd > 0) {
    128                 /* fd is valid, we update poll_fds */
    129                 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[0].fd;
    130                 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
    131                 poll_cb->num_fds++;
    132             }
    133         } else if (MM_CAMERA_POLL_TYPE_CH == poll_cb->poll_type) {
    134             for(i = 0; i < MM_CAMEAR_STRAEM_NUM_MAX; i++) {
    135                 if(poll_cb->poll_entries[i].fd > 0) {
    136                     /* fd is valid, we update poll_fds to this fd */
    137                     poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[i].fd;
    138                     poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
    139                     poll_cb->num_fds++;
    140                 } else {
    141                     /* fd is invalid, we set the entry to -1 to prevent polling.
    142                      * According to spec, polling will not poll on entry with fd=-1.
    143                      * If this is not the case, we need to skip these invalid fds
    144                      * when updating this array.
    145                      * We still keep fd=-1 in this array because this makes easier to
    146                      * map cb associated with this fd once incoming data avail by directly
    147                      * using the index-1(0 is reserved for pipe read, so need to reduce index by 1) */
    148                     poll_cb->poll_fds[poll_cb->num_fds].fd = -1;
    149                     poll_cb->poll_fds[poll_cb->num_fds].events = 0;
    150                     poll_cb->num_fds++;
    151                 }
    152             }
    153         }
    154         mm_camera_poll_sig_done(poll_cb);
    155         break;
    156 
    157     case MM_CAMERA_PIPE_CMD_EXIT:
    158     default:
    159         mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_STOPPED);
    160         mm_camera_poll_sig_done(poll_cb);
    161         break;
    162     }
    163 }
    164 
    165 static void *mm_camera_poll_fn(mm_camera_poll_thread_t *poll_cb)
    166 {
    167     int rc = 0, i;
    168 
    169     CDBG("%s: poll type = %d, num_fd = %d poll_cb = %p\n",
    170          __func__, poll_cb->poll_type, poll_cb->num_fds,poll_cb);
    171     do {
    172          for(i = 0; i < poll_cb->num_fds; i++) {
    173             poll_cb->poll_fds[i].events = POLLIN|POLLRDNORM|POLLPRI;
    174          }
    175 
    176          rc = poll(poll_cb->poll_fds, poll_cb->num_fds, poll_cb->timeoutms);
    177          if(rc > 0) {
    178             if ((poll_cb->poll_fds[0].revents & POLLIN) &&
    179                 (poll_cb->poll_fds[0].revents & POLLRDNORM)) {
    180                 /* if we have data on pipe, we only process pipe in this iteration */
    181                 CDBG("%s: cmd received on pipe\n", __func__);
    182                 mm_camera_poll_proc_pipe(poll_cb);
    183             } else {
    184                 for(i=1; i<poll_cb->num_fds; i++) {
    185                     /* Checking for ctrl events */
    186                     if ((poll_cb->poll_type == MM_CAMERA_POLL_TYPE_EVT) &&
    187                         (poll_cb->poll_fds[i].revents & POLLPRI)) {
    188                         CDBG("%s: mm_camera_evt_notify\n", __func__);
    189                         if (NULL != poll_cb->poll_entries[i-1].notify_cb) {
    190                             poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data);
    191                         }
    192                     }
    193 
    194                     if ((poll_cb->poll_type == MM_CAMERA_POLL_TYPE_CH) &&
    195                         (poll_cb->poll_fds[i].revents & POLLIN) &&
    196                         (poll_cb->poll_fds[i].revents & POLLRDNORM)) {
    197                         CDBG("%s: mm_stream_data_notify\n", __func__);
    198                         if (NULL != poll_cb->poll_entries[i-1].notify_cb) {
    199                             poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data);
    200                         }
    201                     }
    202                 }
    203             }
    204         } else {
    205             /* in error case sleep 10 us and then continue. hard coded here */
    206             usleep(10);
    207             continue;
    208         }
    209     } while (poll_cb->state == MM_CAMERA_POLL_TASK_STATE_POLL);
    210     return NULL;
    211 }
    212 
    213 static void *mm_camera_poll_thread(void *data)
    214 {
    215     int rc = 0;
    216     int i;
    217     void *ret = NULL;
    218     mm_camera_poll_thread_t *poll_cb = (mm_camera_poll_thread_t *)data;
    219 
    220     /* add pipe read fd into poll first */
    221     poll_cb->poll_fds[poll_cb->num_fds++].fd = poll_cb->pfds[0];
    222 
    223     //poll_cb->poll_fds[poll_cb->num_fds++].fd = (((mm_camera_obj_t *)poll_cb->my_obj)->ctrl_fd);
    224 
    225     mm_camera_poll_sig_done(poll_cb);
    226     mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_POLL);
    227     ret = mm_camera_poll_fn(poll_cb);
    228     return ret;
    229 }
    230 
    231 int32_t mm_camera_poll_thread_notify_entries_updated(mm_camera_poll_thread_t * poll_cb)
    232 {
    233     /* send poll entries updated signal to poll thread */
    234     return mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
    235 }
    236 
    237 int32_t mm_camera_poll_thread_add_poll_fd(mm_camera_poll_thread_t * poll_cb,
    238                                           uint32_t handler,
    239                                           int32_t fd,
    240                                           mm_camera_poll_notify_t notify_cb,
    241                                           void* userdata)
    242 {
    243     int32_t rc = -1;
    244     uint8_t idx = 0;
    245 
    246     if (MM_CAMERA_POLL_TYPE_CH == poll_cb->poll_type) {
    247         /* get stream idx from handler if CH type */
    248         idx = mm_camera_util_get_index_by_handler(handler);
    249     } else {
    250         /* for EVT type, only idx=0 is valid */
    251         idx = 0;
    252     }
    253 
    254     if (MM_CAMEAR_STRAEM_NUM_MAX > idx) {
    255         poll_cb->poll_entries[idx].fd = fd;
    256         poll_cb->poll_entries[idx].handler = handler;
    257         poll_cb->poll_entries[idx].notify_cb = notify_cb;
    258         poll_cb->poll_entries[idx].user_data = userdata;
    259         /* send poll entries updated signal to poll thread */
    260         rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
    261     } else {
    262         CDBG_ERROR("%s: invalid handler %d (%d)",
    263                    __func__, handler, idx);
    264     }
    265     return rc;
    266 }
    267 
    268 int32_t mm_camera_poll_thread_del_poll_fd(mm_camera_poll_thread_t * poll_cb,
    269                                           uint32_t handler)
    270 {
    271     int32_t rc = -1;
    272     uint8_t idx = 0;
    273 
    274     if (MM_CAMERA_POLL_TYPE_CH == poll_cb->poll_type) {
    275         /* get stream idx from handler if CH type */
    276         idx = mm_camera_util_get_index_by_handler(handler);
    277     } else {
    278         /* for EVT type, only idx=0 is valid */
    279         idx = 0;
    280     }
    281 
    282     if ((MM_CAMEAR_STRAEM_NUM_MAX > idx) &&
    283         (handler == poll_cb->poll_entries[idx].handler)) {
    284         /* reset poll entry */
    285         poll_cb->poll_entries[idx].fd = -1; /* set fd to invalid */
    286         poll_cb->poll_entries[idx].handler = 0;
    287         poll_cb->poll_entries[idx].notify_cb = NULL;
    288 
    289         /* send poll entries updated signal to poll thread */
    290         rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
    291     } else {
    292         CDBG_ERROR("%s: invalid handler %d (%d)",
    293                    __func__, handler, idx);
    294     }
    295 
    296     return rc;
    297 }
    298 
    299 int32_t mm_camera_poll_thread_launch(mm_camera_poll_thread_t * poll_cb,
    300                                      mm_camera_poll_thread_type_t poll_type)
    301 {
    302     int32_t rc = 0;
    303     poll_cb->poll_type = poll_type;
    304 
    305     poll_cb->pfds[0] = 0;
    306     poll_cb->pfds[1] = 0;
    307     rc = pipe(poll_cb->pfds);
    308     if(rc < 0) {
    309         CDBG_ERROR("%s: pipe open rc=%d\n", __func__, rc);
    310         return -1;
    311     }
    312 
    313     poll_cb->timeoutms = -1;  /* Infinite seconds */
    314 
    315     CDBG("%s: poll_type = %d, read fd = %d, write fd = %d timeout = %d",
    316         __func__, poll_cb->poll_type,
    317         poll_cb->pfds[0], poll_cb->pfds[1],poll_cb->timeoutms);
    318 
    319     pthread_mutex_init(&poll_cb->mutex, NULL);
    320     pthread_cond_init(&poll_cb->cond_v, NULL);
    321 
    322     /* launch the thread */
    323     pthread_mutex_lock(&poll_cb->mutex);
    324     poll_cb->status = 0;
    325     pthread_create(&poll_cb->pid, NULL, mm_camera_poll_thread, (void *)poll_cb);
    326     if(!poll_cb->status) {
    327         pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex);
    328     }
    329     pthread_mutex_unlock(&poll_cb->mutex);
    330     CDBG("%s: End",__func__);
    331     return rc;
    332 }
    333 
    334 int32_t mm_camera_poll_thread_release(mm_camera_poll_thread_t *poll_cb)
    335 {
    336     int32_t rc = 0;
    337     if(MM_CAMERA_POLL_TASK_STATE_STOPPED == poll_cb->state) {
    338         CDBG_ERROR("%s: err, poll thread is not running.\n", __func__);
    339         return rc;
    340     }
    341 
    342     /* send exit signal to poll thread */
    343     mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_EXIT);
    344     /* wait until poll thread exits */
    345     if (pthread_join(poll_cb->pid, NULL) != 0) {
    346         CDBG_ERROR("%s: pthread dead already\n", __func__);
    347     }
    348 
    349     /* close pipe */
    350     if(poll_cb->pfds[0]) {
    351         close(poll_cb->pfds[0]);
    352     }
    353     if(poll_cb->pfds[1]) {
    354         close(poll_cb->pfds[1]);
    355     }
    356 
    357     pthread_mutex_destroy(&poll_cb->mutex);
    358     pthread_cond_destroy(&poll_cb->cond_v);
    359     memset(poll_cb, 0, sizeof(mm_camera_poll_thread_t));
    360     return rc;
    361 }
    362