• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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