• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 <stdbool.h>
33 #include <sys/ioctl.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <poll.h>
38 #include <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     /* exit */
48     MM_CAMERA_PIPE_CMD_EXIT,
49     /* max count */
50     MM_CAMERA_PIPE_CMD_MAX
51 } mm_camera_pipe_cmd_type_t;
52 
53 typedef enum {
54     MM_CAMERA_POLL_TASK_STATE_STOPPED,
55     MM_CAMERA_POLL_TASK_STATE_POLL,     /* polling pid in polling state. */
56     MM_CAMERA_POLL_TASK_STATE_MAX
57 } mm_camera_poll_task_state_type_t;
58 
59 typedef struct {
60     uint8_t cmd;
61     mm_camera_event_t event;
62 } mm_camera_sig_evt_t;
63 
mm_camera_poll_sig(mm_camera_poll_thread_t * poll_cb,uint32_t cmd)64 static int32_t mm_camera_poll_sig(mm_camera_poll_thread_t *poll_cb,
65                                   uint32_t cmd)
66 {
67     /* send through pipe */
68     /* get the mutex */
69     mm_camera_sig_evt_t cmd_evt;
70     int len;
71 
72     CDBG("%s: E cmd = %d", __func__,cmd);
73     memset(&cmd_evt, 0, sizeof(cmd_evt));
74     cmd_evt.cmd = cmd;
75     pthread_mutex_lock(&poll_cb->mutex);
76     /* reset the statue to false */
77     poll_cb->status = false;
78     /* send cmd to worker */
79 
80     len = write(poll_cb->pfds[1], &cmd_evt, sizeof(cmd_evt));
81     if(len < 1) {
82         CDBG_ERROR("%s: len = %d, errno = %d", __func__, len, errno);
83     }
84     CDBG("%s: begin IN mutex write done, len = %d", __func__, len);
85     /* wait till worker task gives positive signal */
86     if (false == poll_cb->status) {
87         CDBG("%s: wait", __func__);
88         pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex);
89     }
90     /* done */
91     pthread_mutex_unlock(&poll_cb->mutex);
92     CDBG("%s: X", __func__);
93     return 0;
94 }
95 
mm_camera_poll_sig_done(mm_camera_poll_thread_t * poll_cb)96 static void mm_camera_poll_sig_done(mm_camera_poll_thread_t *poll_cb)
97 {
98     pthread_mutex_lock(&poll_cb->mutex);
99     poll_cb->status = true;
100     pthread_cond_signal(&poll_cb->cond_v);
101     CDBG("%s: done, in mutex", __func__);
102     pthread_mutex_unlock(&poll_cb->mutex);
103 }
104 
mm_camera_poll_set_state(mm_camera_poll_thread_t * poll_cb,mm_camera_poll_task_state_type_t state)105 static void mm_camera_poll_set_state(mm_camera_poll_thread_t *poll_cb,
106                                      mm_camera_poll_task_state_type_t state)
107 {
108     poll_cb->state = state;
109 }
110 
mm_camera_poll_proc_pipe(mm_camera_poll_thread_t * poll_cb)111 static void mm_camera_poll_proc_pipe(mm_camera_poll_thread_t *poll_cb)
112 {
113     ssize_t read_len;
114     int i;
115     mm_camera_sig_evt_t cmd_evt;
116     read_len = read(poll_cb->pfds[0], &cmd_evt, sizeof(cmd_evt));
117     CDBG("%s: read_fd = %d, read_len = %d, expect_len = %d cmd = %d",
118          __func__, poll_cb->pfds[0], (int)read_len, (int)sizeof(cmd_evt), cmd_evt.cmd);
119     switch (cmd_evt.cmd) {
120     case MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED:
121         /* we always have index 0 for pipe read */
122         poll_cb->num_fds = 0;
123         poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->pfds[0];
124         poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
125         poll_cb->num_fds++;
126 
127         if (MM_CAMERA_POLL_TYPE_EVT == poll_cb->poll_type) {
128             if (poll_cb->poll_entries[0].fd > 0) {
129                 /* fd is valid, we update poll_fds */
130                 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[0].fd;
131                 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
132                 poll_cb->num_fds++;
133             }
134         } else if (MM_CAMERA_POLL_TYPE_CH == poll_cb->poll_type) {
135             for(i = 0; i < MM_CAMEAR_STRAEM_NUM_MAX; i++) {
136                 if(poll_cb->poll_entries[i].fd > 0) {
137                     /* fd is valid, we update poll_fds to this fd */
138                     poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[i].fd;
139                     poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
140                     poll_cb->num_fds++;
141                 } else {
142                     /* fd is invalid, we set the entry to -1 to prevent polling.
143                      * According to spec, polling will not poll on entry with fd=-1.
144                      * If this is not the case, we need to skip these invalid fds
145                      * when updating this array.
146                      * We still keep fd=-1 in this array because this makes easier to
147                      * map cb associated with this fd once incoming data avail by directly
148                      * using the index-1(0 is reserved for pipe read, so need to reduce index by 1) */
149                     poll_cb->poll_fds[poll_cb->num_fds].fd = -1;
150                     poll_cb->poll_fds[poll_cb->num_fds].events = 0;
151                     poll_cb->num_fds++;
152                 }
153             }
154         }
155         mm_camera_poll_sig_done(poll_cb);
156         break;
157 
158     case MM_CAMERA_PIPE_CMD_EXIT:
159     default:
160         mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_STOPPED);
161         mm_camera_poll_sig_done(poll_cb);
162         break;
163     }
164 }
165 
mm_camera_poll_fn(mm_camera_poll_thread_t * poll_cb)166 static void *mm_camera_poll_fn(mm_camera_poll_thread_t *poll_cb)
167 {
168     int rc = 0, i;
169 
170     CDBG("%s: poll type = %d, num_fd = %d poll_cb = %p\n",
171          __func__, poll_cb->poll_type, poll_cb->num_fds,poll_cb);
172     do {
173          for(i = 0; i < poll_cb->num_fds; i++) {
174             poll_cb->poll_fds[i].events = POLLIN|POLLRDNORM|POLLPRI;
175          }
176 
177          rc = poll(poll_cb->poll_fds, poll_cb->num_fds, poll_cb->timeoutms);
178          if(rc > 0) {
179             if ((poll_cb->poll_fds[0].revents & POLLIN) &&
180                 (poll_cb->poll_fds[0].revents & POLLRDNORM)) {
181                 /* if we have data on pipe, we only process pipe in this iteration */
182                 CDBG("%s: cmd received on pipe\n", __func__);
183                 mm_camera_poll_proc_pipe(poll_cb);
184             } else {
185                 for(i=1; i<poll_cb->num_fds; i++) {
186                     /* Checking for ctrl events */
187                     if ((poll_cb->poll_type == MM_CAMERA_POLL_TYPE_EVT) &&
188                         (poll_cb->poll_fds[i].revents & POLLPRI)) {
189                         CDBG("%s: mm_camera_evt_notify\n", __func__);
190                         if (NULL != poll_cb->poll_entries[i-1].notify_cb) {
191                             poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data);
192                         }
193                     }
194 
195                     if ((poll_cb->poll_type == MM_CAMERA_POLL_TYPE_CH) &&
196                         (poll_cb->poll_fds[i].revents & POLLIN) &&
197                         (poll_cb->poll_fds[i].revents & POLLRDNORM)) {
198                         CDBG("%s: mm_stream_data_notify\n", __func__);
199                         if (NULL != poll_cb->poll_entries[i-1].notify_cb) {
200                             poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data);
201                         }
202                     }
203                 }
204             }
205         } else {
206             /* in error case sleep 10 us and then continue. hard coded here */
207             usleep(10);
208             continue;
209         }
210     } while (poll_cb->state == MM_CAMERA_POLL_TASK_STATE_POLL);
211     return NULL;
212 }
213 
mm_camera_poll_thread(void * data)214 static void *mm_camera_poll_thread(void *data)
215 {
216     int rc = 0;
217     int i;
218     void *ret = NULL;
219     mm_camera_poll_thread_t *poll_cb = (mm_camera_poll_thread_t *)data;
220 
221     /* add pipe read fd into poll first */
222     poll_cb->poll_fds[poll_cb->num_fds++].fd = poll_cb->pfds[0];
223 
224     //poll_cb->poll_fds[poll_cb->num_fds++].fd = (((mm_camera_obj_t *)poll_cb->my_obj)->ctrl_fd);
225 
226     mm_camera_poll_sig_done(poll_cb);
227     mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_POLL);
228     ret = mm_camera_poll_fn(poll_cb);
229     return ret;
230 }
231 
mm_camera_poll_thread_notify_entries_updated(mm_camera_poll_thread_t * poll_cb)232 int32_t mm_camera_poll_thread_notify_entries_updated(mm_camera_poll_thread_t * poll_cb)
233 {
234     /* send poll entries updated signal to poll thread */
235     return mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
236 }
237 
mm_camera_poll_thread_add_poll_fd(mm_camera_poll_thread_t * poll_cb,uint32_t handler,int32_t fd,mm_camera_poll_notify_t notify_cb,void * userdata)238 int32_t mm_camera_poll_thread_add_poll_fd(mm_camera_poll_thread_t * poll_cb,
239                                           uint32_t handler,
240                                           int32_t fd,
241                                           mm_camera_poll_notify_t notify_cb,
242                                           void* userdata)
243 {
244     int32_t rc = -1;
245     uint8_t idx = 0;
246 
247     if (MM_CAMERA_POLL_TYPE_CH == poll_cb->poll_type) {
248         /* get stream idx from handler if CH type */
249         idx = mm_camera_util_get_index_by_handler(handler);
250     } else {
251         /* for EVT type, only idx=0 is valid */
252         idx = 0;
253     }
254 
255     if (MM_CAMEAR_STRAEM_NUM_MAX > idx) {
256         poll_cb->poll_entries[idx].fd = fd;
257         poll_cb->poll_entries[idx].handler = handler;
258         poll_cb->poll_entries[idx].notify_cb = notify_cb;
259         poll_cb->poll_entries[idx].user_data = userdata;
260         /* send poll entries updated signal to poll thread */
261         rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
262     } else {
263         CDBG_ERROR("%s: invalid handler %d (%d)",
264                    __func__, handler, idx);
265     }
266     return rc;
267 }
268 
mm_camera_poll_thread_del_poll_fd(mm_camera_poll_thread_t * poll_cb,uint32_t handler)269 int32_t mm_camera_poll_thread_del_poll_fd(mm_camera_poll_thread_t * poll_cb,
270                                           uint32_t handler)
271 {
272     int32_t rc = -1;
273     uint8_t idx = 0;
274 
275     if (MM_CAMERA_POLL_TYPE_CH == poll_cb->poll_type) {
276         /* get stream idx from handler if CH type */
277         idx = mm_camera_util_get_index_by_handler(handler);
278     } else {
279         /* for EVT type, only idx=0 is valid */
280         idx = 0;
281     }
282 
283     if ((MM_CAMEAR_STRAEM_NUM_MAX > idx) &&
284         (handler == poll_cb->poll_entries[idx].handler)) {
285         /* reset poll entry */
286         poll_cb->poll_entries[idx].fd = -1; /* set fd to invalid */
287         poll_cb->poll_entries[idx].handler = 0;
288         poll_cb->poll_entries[idx].notify_cb = NULL;
289 
290         /* send poll entries updated signal to poll thread */
291         rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
292     } else {
293         CDBG_ERROR("%s: invalid handler %d (%d)",
294                    __func__, handler, idx);
295     }
296 
297     return rc;
298 }
299 
mm_camera_poll_thread_launch(mm_camera_poll_thread_t * poll_cb,mm_camera_poll_thread_type_t poll_type)300 int32_t mm_camera_poll_thread_launch(mm_camera_poll_thread_t * poll_cb,
301                                      mm_camera_poll_thread_type_t poll_type)
302 {
303     int32_t rc = 0;
304     poll_cb->poll_type = poll_type;
305 
306     poll_cb->pfds[0] = 0;
307     poll_cb->pfds[1] = 0;
308     rc = pipe(poll_cb->pfds);
309     if(rc < 0) {
310         CDBG_ERROR("%s: pipe open rc=%d\n", __func__, rc);
311         return -1;
312     }
313 
314     poll_cb->timeoutms = -1;  /* Infinite seconds */
315 
316     CDBG("%s: poll_type = %d, read fd = %d, write fd = %d timeout = %d",
317         __func__, poll_cb->poll_type,
318         poll_cb->pfds[0], poll_cb->pfds[1],poll_cb->timeoutms);
319 
320     pthread_mutex_init(&poll_cb->mutex, NULL);
321     pthread_cond_init(&poll_cb->cond_v, NULL);
322 
323     /* launch the thread */
324     pthread_mutex_lock(&poll_cb->mutex);
325     poll_cb->status = 0;
326     pthread_create(&poll_cb->pid, NULL, mm_camera_poll_thread, (void *)poll_cb);
327     if(!poll_cb->status) {
328         pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex);
329     }
330     pthread_mutex_unlock(&poll_cb->mutex);
331     CDBG("%s: End",__func__);
332     return rc;
333 }
334 
mm_camera_poll_thread_release(mm_camera_poll_thread_t * poll_cb)335 int32_t mm_camera_poll_thread_release(mm_camera_poll_thread_t *poll_cb)
336 {
337     int32_t rc = 0;
338     if(MM_CAMERA_POLL_TASK_STATE_STOPPED == poll_cb->state) {
339         CDBG_ERROR("%s: err, poll thread is not running.\n", __func__);
340         return rc;
341     }
342 
343     /* send exit signal to poll thread */
344     mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_EXIT);
345     /* wait until poll thread exits */
346     if (pthread_join(poll_cb->pid, NULL) != 0) {
347         CDBG_ERROR("%s: pthread dead already\n", __func__);
348     }
349 
350     /* close pipe */
351     if(poll_cb->pfds[0]) {
352         close(poll_cb->pfds[0]);
353     }
354     if(poll_cb->pfds[1]) {
355         close(poll_cb->pfds[1]);
356     }
357 
358     pthread_mutex_destroy(&poll_cb->mutex);
359     pthread_cond_destroy(&poll_cb->cond_v);
360     memset(poll_cb, 0, sizeof(mm_camera_poll_thread_t));
361     return rc;
362 }
363