1 /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30 #include <pthread.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <sys/ioctl.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/prctl.h>
37 #include <fcntl.h>
38 #include <poll.h>
39 #include <unistd.h> // for write, read, usleep, pipe, ...
40 #include <cam_semaphore.h>
41
42 #include "mm_camera_dbg.h"
43 #include "mm_camera_interface.h"
44 #include "mm_camera.h"
45
46 typedef enum {
47 /* poll entries updated */
48 MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED,
49 /* poll entries updated asynchronous */
50 MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC,
51 /* commit updates */
52 MM_CAMERA_PIPE_CMD_COMMIT,
53 /* exit */
54 MM_CAMERA_PIPE_CMD_EXIT,
55 /* max count */
56 MM_CAMERA_PIPE_CMD_MAX
57 } mm_camera_pipe_cmd_type_t;
58
59 typedef enum {
60 MM_CAMERA_POLL_TASK_STATE_STOPPED,
61 MM_CAMERA_POLL_TASK_STATE_POLL, /* polling pid in polling state. */
62 MM_CAMERA_POLL_TASK_STATE_MAX
63 } mm_camera_poll_task_state_type_t;
64
65 typedef struct {
66 uint32_t cmd;
67 mm_camera_event_t event;
68 } mm_camera_sig_evt_t;
69
70
71 /*===========================================================================
72 * FUNCTION : mm_camera_poll_sig_async
73 *
74 * DESCRIPTION: Asynchoronous call to send a command through pipe.
75 *
76 * PARAMETERS :
77 * @poll_cb : ptr to poll thread object
78 * @cmd : command to be sent
79 *
80 * RETURN : int32_t type of status
81 * 0 -- success
82 * -1 -- failure
83 *==========================================================================*/
mm_camera_poll_sig_async(mm_camera_poll_thread_t * poll_cb,uint32_t cmd)84 static int32_t mm_camera_poll_sig_async(mm_camera_poll_thread_t *poll_cb,
85 uint32_t cmd)
86 {
87 /* send through pipe */
88 /* get the mutex */
89 mm_camera_sig_evt_t cmd_evt;
90
91 LOGD("E cmd = %d",cmd);
92 memset(&cmd_evt, 0, sizeof(cmd_evt));
93 cmd_evt.cmd = cmd;
94 pthread_mutex_lock(&poll_cb->mutex);
95 /* reset the statue to false */
96 poll_cb->status = FALSE;
97
98 /* send cmd to worker */
99 ssize_t len = write(poll_cb->pfds[1], &cmd_evt, sizeof(cmd_evt));
100 if (len < 1) {
101 LOGW("len = %lld, errno = %d",
102 (long long int)len, errno);
103 /* Avoid waiting for the signal */
104 pthread_mutex_unlock(&poll_cb->mutex);
105 return 0;
106 }
107 LOGD("begin IN mutex write done, len = %lld",
108 (long long int)len);
109 pthread_mutex_unlock(&poll_cb->mutex);
110 LOGD("X");
111 return 0;
112 }
113
114
115
116
117 /*===========================================================================
118 * FUNCTION : mm_camera_poll_sig
119 *
120 * DESCRIPTION: synchorinzed call to send a command through pipe.
121 *
122 * PARAMETERS :
123 * @poll_cb : ptr to poll thread object
124 * @cmd : command to be sent
125 *
126 * RETURN : int32_t type of status
127 * 0 -- success
128 * -1 -- failure
129 *==========================================================================*/
mm_camera_poll_sig(mm_camera_poll_thread_t * poll_cb,uint32_t cmd)130 static int32_t mm_camera_poll_sig(mm_camera_poll_thread_t *poll_cb,
131 uint32_t cmd)
132 {
133 /* send through pipe */
134 /* get the mutex */
135 mm_camera_sig_evt_t cmd_evt;
136
137 LOGD("E cmd = %d",cmd);
138 memset(&cmd_evt, 0, sizeof(cmd_evt));
139 cmd_evt.cmd = cmd;
140 pthread_mutex_lock(&poll_cb->mutex);
141 /* reset the statue to false */
142 poll_cb->status = FALSE;
143 /* send cmd to worker */
144
145 ssize_t len = write(poll_cb->pfds[1], &cmd_evt, sizeof(cmd_evt));
146 if(len < 1) {
147 LOGW("len = %lld, errno = %d",
148 (long long int)len, errno);
149 /* Avoid waiting for the signal */
150 pthread_mutex_unlock(&poll_cb->mutex);
151 return 0;
152 }
153 LOGD("begin IN mutex write done, len = %lld",
154 (long long int)len);
155 /* wait till worker task gives positive signal */
156 if (FALSE == poll_cb->status) {
157 LOGD("wait");
158 pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex);
159 }
160 /* done */
161 pthread_mutex_unlock(&poll_cb->mutex);
162 LOGD("X");
163 return 0;
164 }
165
166 /*===========================================================================
167 * FUNCTION : mm_camera_poll_sig
168 *
169 * DESCRIPTION: signal the status of done
170 *
171 * PARAMETERS :
172 * @poll_cb : ptr to poll thread object
173 *
174 * RETURN : none
175 *==========================================================================*/
mm_camera_poll_sig_done(mm_camera_poll_thread_t * poll_cb)176 static void mm_camera_poll_sig_done(mm_camera_poll_thread_t *poll_cb)
177 {
178 pthread_mutex_lock(&poll_cb->mutex);
179 poll_cb->status = TRUE;
180 pthread_cond_signal(&poll_cb->cond_v);
181 LOGD("done, in mutex");
182 pthread_mutex_unlock(&poll_cb->mutex);
183 }
184
185 /*===========================================================================
186 * FUNCTION : mm_camera_poll_set_state
187 *
188 * DESCRIPTION: set a polling state
189 *
190 * PARAMETERS :
191 * @poll_cb : ptr to poll thread object
192 * @state : polling state (stopped/polling)
193 *
194 * RETURN : none
195 *==========================================================================*/
mm_camera_poll_set_state(mm_camera_poll_thread_t * poll_cb,mm_camera_poll_task_state_type_t state)196 static void mm_camera_poll_set_state(mm_camera_poll_thread_t *poll_cb,
197 mm_camera_poll_task_state_type_t state)
198 {
199 poll_cb->state = state;
200 }
201
202 /*===========================================================================
203 * FUNCTION : mm_camera_poll_proc_pipe
204 *
205 * DESCRIPTION: polling thread routine to process pipe
206 *
207 * PARAMETERS :
208 * @poll_cb : ptr to poll thread object
209 *
210 * RETURN : none
211 *==========================================================================*/
mm_camera_poll_proc_pipe(mm_camera_poll_thread_t * poll_cb)212 static void mm_camera_poll_proc_pipe(mm_camera_poll_thread_t *poll_cb)
213 {
214 ssize_t read_len;
215 int i;
216 mm_camera_sig_evt_t cmd_evt;
217 read_len = read(poll_cb->pfds[0], &cmd_evt, sizeof(cmd_evt));
218 LOGD("read_fd = %d, read_len = %d, expect_len = %d cmd = %d",
219 poll_cb->pfds[0], (int)read_len, (int)sizeof(cmd_evt), cmd_evt.cmd);
220 switch (cmd_evt.cmd) {
221 case MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED:
222 case MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC:
223 /* we always have index 0 for pipe read */
224 poll_cb->num_fds = 0;
225 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->pfds[0];
226 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
227 poll_cb->num_fds++;
228
229 if (MM_CAMERA_POLL_TYPE_EVT == poll_cb->poll_type &&
230 poll_cb->num_fds < MAX_STREAM_NUM_IN_BUNDLE) {
231 if (poll_cb->poll_entries[0].fd >= 0) {
232 /* fd is valid, we update poll_fds */
233 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[0].fd;
234 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
235 poll_cb->num_fds++;
236 }
237 } else if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type &&
238 poll_cb->num_fds <= MAX_STREAM_NUM_IN_BUNDLE) {
239 for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
240 if(poll_cb->poll_entries[i].fd >= 0) {
241 /* fd is valid, we update poll_fds to this fd */
242 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[i].fd;
243 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
244 poll_cb->num_fds++;
245 } else {
246 /* fd is invalid, we set the entry to -1 to prevent polling.
247 * According to spec, polling will not poll on entry with fd=-1.
248 * If this is not the case, we need to skip these invalid fds
249 * when updating this array.
250 * We still keep fd=-1 in this array because this makes easier to
251 * map cb associated with this fd once incoming data avail by directly
252 * using the index-1(0 is reserved for pipe read, so need to reduce index by 1) */
253 poll_cb->poll_fds[poll_cb->num_fds].fd = -1;
254 poll_cb->poll_fds[poll_cb->num_fds].events = 0;
255 poll_cb->num_fds++;
256 }
257 }
258 }
259 if (cmd_evt.cmd != MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC)
260 mm_camera_poll_sig_done(poll_cb);
261 break;
262
263 case MM_CAMERA_PIPE_CMD_COMMIT:
264 mm_camera_poll_sig_done(poll_cb);
265 break;
266 case MM_CAMERA_PIPE_CMD_EXIT:
267 default:
268 mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_STOPPED);
269 mm_camera_poll_sig_done(poll_cb);
270 break;
271 }
272 }
273
274 /*===========================================================================
275 * FUNCTION : mm_camera_poll_fn
276 *
277 * DESCRIPTION: polling thread routine
278 *
279 * PARAMETERS :
280 * @poll_cb : ptr to poll thread object
281 *
282 * RETURN : none
283 *==========================================================================*/
mm_camera_poll_fn(mm_camera_poll_thread_t * poll_cb)284 static void *mm_camera_poll_fn(mm_camera_poll_thread_t *poll_cb)
285 {
286 int rc = 0, i;
287
288 if (NULL == poll_cb) {
289 LOGE("poll_cb is NULL!\n");
290 return NULL;
291 }
292 LOGD("poll type = %d, num_fd = %d poll_cb = %p\n",
293 poll_cb->poll_type, poll_cb->num_fds,poll_cb);
294 do {
295 for(i = 0; i < poll_cb->num_fds; i++) {
296 poll_cb->poll_fds[i].events = POLLIN|POLLRDNORM|POLLPRI;
297 }
298
299 rc = poll(poll_cb->poll_fds, poll_cb->num_fds, poll_cb->timeoutms);
300 if(rc > 0) {
301 if ((poll_cb->poll_fds[0].revents & POLLIN) &&
302 (poll_cb->poll_fds[0].revents & POLLRDNORM)) {
303 /* if we have data on pipe, we only process pipe in this iteration */
304 LOGD("cmd received on pipe\n");
305 mm_camera_poll_proc_pipe(poll_cb);
306 } else {
307 for(i=1; i<poll_cb->num_fds; i++) {
308 /* Checking for ctrl events */
309 if ((poll_cb->poll_type == MM_CAMERA_POLL_TYPE_EVT) &&
310 (poll_cb->poll_fds[i].revents & POLLPRI)) {
311 LOGD("mm_camera_evt_notify\n");
312 if (NULL != poll_cb->poll_entries[i-1].notify_cb) {
313 poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data);
314 }
315 }
316
317 if ((MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) &&
318 (poll_cb->poll_fds[i].revents & POLLIN) &&
319 (poll_cb->poll_fds[i].revents & POLLRDNORM)) {
320 LOGD("mm_stream_data_notify\n");
321 if (NULL != poll_cb->poll_entries[i-1].notify_cb) {
322 poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data);
323 }
324 }
325 }
326 }
327 } else {
328 /* in error case sleep 10 us and then continue. hard coded here */
329 usleep(10);
330 continue;
331 }
332 } while ((poll_cb != NULL) && (poll_cb->state == MM_CAMERA_POLL_TASK_STATE_POLL));
333 return NULL;
334 }
335
336 /*===========================================================================
337 * FUNCTION : mm_camera_poll_thread
338 *
339 * DESCRIPTION: polling thread entry function
340 *
341 * PARAMETERS :
342 * @data : ptr to poll thread object
343 *
344 * RETURN : none
345 *==========================================================================*/
mm_camera_poll_thread(void * data)346 static void *mm_camera_poll_thread(void *data)
347 {
348 mm_camera_poll_thread_t *poll_cb = (mm_camera_poll_thread_t *)data;
349
350 mm_camera_cmd_thread_name(poll_cb->threadName);
351 /* add pipe read fd into poll first */
352 poll_cb->poll_fds[poll_cb->num_fds++].fd = poll_cb->pfds[0];
353
354 mm_camera_poll_sig_done(poll_cb);
355 mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_POLL);
356 return mm_camera_poll_fn(poll_cb);
357 }
358
359 /*===========================================================================
360 * FUNCTION : mm_camera_poll_thread
361 *
362 * DESCRIPTION: notify the polling thread that entries for polling fd have
363 * been updated
364 *
365 * PARAMETERS :
366 * @poll_cb : ptr to poll thread object
367 *
368 * RETURN : none
369 *==========================================================================*/
mm_camera_poll_thread_notify_entries_updated(mm_camera_poll_thread_t * poll_cb)370 int32_t mm_camera_poll_thread_notify_entries_updated(mm_camera_poll_thread_t * poll_cb)
371 {
372 /* send poll entries updated signal to poll thread */
373 return mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
374 }
375
376 /*===========================================================================
377 * FUNCTION : mm_camera_poll_thread_commit_updates
378 *
379 * DESCRIPTION: sync with all previously pending async updates
380 *
381 * PARAMETERS :
382 * @poll_cb : ptr to poll thread object
383 *
384 * RETURN : int32_t type of status
385 * 0 -- success
386 * -1 -- failure
387 *==========================================================================*/
mm_camera_poll_thread_commit_updates(mm_camera_poll_thread_t * poll_cb)388 int32_t mm_camera_poll_thread_commit_updates(mm_camera_poll_thread_t * poll_cb)
389 {
390 return mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_COMMIT);
391 }
392
393 /*===========================================================================
394 * FUNCTION : mm_camera_poll_thread_add_poll_fd
395 *
396 * DESCRIPTION: add a new fd into polling thread
397 *
398 * PARAMETERS :
399 * @poll_cb : ptr to poll thread object
400 * @handler : stream handle if channel data polling thread,
401 * 0 if event polling thread
402 * @fd : file descriptor need to be added into polling thread
403 * @notify_cb : callback function to handle if any notify from fd
404 * @userdata : user data ptr
405 * @call_type : Whether its Synchronous or Asynchronous call
406 *
407 * RETURN : none
408 *==========================================================================*/
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,mm_camera_call_type_t call_type)409 int32_t mm_camera_poll_thread_add_poll_fd(mm_camera_poll_thread_t * poll_cb,
410 uint32_t handler,
411 int32_t fd,
412 mm_camera_poll_notify_t notify_cb,
413 void* userdata,
414 mm_camera_call_type_t call_type)
415 {
416 int32_t rc = -1;
417 uint8_t idx = 0;
418
419 if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) {
420 /* get stream idx from handler if CH type */
421 idx = mm_camera_util_get_index_by_handler(handler);
422 } else {
423 /* for EVT type, only idx=0 is valid */
424 idx = 0;
425 }
426
427 if (MAX_STREAM_NUM_IN_BUNDLE > idx) {
428 poll_cb->poll_entries[idx].fd = fd;
429 poll_cb->poll_entries[idx].handler = handler;
430 poll_cb->poll_entries[idx].notify_cb = notify_cb;
431 poll_cb->poll_entries[idx].user_data = userdata;
432 /* send poll entries updated signal to poll thread */
433 if (call_type == mm_camera_sync_call ) {
434 rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
435 } else {
436 rc = mm_camera_poll_sig_async(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC );
437 }
438 } else {
439 LOGE("invalid handler %d (%d)", handler, idx);
440 }
441 return rc;
442 }
443
444 /*===========================================================================
445 * FUNCTION : mm_camera_poll_thread_del_poll_fd
446 *
447 * DESCRIPTION: delete a fd from polling thread
448 *
449 * PARAMETERS :
450 * @poll_cb : ptr to poll thread object
451 * @handler : stream handle if channel data polling thread,
452 * 0 if event polling thread
453 *
454 * RETURN : int32_t type of status
455 * 0 -- success
456 * -1 -- failure
457 *==========================================================================*/
mm_camera_poll_thread_del_poll_fd(mm_camera_poll_thread_t * poll_cb,uint32_t handler,mm_camera_call_type_t call_type)458 int32_t mm_camera_poll_thread_del_poll_fd(mm_camera_poll_thread_t * poll_cb,
459 uint32_t handler,
460 mm_camera_call_type_t call_type)
461 {
462 int32_t rc = -1;
463 uint8_t idx = 0;
464
465 if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) {
466 /* get stream idx from handler if CH type */
467 idx = mm_camera_util_get_index_by_handler(handler);
468 } else {
469 /* for EVT type, only idx=0 is valid */
470 idx = 0;
471 }
472
473 if ((MAX_STREAM_NUM_IN_BUNDLE > idx) &&
474 (handler == poll_cb->poll_entries[idx].handler)) {
475 /* reset poll entry */
476 poll_cb->poll_entries[idx].fd = -1; /* set fd to invalid */
477 poll_cb->poll_entries[idx].handler = 0;
478 poll_cb->poll_entries[idx].notify_cb = NULL;
479
480 /* send poll entries updated signal to poll thread */
481 if (call_type == mm_camera_sync_call ) {
482 rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
483 } else {
484 rc = mm_camera_poll_sig_async(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC );
485 }
486 } else {
487 if ((MAX_STREAM_NUM_IN_BUNDLE <= idx) ||
488 (poll_cb->poll_entries[idx].handler != 0)) {
489 LOGE("invalid handler %d (%d)", poll_cb->poll_entries[idx].handler,
490 idx);
491 rc = -1;
492 } else {
493 LOGW("invalid handler %d (%d)", handler, idx);
494 rc = 0;
495 }
496 }
497
498 return rc;
499 }
500
mm_camera_poll_thread_launch(mm_camera_poll_thread_t * poll_cb,mm_camera_poll_thread_type_t poll_type)501 int32_t mm_camera_poll_thread_launch(mm_camera_poll_thread_t * poll_cb,
502 mm_camera_poll_thread_type_t poll_type)
503 {
504 int32_t rc = 0;
505 size_t i = 0, cnt = 0;
506 poll_cb->poll_type = poll_type;
507
508 //Initialize poll_fds
509 cnt = sizeof(poll_cb->poll_fds) / sizeof(poll_cb->poll_fds[0]);
510 for (i = 0; i < cnt; i++) {
511 poll_cb->poll_fds[i].fd = -1;
512 }
513 //Initialize poll_entries
514 cnt = sizeof(poll_cb->poll_entries) / sizeof(poll_cb->poll_entries[0]);
515 for (i = 0; i < cnt; i++) {
516 poll_cb->poll_entries[i].fd = -1;
517 }
518 //Initialize pipe fds
519 poll_cb->pfds[0] = -1;
520 poll_cb->pfds[1] = -1;
521 rc = pipe(poll_cb->pfds);
522 if(rc < 0) {
523 LOGE("pipe open rc=%d\n", rc);
524 return -1;
525 }
526
527 poll_cb->timeoutms = -1; /* Infinite seconds */
528
529 LOGD("poll_type = %d, read fd = %d, write fd = %d timeout = %d",
530 poll_cb->poll_type,
531 poll_cb->pfds[0], poll_cb->pfds[1],poll_cb->timeoutms);
532
533 pthread_mutex_init(&poll_cb->mutex, NULL);
534 pthread_cond_init(&poll_cb->cond_v, NULL);
535
536 /* launch the thread */
537 pthread_mutex_lock(&poll_cb->mutex);
538 poll_cb->status = 0;
539 pthread_create(&poll_cb->pid, NULL, mm_camera_poll_thread, (void *)poll_cb);
540 if(!poll_cb->status) {
541 pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex);
542 }
543
544 pthread_mutex_unlock(&poll_cb->mutex);
545 LOGD("End");
546 return rc;
547 }
548
mm_camera_poll_thread_release(mm_camera_poll_thread_t * poll_cb)549 int32_t mm_camera_poll_thread_release(mm_camera_poll_thread_t *poll_cb)
550 {
551 int32_t rc = 0;
552 if(MM_CAMERA_POLL_TASK_STATE_STOPPED == poll_cb->state) {
553 LOGE("err, poll thread is not running.\n");
554 return rc;
555 }
556
557 /* send exit signal to poll thread */
558 mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_EXIT);
559 /* wait until poll thread exits */
560 if (pthread_join(poll_cb->pid, NULL) != 0) {
561 LOGD("pthread dead already\n");
562 }
563
564 /* close pipe */
565 if(poll_cb->pfds[0] >= 0) {
566 close(poll_cb->pfds[0]);
567 }
568 if(poll_cb->pfds[1] >= 0) {
569 close(poll_cb->pfds[1]);
570 }
571
572 pthread_mutex_destroy(&poll_cb->mutex);
573 pthread_cond_destroy(&poll_cb->cond_v);
574 memset(poll_cb, 0, sizeof(mm_camera_poll_thread_t));
575 poll_cb->pfds[0] = -1;
576 poll_cb->pfds[1] = -1;
577 return rc;
578 }
579
mm_camera_cmd_thread(void * data)580 static void *mm_camera_cmd_thread(void *data)
581 {
582 int running = 1;
583 int ret;
584 mm_camera_cmd_thread_t *cmd_thread =
585 (mm_camera_cmd_thread_t *)data;
586 mm_camera_cmdcb_t* node = NULL;
587
588 mm_camera_cmd_thread_name(cmd_thread->threadName);
589 do {
590 do {
591 ret = cam_sem_wait(&cmd_thread->cmd_sem);
592 if (ret != 0 && errno != EINVAL) {
593 LOGE("cam_sem_wait error (%s)",
594 strerror(errno));
595 return NULL;
596 }
597 } while (ret != 0);
598
599 /* we got notified about new cmd avail in cmd queue */
600 node = (mm_camera_cmdcb_t*)cam_queue_deq(&cmd_thread->cmd_queue);
601 while (node != NULL) {
602 switch (node->cmd_type) {
603 case MM_CAMERA_CMD_TYPE_EVT_CB:
604 case MM_CAMERA_CMD_TYPE_DATA_CB:
605 case MM_CAMERA_CMD_TYPE_REQ_DATA_CB:
606 case MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB:
607 case MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY:
608 case MM_CAMERA_CMD_TYPE_START_ZSL:
609 case MM_CAMERA_CMD_TYPE_STOP_ZSL:
610 case MM_CAMERA_CMD_TYPE_GENERAL:
611 case MM_CAMERA_CMD_TYPE_FLUSH_QUEUE:
612 if (NULL != cmd_thread->cb) {
613 cmd_thread->cb(node, cmd_thread->user_data);
614 }
615 break;
616 case MM_CAMERA_CMD_TYPE_EXIT:
617 default:
618 running = 0;
619 break;
620 }
621 free(node);
622 node = (mm_camera_cmdcb_t*)cam_queue_deq(&cmd_thread->cmd_queue);
623 } /* (node != NULL) */
624 } while (running);
625 return NULL;
626 }
627
mm_camera_cmd_thread_launch(mm_camera_cmd_thread_t * cmd_thread,mm_camera_cmd_cb_t cb,void * user_data)628 int32_t mm_camera_cmd_thread_launch(mm_camera_cmd_thread_t * cmd_thread,
629 mm_camera_cmd_cb_t cb,
630 void* user_data)
631 {
632 int32_t rc = 0;
633
634 cam_sem_init(&cmd_thread->cmd_sem, 0);
635 cam_sem_init(&cmd_thread->sync_sem, 0);
636 cam_queue_init(&cmd_thread->cmd_queue);
637 cmd_thread->cb = cb;
638 cmd_thread->user_data = user_data;
639 cmd_thread->is_active = TRUE;
640
641 /* launch the thread */
642 pthread_create(&cmd_thread->cmd_pid,
643 NULL,
644 mm_camera_cmd_thread,
645 (void *)cmd_thread);
646 return rc;
647 }
648
mm_camera_cmd_thread_name(const char * name)649 int32_t mm_camera_cmd_thread_name(const char* name)
650 {
651 int32_t rc = 0;
652 /* name the thread */
653 if (name && strlen(name))
654 prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
655 return rc;
656 }
657
658
mm_camera_cmd_thread_stop(mm_camera_cmd_thread_t * cmd_thread)659 int32_t mm_camera_cmd_thread_stop(mm_camera_cmd_thread_t * cmd_thread)
660 {
661 int32_t rc = 0;
662 mm_camera_cmdcb_t* node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
663 if (NULL == node) {
664 LOGE("No memory for mm_camera_cmdcb_t");
665 return -1;
666 }
667
668 memset(node, 0, sizeof(mm_camera_cmdcb_t));
669 node->cmd_type = MM_CAMERA_CMD_TYPE_EXIT;
670
671 cam_queue_enq(&cmd_thread->cmd_queue, node);
672 cam_sem_post(&cmd_thread->cmd_sem);
673
674 /* wait until cmd thread exits */
675 if (pthread_join(cmd_thread->cmd_pid, NULL) != 0) {
676 LOGD("pthread dead already\n");
677 }
678 return rc;
679 }
680
mm_camera_cmd_thread_destroy(mm_camera_cmd_thread_t * cmd_thread)681 int32_t mm_camera_cmd_thread_destroy(mm_camera_cmd_thread_t * cmd_thread)
682 {
683 int32_t rc = 0;
684 cam_queue_deinit(&cmd_thread->cmd_queue);
685 cam_sem_destroy(&cmd_thread->cmd_sem);
686 cam_sem_destroy(&cmd_thread->sync_sem);
687 memset(cmd_thread, 0, sizeof(mm_camera_cmd_thread_t));
688 return rc;
689 }
690
mm_camera_cmd_thread_release(mm_camera_cmd_thread_t * cmd_thread)691 int32_t mm_camera_cmd_thread_release(mm_camera_cmd_thread_t * cmd_thread)
692 {
693 int32_t rc = 0;
694 rc = mm_camera_cmd_thread_stop(cmd_thread);
695 if (0 == rc) {
696 rc = mm_camera_cmd_thread_destroy(cmd_thread);
697 }
698 return rc;
699 }
700