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