1 /* Copyright (c) 2012-2013, The Linux Foundataion. 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 <utils/Errors.h>
31 #include <utils/Log.h>
32 #include <malloc.h>
33 #include <sys/prctl.h>
34 #include "QCameraCmdThread.h"
35 
36 using namespace android;
37 
38 namespace qcamera {
39 
40 /*===========================================================================
41  * FUNCTION   : QCameraCmdThread
42  *
43  * DESCRIPTION: default constructor of QCameraCmdThread
44  *
45  * PARAMETERS : None
46  *
47  * RETURN     : None
48  *==========================================================================*/
QCameraCmdThread()49 QCameraCmdThread::QCameraCmdThread() :
50     cmd_queue()
51 {
52     cmd_pid = 0;
53     cam_sem_init(&sync_sem, 0);
54     cam_sem_init(&cmd_sem, 0);
55 }
56 
57 /*===========================================================================
58  * FUNCTION   : ~QCameraCmdThread
59  *
60  * DESCRIPTION: deconstructor of QCameraCmdThread
61  *
62  * PARAMETERS : None
63  *
64  * RETURN     : None
65  *==========================================================================*/
~QCameraCmdThread()66 QCameraCmdThread::~QCameraCmdThread()
67 {
68     cam_sem_destroy(&sync_sem);
69     cam_sem_destroy(&cmd_sem);
70 }
71 
72 /*===========================================================================
73  * FUNCTION   : launch
74  *
75  * DESCRIPTION: launch Cmd Thread
76  *
77  * PARAMETERS :
78  *   @start_routine : thread routine function ptr
79  *   @user_data     : user data ptr
80  *
81  * RETURN     : int32_t type of status
82  *              NO_ERROR  -- success
83  *              none-zero failure code
84  *==========================================================================*/
launch(void * (* start_routine)(void *),void * user_data)85 int32_t QCameraCmdThread::launch(void *(*start_routine)(void *),
86                                  void* user_data)
87 {
88     /* launch the thread */
89     pthread_create(&cmd_pid,
90                    NULL,
91                    start_routine,
92                    user_data);
93     return NO_ERROR;
94 }
95 
96 /*===========================================================================
97  * FUNCTION   : setName
98  *
99  * DESCRIPTION: name the cmd thread
100  *
101  * PARAMETERS :
102  *   @name : desired name for the thread
103  *
104  * RETURN     : int32_t type of status
105  *              NO_ERROR  -- success
106  *              none-zero failure code
107  *==========================================================================*/
setName(const char * name)108 int32_t QCameraCmdThread::setName(const char* name)
109 {
110     /* name the thread */
111     prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
112     return NO_ERROR;
113 }
114 
115 /*===========================================================================
116  * FUNCTION   : sendCmd
117  *
118  * DESCRIPTION: send a command to the Cmd Thread
119  *
120  * PARAMETERS :
121  *   @cmd     : command to be executed.
122  *   @sync_cmd: flag to indicate if this is a synchorinzed cmd. If true, this call
123  *              will wait until signal is set after the command is completed.
124  *   @priority: flag to indicate if this is a cmd with priority. If true, the cmd
125  *              will be enqueued to the head with priority.
126  *
127  * RETURN     : int32_t type of status
128  *              NO_ERROR  -- success
129  *              none-zero failure code
130  *==========================================================================*/
sendCmd(camera_cmd_type_t cmd,uint8_t sync_cmd,uint8_t priority)131 int32_t QCameraCmdThread::sendCmd(camera_cmd_type_t cmd, uint8_t sync_cmd, uint8_t priority)
132 {
133     camera_cmd_t *node = (camera_cmd_t *)malloc(sizeof(camera_cmd_t));
134     if (NULL == node) {
135         ALOGE("%s: No memory for camera_cmd_t", __func__);
136         return NO_MEMORY;
137     }
138     memset(node, 0, sizeof(camera_cmd_t));
139     node->cmd = cmd;
140 
141     if (priority) {
142         cmd_queue.enqueueWithPriority((void *)node);
143     } else {
144         cmd_queue.enqueue((void *)node);
145     }
146     cam_sem_post(&cmd_sem);
147 
148     /* if is a sync call, need to wait until it returns */
149     if (sync_cmd) {
150         cam_sem_wait(&sync_sem);
151     }
152     return NO_ERROR;
153 }
154 
155 /*===========================================================================
156  * FUNCTION   : getCmd
157  *
158  * DESCRIPTION: dequeue a cmommand from cmd queue
159  *
160  * PARAMETERS : None
161  *
162  * RETURN     : cmd dequeued
163  *==========================================================================*/
getCmd()164 camera_cmd_type_t QCameraCmdThread::getCmd()
165 {
166     camera_cmd_type_t cmd = CAMERA_CMD_TYPE_NONE;
167     camera_cmd_t *node = (camera_cmd_t *)cmd_queue.dequeue();
168     if (NULL == node) {
169         ALOGD("%s: No notify avail", __func__);
170         return CAMERA_CMD_TYPE_NONE;
171     } else {
172         cmd = node->cmd;
173         free(node);
174     }
175     return cmd;
176 }
177 
178 /*===========================================================================
179  * FUNCTION   : exit
180  *
181  * DESCRIPTION: exit the CMD thread
182  *
183  * PARAMETERS : None
184  *
185  * RETURN     : int32_t type of status
186  *              NO_ERROR  -- success
187  *              none-zero failure code
188  *==========================================================================*/
exit()189 int32_t QCameraCmdThread::exit()
190 {
191     int32_t rc = NO_ERROR;
192 
193     if (cmd_pid == 0) {
194         return rc;
195     }
196 
197     rc = sendCmd(CAMERA_CMD_TYPE_EXIT, 0, 1);
198     if (NO_ERROR != rc) {
199         ALOGE("%s: Error during exit, rc = %d", __func__, rc);
200         return rc;
201     }
202 
203     /* wait until cmd thread exits */
204     if (pthread_join(cmd_pid, NULL) != 0) {
205         ALOGD("%s: pthread dead already\n", __func__);
206     }
207     cmd_pid = 0;
208     return rc;
209 }
210 
211 }; // namespace qcamera
212