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