• 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 <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