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