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