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