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
mm_camera_poll_sig(mm_camera_poll_thread_t * poll_cb,uint32_t cmd)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
mm_camera_poll_sig_done(mm_camera_poll_thread_t * poll_cb)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
mm_camera_poll_set_state(mm_camera_poll_thread_t * poll_cb,mm_camera_poll_task_state_type_t state)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
mm_camera_poll_proc_pipe(mm_camera_poll_thread_t * poll_cb)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
mm_camera_poll_fn(mm_camera_poll_thread_t * poll_cb)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
mm_camera_poll_thread(void * data)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
mm_camera_poll_thread_notify_entries_updated(mm_camera_poll_thread_t * poll_cb)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
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)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
mm_camera_poll_thread_del_poll_fd(mm_camera_poll_thread_t * poll_cb,uint32_t handler)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
mm_camera_poll_thread_launch(mm_camera_poll_thread_t * poll_cb,mm_camera_poll_thread_type_t poll_type)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
mm_camera_poll_thread_release(mm_camera_poll_thread_t * poll_cb)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