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