1 /*
2 Copyright (c) 2011, 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 "mm_camera_dbg.h"
32 #include <errno.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 "mm_camera_interface2.h"
39 #include "mm_camera.h"
40
41 typedef enum {
42 /* ask the channel to flash out the queued frames. */
43 MM_CAMERA_PIPE_CMD_FLASH_QUEUED_FRAME,
44 /* ask ctrl fd to generate ch event to HAL */
45 MM_CAMERA_PIPE_CMD_CH_EVENT,
46 /*start*/
47 MM_CAMERA_PIPE_CMD_ADD_CH,
48
49 /*stop*/
50 MM_CAMERA_PIPE_CMD_DEL_CH,
51
52 /* exit */
53 MM_CAMERA_PIPE_CMD_EXIT,
54 /* max count */
55 MM_CAMERA_PIPE_CMD_MAX
56 } mm_camera_pipe_cmd_type_t;
57
58 typedef enum {
59 MM_CAMERA_POLL_TASK_STATE_POLL, /* polling pid in polling state. */
60 MM_CAMERA_POLL_TASK_STATE_MAX
61 } mm_camera_poll_task_state_type_t;
62
63 typedef struct {
64 uint8_t cmd;
65 mm_camera_event_t event;
66 } mm_camera_sig_evt_t;
67
mm_camera_poll_sig(mm_camera_poll_thread_t * poll_cb,uint32_t cmd)68 static int32_t mm_camera_poll_sig(mm_camera_poll_thread_t *poll_cb,
69 uint32_t cmd)
70 {
71 /* send through pipe */
72 /* get the mutex */
73 mm_camera_sig_evt_t cmd_evt;
74 memset(&cmd_evt, 0, sizeof(cmd_evt));
75 cmd_evt.cmd = cmd;
76 int len;
77 CDBG("%s: begin", __func__);
78
79 pthread_mutex_lock(&poll_cb->mutex);
80 /* reset the statue to false */
81 poll_cb->status = FALSE;
82 /* send cmd to worker */
83 len = write(poll_cb->data.pfds[1], &cmd_evt, sizeof(cmd_evt));
84 if(len < 1) {
85 CDBG("%s: len = %d, errno = %d", __func__, len, errno);
86 //pthread_mutex_unlock(&poll_cb->mutex);
87 //return -1;
88 }
89 CDBG("%s: begin IN mutex write done, len = %d", __func__, len);
90 /* wait till worker task gives positive signal */
91 while (!poll_cb->status) {
92 int rc;
93 struct timespec ts;
94 clock_gettime(CLOCK_REALTIME, &ts);
95 ts.tv_sec += 2;
96 CDBG("%s: wait", __func__);
97 rc = pthread_cond_timedwait(&poll_cb->cond_v, &poll_cb->mutex, &ts);
98 if (rc) {
99 ALOGV("%s: error on pthread_cond_timedwait: %s", __func__, strerror(rc));
100 break;
101 }
102 }
103 /* done */
104 pthread_mutex_unlock(&poll_cb->mutex);
105 CDBG("%s: end, len = %d, size = %d", __func__, len, sizeof(cmd_evt));
106 return MM_CAMERA_OK;
107 }
108
mm_camera_poll_sig_done(mm_camera_poll_thread_t * poll_cb)109 static void mm_camera_poll_sig_done(mm_camera_poll_thread_t *poll_cb)
110 {
111 pthread_mutex_lock(&poll_cb->mutex);
112 poll_cb->status = TRUE;
113 pthread_cond_signal(&poll_cb->cond_v);
114 CDBG("%s: done, in mutex", __func__);
115 pthread_mutex_unlock(&poll_cb->mutex);
116 }
117
mm_camera_poll_proc_msm(mm_camera_poll_thread_t * poll_cb,struct pollfd * fds)118 static int32_t mm_camera_poll_proc_msm(mm_camera_poll_thread_t *poll_cb, struct pollfd *fds)
119 {
120 int i;
121
122 for(i = 0; i < poll_cb->data.num_fds-1; i++) {
123 /*Checking for data events*/
124 if((poll_cb->data.poll_type == MM_CAMERA_POLL_TYPE_CH) &&
125 (fds[i].revents & POLLIN) &&
126 (fds[i].revents & POLLRDNORM)) {
127 if(poll_cb->data.used) {
128 mm_camera_msm_data_notify(poll_cb->data.my_obj,
129 fds[i].fd,
130 poll_cb->data.poll_streams[i]->stream_type);
131 }
132
133 }
134 /*Checking for ctrl events*/
135 if((poll_cb->data.poll_type == MM_CAMERA_POLL_TYPE_EVT) &&
136 (fds[i].revents & POLLPRI)) {
137 CDBG("%s: mm_camera_msm_evt_notify\n", __func__);
138 mm_camera_msm_evt_notify(poll_cb->data.my_obj, fds[i].fd);
139 }
140
141 }
142 return 0;
143 }
144
cm_camera_poll_set_state(mm_camera_poll_thread_t * poll_cb,mm_camera_poll_task_state_type_t state)145 static void cm_camera_poll_set_state(mm_camera_poll_thread_t *poll_cb,
146 mm_camera_poll_task_state_type_t state)
147 {
148 poll_cb->data.state = state;
149 }
150
mm_camera_poll_proc_pipe(mm_camera_poll_thread_t * poll_cb)151 static void mm_camera_poll_proc_pipe(mm_camera_poll_thread_t *poll_cb)
152 {
153 ssize_t read_len;
154 int i;
155 mm_camera_sig_evt_t cmd_evt;
156 read_len = read(poll_cb->data.pfds[0], &cmd_evt, sizeof(cmd_evt));
157 CDBG("%s: read_fd = %d, read_len = %d, expect_len = %d",
158 __func__, poll_cb->data.pfds[0], (int)read_len, (int)sizeof(cmd_evt));
159 switch(cmd_evt.cmd) {
160 case MM_CAMERA_PIPE_CMD_FLASH_QUEUED_FRAME:
161 mm_camera_dispatch_buffered_frames(poll_cb->data.my_obj,
162 poll_cb->data.ch_type);
163 break;
164 case MM_CAMERA_PIPE_CMD_CH_EVENT: {
165 mm_camera_event_t *event = &cmd_evt.event;
166 CDBG("%s: ch event, type=0x%x, ch=%d, evt=%d",
167 __func__, event->event_type, event->e.ch.ch, event->e.ch.evt);
168 mm_camera_dispatch_app_event(poll_cb->data.my_obj, event);
169 break;
170 }
171 case MM_CAMERA_PIPE_CMD_ADD_CH:
172 if(poll_cb->data.poll_type == MM_CAMERA_POLL_TYPE_CH) {
173 for(i = 0; i < MM_CAMERA_CH_STREAM_MAX; i++) {
174 if(poll_cb->data.poll_streams[i]) {
175 poll_cb->data.poll_fd[poll_cb->data.num_fds + i] = poll_cb->data.poll_streams[i]->fd;
176 }
177 }
178 }
179 poll_cb->data.num_fds += mm_camera_ch_util_get_num_stream(poll_cb->data.my_obj,
180 poll_cb->data.ch_type);
181 poll_cb->data.used = 1;
182 CDBG("Num fds after MM_CAMERA_PIPE_CMD_ADD_CH = %d",poll_cb->data.num_fds);
183 break;
184
185 case MM_CAMERA_PIPE_CMD_DEL_CH:
186 poll_cb->data.num_fds -= mm_camera_ch_util_get_num_stream(poll_cb->data.my_obj,
187 poll_cb->data.ch_type);
188 poll_cb->data.used = 0;
189 CDBG("Num fds after MM_CAMERA_PIPE_CMD_DEL_CH = %d",poll_cb->data.num_fds);
190 break;
191
192 case MM_CAMERA_PIPE_CMD_EXIT:
193 default:
194 cm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_MAX);
195 mm_camera_poll_sig_done(poll_cb);
196 break;
197 }
198 }
199
mm_camera_poll_ch_busy(mm_camera_obj_t * my_obj,int ch_type)200 static int mm_camera_poll_ch_busy(mm_camera_obj_t * my_obj, int ch_type)
201 {
202 int i;
203 int used = 0;
204 mm_camera_poll_thread_t *poll_cb = &my_obj->poll_threads[ch_type];
205 pthread_mutex_lock(&poll_cb->mutex);
206 used = poll_cb->data.used;
207 pthread_mutex_unlock(&poll_cb->mutex);
208 if(used)
209 return 1;
210 else
211 return 0;
212 }
mm_camera_poll_dispatch_buffered_frames(mm_camera_obj_t * my_obj,int ch_type)213 int32_t mm_camera_poll_dispatch_buffered_frames(mm_camera_obj_t * my_obj, int ch_type)
214 {
215 mm_camera_poll_thread_t *poll_cb = &my_obj->poll_threads[ch_type];
216 mm_camera_sig_evt_t cmd;
217 int len;
218
219 cmd.cmd = MM_CAMERA_PIPE_CMD_FLASH_QUEUED_FRAME;
220 memset(&cmd.event, 0, sizeof(cmd.event));
221 pthread_mutex_lock(&poll_cb->mutex);
222 len = write(poll_cb->data.pfds[1], &cmd, sizeof(cmd));
223 pthread_mutex_unlock(&poll_cb->mutex);
224 return MM_CAMERA_OK;
225 }
226
mm_camera_poll_busy(mm_camera_obj_t * my_obj)227 int mm_camera_poll_busy(mm_camera_obj_t * my_obj)
228 {
229 int i;
230 mm_camera_poll_thread_t *poll_cb;
231 for(i = 0; i < (MM_CAMERA_POLL_THRAED_MAX - 1); i++) {
232 if(mm_camera_poll_ch_busy(my_obj, i) > 0)
233 return 1;
234 }
235 return 0;
236 }
237
mm_camera_poll_send_ch_event(mm_camera_obj_t * my_obj,mm_camera_event_t * event)238 int mm_camera_poll_send_ch_event(mm_camera_obj_t * my_obj, mm_camera_event_t *event)
239 {
240 mm_camera_poll_thread_t *poll_cb = &my_obj->poll_threads[MM_CAMERA_CH_MAX];
241 mm_camera_sig_evt_t cmd;
242 int len;
243
244 cmd.cmd = MM_CAMERA_PIPE_CMD_CH_EVENT;
245 memcpy(&cmd.event, event, sizeof(cmd.event));
246 CDBG("%s: ch event, type=0x%x, ch=%d, evt=%d, poll_type = %d, read_fd=%d, write_fd=%d",
247 __func__, event->event_type, event->e.ch.ch, event->e.ch.evt, poll_cb->data.poll_type,
248 poll_cb->data.pfds[0], poll_cb->data.pfds[1]);
249 pthread_mutex_lock(&poll_cb->mutex);
250 len = write(poll_cb->data.pfds[1], &cmd, sizeof(cmd));
251 pthread_mutex_unlock(&poll_cb->mutex);
252 return MM_CAMERA_OK;
253 }
254
mm_camera_poll_fn(mm_camera_poll_thread_t * poll_cb)255 static void *mm_camera_poll_fn(mm_camera_poll_thread_t *poll_cb)
256 {
257 int rc = 0, i;
258 struct pollfd fds[MM_CAMERA_CH_STREAM_MAX+1];
259 int timeoutms;
260 CDBG("%s: poll type = %d, num_fd = %d\n",
261 __func__, poll_cb->data.poll_type, poll_cb->data.num_fds);
262 do {
263 for(i = 0; i < poll_cb->data.num_fds; i++) {
264 fds[i].fd = poll_cb->data.poll_fd[i];
265 fds[i].events = POLLIN|POLLRDNORM|POLLPRI;
266 }
267 timeoutms = poll_cb->data.timeoutms;
268 rc = poll(fds, poll_cb->data.num_fds, timeoutms);
269 if(rc > 0) {
270 if((fds[0].revents & POLLIN) && (fds[0].revents & POLLRDNORM))
271 mm_camera_poll_proc_pipe(poll_cb);
272 else
273 mm_camera_poll_proc_msm(poll_cb, &fds[1]);
274 } else {
275 /* in error case sleep 10 us and then continue. hard coded here */
276 usleep(10);
277 continue;
278 }
279 } while (poll_cb->data.state == MM_CAMERA_POLL_TASK_STATE_POLL);
280 return NULL;
281 }
282
mm_camera_poll_thread(void * data)283 static void *mm_camera_poll_thread(void *data)
284 {
285 int rc = 0;
286 int i;
287 void *ret = NULL;
288 mm_camera_poll_thread_t *poll_cb = data;
289
290 poll_cb->data.poll_fd[poll_cb->data.num_fds++] = poll_cb->data.pfds[0];
291 switch(poll_cb->data.poll_type) {
292 case MM_CAMERA_POLL_TYPE_EVT:
293 poll_cb->data.poll_fd[poll_cb->data.num_fds++] =
294 ((mm_camera_obj_t *)(poll_cb->data.my_obj))->ctrl_fd;
295 break;
296 case MM_CAMERA_POLL_TYPE_CH:
297 default:
298 break;
299 }
300 mm_camera_poll_sig_done(poll_cb);
301 ret = mm_camera_poll_fn(poll_cb);
302 return ret;
303 }
304
mm_camera_poll_start(mm_camera_obj_t * my_obj,mm_camera_poll_thread_t * poll_cb)305 int mm_camera_poll_start(mm_camera_obj_t * my_obj, mm_camera_poll_thread_t *poll_cb)
306 {
307 pthread_mutex_lock(&poll_cb->mutex);
308 poll_cb->status = 0;
309 pthread_create(&poll_cb->data.pid, NULL, mm_camera_poll_thread, (void *)poll_cb);
310 while (!poll_cb->status) {
311 int rc;
312 struct timespec ts;
313
314 clock_gettime(CLOCK_REALTIME, &ts);
315 ts.tv_sec += 2;
316 rc = pthread_cond_timedwait(&poll_cb->cond_v, &poll_cb->mutex, &ts);
317 if (rc) {
318 ALOGV("%s: error on pthread_cond_timedwait: %s", __func__, strerror(rc));
319 break;
320 }
321 }
322 pthread_mutex_unlock(&poll_cb->mutex);
323 return MM_CAMERA_OK;
324 }
325
mm_camera_poll_stop(mm_camera_obj_t * my_obj,mm_camera_poll_thread_t * poll_cb)326 int mm_camera_poll_stop(mm_camera_obj_t * my_obj, mm_camera_poll_thread_t *poll_cb)
327 {
328 CDBG("%s, my_obj=0x%x\n", __func__, (uint32_t)my_obj);
329 mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_EXIT);
330 if (pthread_join(poll_cb->data.pid, NULL) != 0) {
331 CDBG("%s: pthread dead already\n", __func__);
332 }
333 return MM_CAMERA_OK;
334 }
335
336
mm_camera_poll_thread_add_ch(mm_camera_obj_t * my_obj,int ch_type)337 int mm_camera_poll_thread_add_ch(mm_camera_obj_t * my_obj, int ch_type)
338 {
339 mm_camera_poll_thread_t *poll_cb = &my_obj->poll_threads[ch_type];
340 mm_camera_sig_evt_t cmd;
341 int len;
342
343 if(poll_cb->data.used == 1){
344 CDBG_ERROR("%s : Thread is Active",__func__);
345 return MM_CAMERA_OK;
346 }
347 CDBG("Run thread for ch_type = %d ",ch_type);
348 cmd.cmd = MM_CAMERA_PIPE_CMD_ADD_CH;
349 poll_cb->data.ch_type = ch_type;
350
351 pthread_mutex_lock(&poll_cb->mutex);
352 len = write(poll_cb->data.pfds[1], &cmd, sizeof(cmd));
353 pthread_mutex_unlock(&poll_cb->mutex);
354 poll_cb->data.used = 1;
355 return MM_CAMERA_OK;
356 }
357
mm_camera_poll_thread_del_ch(mm_camera_obj_t * my_obj,int ch_type)358 int mm_camera_poll_thread_del_ch(mm_camera_obj_t * my_obj, int ch_type)
359 {
360 mm_camera_poll_thread_t *poll_cb = &my_obj->poll_threads[ch_type];
361 mm_camera_sig_evt_t cmd;
362 int len;
363
364 if(poll_cb->data.used == 0){
365 CDBG_ERROR("%s : Thread is Not Active",__func__);
366 return MM_CAMERA_OK;
367 }
368 CDBG("Stop thread for ch_type = %d ",ch_type);
369 cmd.cmd = MM_CAMERA_PIPE_CMD_DEL_CH;
370 poll_cb->data.ch_type = (mm_camera_channel_type_t)ch_type;
371
372 pthread_mutex_lock(&poll_cb->mutex);
373 len = write(poll_cb->data.pfds[1], &cmd, sizeof(cmd));
374 pthread_mutex_unlock(&poll_cb->mutex);
375 poll_cb->data.used = 0;
376 return MM_CAMERA_OK;
377
378 }
379
380
mm_camera_poll_thread_launch(mm_camera_obj_t * my_obj,int ch_type)381 int mm_camera_poll_thread_launch(mm_camera_obj_t * my_obj, int ch_type)
382 {
383 int rc = MM_CAMERA_OK;
384 mm_camera_poll_thread_t *poll_cb = &my_obj->poll_threads[ch_type];
385 if(mm_camera_poll_ch_busy(my_obj, ch_type) > 0) {
386 CDBG_ERROR("%s: err, poll thread of channel %d already running. cam_id=%d\n",
387 __func__, ch_type, my_obj->my_id);
388 return -MM_CAMERA_E_INVALID_OPERATION;
389 }
390 poll_cb->data.ch_type = ch_type;
391 rc = pipe(poll_cb->data.pfds);
392 if(rc < 0) {
393 CDBG_ERROR("%s: camera_id = %d, pipe open rc=%d\n", __func__, my_obj->my_id, rc);
394 rc = - MM_CAMERA_E_GENERAL;
395 }
396 CDBG("%s: ch = %d, poll_type = %d, read fd = %d, write fd = %d",
397 __func__, ch_type, poll_cb->data.poll_type,
398 poll_cb->data.pfds[0], poll_cb->data.pfds[1]);
399 poll_cb->data.my_obj = my_obj;
400 poll_cb->data.used = 0;
401 poll_cb->data.timeoutms = -1; /* Infinite seconds */
402
403 if(ch_type < MM_CAMERA_CH_MAX) {
404 poll_cb->data.poll_type = MM_CAMERA_POLL_TYPE_CH;
405 mm_camera_ch_util_get_stream_objs(my_obj, ch_type,
406 &poll_cb->data.poll_streams[0],
407 &poll_cb->data.poll_streams[1]);
408 } else{
409 poll_cb->data.poll_type = MM_CAMERA_POLL_TYPE_EVT;
410 }
411
412 ALOGV("%s: ch_type = %d, poll_type = %d, read fd = %d, write fd = %d",
413 __func__, ch_type, poll_cb->data.poll_type,
414 poll_cb->data.pfds[0], poll_cb->data.pfds[1]);
415 /* launch the thread */
416 rc = mm_camera_poll_start(my_obj, poll_cb);
417 return rc;
418 }
419
mm_camera_poll_thread_release(mm_camera_obj_t * my_obj,int ch_type)420 int mm_camera_poll_thread_release(mm_camera_obj_t * my_obj, int ch_type)
421 {
422 int rc = MM_CAMERA_OK;
423 mm_camera_poll_thread_t *poll_cb = &my_obj->poll_threads[ch_type];
424 if(MM_CAMERA_POLL_TASK_STATE_MAX == poll_cb->data.state) {
425 CDBG("%s: err, poll thread of channel % is not running. cam_id=%d\n",
426 __func__, ch_type, my_obj->my_id);
427 return -MM_CAMERA_E_INVALID_OPERATION;
428 }
429 rc = mm_camera_poll_stop(my_obj, poll_cb);
430
431 if(poll_cb->data.pfds[0]) {
432 close(poll_cb->data.pfds[0]);
433 }
434 if(poll_cb->data.pfds[1]) {
435 close(poll_cb->data.pfds[1]);
436 }
437 memset(&poll_cb->data, 0, sizeof(poll_cb->data));
438 return MM_CAMERA_OK;
439 }
440
mm_camera_poll_threads_init(mm_camera_obj_t * my_obj)441 void mm_camera_poll_threads_init(mm_camera_obj_t * my_obj)
442 {
443 int i;
444 mm_camera_poll_thread_t *poll_cb;
445
446 for(i = 0; i < MM_CAMERA_POLL_THRAED_MAX; i++) {
447 poll_cb = &my_obj->poll_threads[i];
448 pthread_mutex_init(&poll_cb->mutex, NULL);
449 pthread_cond_init(&poll_cb->cond_v, NULL);
450 }
451 }
452
mm_camera_poll_threads_deinit(mm_camera_obj_t * my_obj)453 void mm_camera_poll_threads_deinit(mm_camera_obj_t * my_obj)
454 {
455 int i;
456 mm_camera_poll_thread_t *poll_cb;
457
458 for(i = 0; i < MM_CAMERA_POLL_THRAED_MAX; i++) {
459 poll_cb = &my_obj->poll_threads[i];
460 if(poll_cb->data.used)
461 mm_camera_poll_stop(my_obj, poll_cb);
462 pthread_mutex_destroy(&poll_cb->mutex);
463 pthread_cond_destroy(&poll_cb->cond_v);
464 memset(poll_cb, 0, sizeof(mm_camera_poll_thread_t));
465 }
466 }
467