• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (c) 2012, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above
10       copyright notice, this list of conditions and the following
11       disclaimer in the documentation and/or other materials provided
12       with the distribution.
13     * Neither the name of The Linux Foundation nor the names of its
14       contributors may be used to endorse or promote products derived
15       from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include <pthread.h>
31 #include <errno.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <semaphore.h>
37 
38 #include "mm_camera_dbg.h"
39 #include "mm_camera_interface.h"
40 #include "mm_camera.h"
41 
42 #if 0
43 #undef CDBG
44 #undef LOG_TAG
45 #define CDBG ALOGE
46 #define LOG_TAG "NotifyLogs"
47 #endif
48 
mm_camera_queue_init(mm_camera_queue_t * queue)49 int32_t mm_camera_queue_init(mm_camera_queue_t* queue)
50 {
51     pthread_mutex_init(&queue->lock, NULL);
52     cam_list_init(&queue->head.list);
53     queue->size = 0;
54     return 0;
55 }
56 
mm_camera_queue_enq(mm_camera_queue_t * queue,void * data)57 int32_t mm_camera_queue_enq(mm_camera_queue_t* queue, void* data)
58 {
59     mm_camera_q_node_t* node =
60         (mm_camera_q_node_t *)malloc(sizeof(mm_camera_q_node_t));
61     if (NULL == node) {
62         CDBG_ERROR("%s: No memory for mm_camera_q_node_t", __func__);
63         return -1;
64     }
65 
66     memset(node, 0, sizeof(mm_camera_q_node_t));
67     node->data = data;
68 
69     pthread_mutex_lock(&queue->lock);
70     cam_list_add_tail_node(&node->list, &queue->head.list);
71     queue->size++;
72     pthread_mutex_unlock(&queue->lock);
73 
74     return 0;
75 
76 }
77 
mm_camera_queue_deq(mm_camera_queue_t * queue)78 void* mm_camera_queue_deq(mm_camera_queue_t* queue)
79 {
80     mm_camera_q_node_t* node = NULL;
81     void* data = NULL;
82     struct cam_list *head = NULL;
83     struct cam_list *pos = NULL;
84 
85     pthread_mutex_lock(&queue->lock);
86     head = &queue->head.list;
87     pos = head->next;
88     if (pos != head) {
89         node = member_of(pos, mm_camera_q_node_t, list);
90         cam_list_del_node(&node->list);
91         queue->size--;
92     }
93     pthread_mutex_unlock(&queue->lock);
94 
95     if (NULL != node) {
96         data = node->data;
97         free(node);
98     }
99 
100     return data;
101 }
102 
mm_camera_queue_deinit(mm_camera_queue_t * queue)103 int32_t mm_camera_queue_deinit(mm_camera_queue_t* queue)
104 {
105     mm_camera_queue_flush(queue);
106     pthread_mutex_destroy(&queue->lock);
107     return 0;
108 }
109 
mm_camera_queue_flush(mm_camera_queue_t * queue)110 int32_t mm_camera_queue_flush(mm_camera_queue_t* queue)
111 {
112     mm_camera_q_node_t* node = NULL;
113     void* data = NULL;
114     struct cam_list *head = NULL;
115     struct cam_list *pos = NULL;
116 
117     pthread_mutex_lock(&queue->lock);
118     head = &queue->head.list;
119     pos = head->next;
120 
121     while(pos != head) {
122         node = member_of(pos, mm_camera_q_node_t, list);
123         cam_list_del_node(&node->list);
124         queue->size--;
125 
126         /* TODO later to consider ptr inside data */
127         /* for now we only assume there is no ptr inside data
128          * so we free data directly */
129         if (NULL != node->data) {
130             free(node->data);
131         }
132         free(node);
133         pos = pos->next;
134     }
135     queue->size = 0;
136     pthread_mutex_unlock(&queue->lock);
137     return 0;
138 }
139 
mm_camera_cmd_thread(void * data)140 static void *mm_camera_cmd_thread(void *data)
141 {
142     int rc = 0;
143     int running = 1;
144     int ret;
145     mm_camera_cmd_thread_t *cmd_thread =
146                 (mm_camera_cmd_thread_t *)data;
147     mm_camera_cmdcb_t* node = NULL;
148 
149     do {
150         do {
151             ret = sem_wait(&cmd_thread->cmd_sem);
152             if (ret != 0 && errno != EINVAL) {
153                 CDBG_ERROR("%s: sem_wait error (%s)",
154                            __func__, strerror(errno));
155                 return NULL;
156             }
157         } while (ret != 0);
158 
159         /* we got notified about new cmd avail in cmd queue */
160         node = (mm_camera_cmdcb_t*)mm_camera_queue_deq(&cmd_thread->cmd_queue);
161         if (node != NULL) {
162             switch (node->cmd_type) {
163             case MM_CAMERA_CMD_TYPE_EVT_CB:
164             case MM_CAMERA_CMD_TYPE_DATA_CB:
165             case MM_CAMERA_CMD_TYPE_ASYNC_CB:
166             case MM_CAMERA_CMD_TYPE_REQ_DATA_CB:
167                 if (NULL != cmd_thread->cb) {
168                     cmd_thread->cb(node, cmd_thread->user_data);
169                 }
170                 break;
171             case MM_CAMERA_CMD_TYPE_EXIT:
172             default:
173                 running = 0;
174                 break;
175             }
176             free(node);
177         }
178     } while (running);
179     return NULL;
180 }
181 
mm_camera_cmd_thread_launch(mm_camera_cmd_thread_t * cmd_thread,mm_camera_cmd_cb_t cb,void * user_data)182 int32_t mm_camera_cmd_thread_launch(mm_camera_cmd_thread_t * cmd_thread,
183                                     mm_camera_cmd_cb_t cb,
184                                     void* user_data)
185 {
186     int32_t rc = 0;
187 
188     sem_init(&cmd_thread->cmd_sem, 0, 0);
189     mm_camera_queue_init(&cmd_thread->cmd_queue);
190     cmd_thread->cb = cb;
191     cmd_thread->user_data = user_data;
192 
193     /* launch the thread */
194     pthread_create(&cmd_thread->cmd_pid,
195                    NULL,
196                    mm_camera_cmd_thread,
197                    (void *)cmd_thread);
198     return rc;
199 }
200 
mm_camera_cmd_thread_release(mm_camera_cmd_thread_t * cmd_thread)201 int32_t mm_camera_cmd_thread_release(mm_camera_cmd_thread_t * cmd_thread)
202 {
203     int32_t rc = 0;
204     mm_camera_buf_info_t  buf_info;
205     mm_camera_cmdcb_t* node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
206     if (NULL == node) {
207         CDBG_ERROR("%s: No memory for mm_camera_cmdcb_t", __func__);
208         return -1;
209     }
210 
211     memset(node, 0, sizeof(mm_camera_cmdcb_t));
212     node->cmd_type = MM_CAMERA_CMD_TYPE_EXIT;
213 
214     mm_camera_queue_enq(&cmd_thread->cmd_queue, node);
215     sem_post(&cmd_thread->cmd_sem);
216 
217     /* wait until cmd thread exits */
218     if (pthread_join(cmd_thread->cmd_pid, NULL) != 0) {
219         CDBG("%s: pthread dead already\n", __func__);
220     }
221     mm_camera_queue_deinit(&cmd_thread->cmd_queue);
222 
223     sem_destroy(&cmd_thread->cmd_sem);
224     memset(cmd_thread, 0, sizeof(mm_camera_cmd_thread_t));
225     return rc;
226 }
227 
228