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