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