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