1 /* Copyright (c) 2015, 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 <stdio.h> 31 #include <fcntl.h> 32 #include <linux/media.h> 33 #include <media/msmb_camera.h> 34 #include <media/msm_cam_sensor.h> 35 #include <utils/Log.h> 36 37 #include "HAL3/QCamera3HWI.h" 38 #include "QCameraFlash.h" 39 40 #define STRING_LENGTH_OF_64_BIT_NUMBER 21 41 42 volatile uint32_t gCamHal3LogLevel = 1; 43 44 namespace qcamera { 45 46 /*=========================================================================== 47 * FUNCTION : getInstance 48 * 49 * DESCRIPTION: Get and create the QCameraFlash singleton. 50 * 51 * PARAMETERS : None 52 * 53 * RETURN : None 54 *==========================================================================*/ 55 QCameraFlash& QCameraFlash::getInstance() 56 { 57 static QCameraFlash flashInstance; 58 return flashInstance; 59 } 60 61 /*=========================================================================== 62 * FUNCTION : QCameraFlash 63 * 64 * DESCRIPTION: default constructor of QCameraFlash 65 * 66 * PARAMETERS : None 67 * 68 * RETURN : None 69 *==========================================================================*/ 70 QCameraFlash::QCameraFlash() : m_callbacks(NULL) 71 { 72 memset(&m_flashOn, 0, sizeof(m_flashOn)); 73 memset(&m_cameraOpen, 0, sizeof(m_cameraOpen)); 74 for (int pos = 0; pos < MM_CAMERA_MAX_NUM_SENSORS; pos++) { 75 m_flashFds[pos] = -1; 76 } 77 } 78 79 /*=========================================================================== 80 * FUNCTION : ~QCameraFlash 81 * 82 * DESCRIPTION: deconstructor of QCameraFlash 83 * 84 * PARAMETERS : None 85 * 86 * RETURN : None 87 *==========================================================================*/ 88 QCameraFlash::~QCameraFlash() 89 { 90 for (int pos = 0; pos < MM_CAMERA_MAX_NUM_SENSORS; pos++) { 91 if (m_flashFds[pos] >= 0) 92 { 93 setFlashMode(pos, false); 94 close(m_flashFds[pos]); 95 m_flashFds[pos] = -1; 96 } 97 } 98 } 99 100 /*=========================================================================== 101 * FUNCTION : registerCallbacks 102 * 103 * DESCRIPTION: provide flash module with reference to callbacks to framework 104 * 105 * PARAMETERS : None 106 * 107 * RETURN : None 108 *==========================================================================*/ 109 int32_t QCameraFlash::registerCallbacks( 110 const camera_module_callbacks_t* callbacks) 111 { 112 int32_t retVal = 0; 113 m_callbacks = callbacks; 114 return retVal; 115 } 116 117 /*=========================================================================== 118 * FUNCTION : initFlash 119 * 120 * DESCRIPTION: Reserve and initialize the flash unit associated with a 121 * given camera id. This function is blocking until the 122 * operation completes or fails. Each flash unit can be "inited" 123 * by only one process at a time. 124 * 125 * PARAMETERS : 126 * @camera_id : Camera id of the flash. 127 * 128 * RETURN : 129 * 0 : success 130 * -EBUSY : The flash unit or the resource needed to turn on the 131 * the flash is busy, typically because the flash is 132 * already in use. 133 * -EINVAL : No flash present at camera_id. 134 *==========================================================================*/ 135 int32_t QCameraFlash::initFlash(const int camera_id) 136 { 137 int32_t retVal = 0; 138 bool hasFlash = false; 139 char flashNode[QCAMERA_MAX_FILEPATH_LENGTH]; 140 char flashPath[QCAMERA_MAX_FILEPATH_LENGTH] = "/dev/"; 141 142 if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { 143 ALOGE("%s: Invalid camera id: %d", __func__, camera_id); 144 return -EINVAL; 145 } 146 147 QCamera3HardwareInterface::getFlashInfo(camera_id, 148 hasFlash, 149 flashNode); 150 151 strlcat(flashPath, 152 flashNode, 153 sizeof(flashPath)); 154 155 if (!hasFlash) { 156 ALOGE("%s: No flash available for camera id: %d", 157 __func__, 158 camera_id); 159 retVal = -EINVAL; 160 } else if (m_cameraOpen[camera_id]) { 161 ALOGE("%s: Camera in use for camera id: %d", 162 __func__, 163 camera_id); 164 retVal = -EBUSY; 165 } else if (m_flashFds[camera_id] >= 0) { 166 CDBG("%s: Flash is already inited for camera id: %d", 167 __func__, 168 camera_id); 169 } else { 170 m_flashFds[camera_id] = open(flashPath, O_RDWR | O_NONBLOCK); 171 172 if (m_flashFds[camera_id] < 0) { 173 ALOGE("%s: Unable to open node '%s'", 174 __func__, 175 flashPath); 176 retVal = -EBUSY; 177 } else { 178 struct msm_camera_led_cfg_t cfg; 179 cfg.cfgtype = MSM_CAMERA_LED_INIT; 180 retVal = ioctl(m_flashFds[camera_id], 181 VIDIOC_MSM_FLASH_LED_DATA_CFG, 182 &cfg); 183 if (retVal < 0) { 184 ALOGE("%s: Unable to init flash for camera id: %d", 185 __func__, 186 camera_id); 187 close(m_flashFds[camera_id]); 188 m_flashFds[camera_id] = -1; 189 } 190 } 191 } 192 193 return retVal; 194 } 195 196 /*=========================================================================== 197 * FUNCTION : setFlashMode 198 * 199 * DESCRIPTION: Turn on or off the flash associated with a given handle. 200 * This function is blocking until the operation completes or 201 * fails. 202 * 203 * PARAMETERS : 204 * @camera_id : Camera id of the flash 205 * @on : Whether to turn flash on (true) or off (false) 206 * 207 * RETURN : 208 * 0 : success 209 * -EINVAL : No camera present at camera_id, or it is not inited. 210 * -EALREADY: Flash is already in requested state 211 *==========================================================================*/ 212 int32_t QCameraFlash::setFlashMode(const int camera_id, const bool mode) 213 { 214 int32_t retVal = 0; 215 struct msm_camera_led_cfg_t cfg; 216 217 if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { 218 ALOGE("%s: Invalid camera id: %d", __func__, camera_id); 219 retVal = -EINVAL; 220 } else if (mode == m_flashOn[camera_id]) { 221 CDBG("%s: flash %d is already in requested state: %d", 222 __func__, 223 camera_id, 224 mode); 225 retVal = -EALREADY; 226 } else if (m_flashFds[camera_id] < 0) { 227 ALOGE("%s: called for uninited flash: %d", __func__, camera_id); 228 retVal = -EINVAL; 229 } else { 230 cfg.cfgtype = mode ? MSM_CAMERA_LED_LOW : MSM_CAMERA_LED_OFF; 231 retVal = ioctl(m_flashFds[camera_id], 232 VIDIOC_MSM_FLASH_LED_DATA_CFG, 233 &cfg); 234 if (retVal == 0) { 235 m_flashOn[camera_id] = mode; 236 } 237 } 238 return retVal; 239 } 240 241 /*=========================================================================== 242 * FUNCTION : deinitFlash 243 * 244 * DESCRIPTION: Release the flash unit associated with a given camera 245 * position. This function is blocking until the operation 246 * completes or fails. 247 * 248 * PARAMETERS : 249 * @camera_id : Camera id of the flash. 250 * 251 * RETURN : 252 * 0 : success 253 * -EINVAL : No camera present at camera_id or not inited. 254 *==========================================================================*/ 255 int32_t QCameraFlash::deinitFlash(const int camera_id) 256 { 257 int32_t retVal = 0; 258 259 if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { 260 ALOGE("%s: Invalid camera id: %d", __func__, camera_id); 261 retVal = -EINVAL; 262 } else if (m_flashFds[camera_id] < 0) { 263 ALOGE("%s: called deinitFlash for uninited flash", __func__); 264 retVal = -EINVAL; 265 } else { 266 setFlashMode(camera_id, false); 267 268 struct msm_camera_led_cfg_t cfg; 269 cfg.cfgtype = MSM_CAMERA_LED_RELEASE; 270 retVal = ioctl(m_flashFds[camera_id], 271 VIDIOC_MSM_FLASH_LED_DATA_CFG, 272 &cfg); 273 if (retVal < 0) { 274 ALOGE("%s: Failed to release flash for camera id: %d", 275 __func__, 276 camera_id); 277 } 278 279 close(m_flashFds[camera_id]); 280 m_flashFds[camera_id] = -1; 281 } 282 283 return retVal; 284 } 285 286 /*=========================================================================== 287 * FUNCTION : reserveFlashForCamera 288 * 289 * DESCRIPTION: Give control of the flash to the camera, and notify 290 * framework that the flash has become unavailable. 291 * 292 * PARAMETERS : 293 * @camera_id : Camera id of the flash. 294 * 295 * RETURN : 296 * 0 : success 297 * -EINVAL : No camera present at camera_id or not inited. 298 * -ENOSYS : No callback available for torch_mode_status_change. 299 *==========================================================================*/ 300 int32_t QCameraFlash::reserveFlashForCamera(const int camera_id) 301 { 302 int32_t retVal = 0; 303 304 if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { 305 ALOGE("%s: Invalid camera id: %d", __func__, camera_id); 306 retVal = -EINVAL; 307 } else if (m_cameraOpen[camera_id]) { 308 CDBG("%s: Flash already reserved for camera id: %d", 309 __func__, 310 camera_id); 311 } else { 312 if (m_flashOn[camera_id]) { 313 setFlashMode(camera_id, false); 314 deinitFlash(camera_id); 315 } 316 m_cameraOpen[camera_id] = true; 317 318 bool hasFlash = false; 319 char flashNode[QCAMERA_MAX_FILEPATH_LENGTH]; 320 321 QCamera3HardwareInterface::getFlashInfo(camera_id, 322 hasFlash, 323 flashNode); 324 325 if (m_callbacks == NULL || 326 m_callbacks->torch_mode_status_change == NULL) { 327 ALOGE("%s: Callback is not defined!", __func__); 328 retVal = -ENOSYS; 329 } else if (!hasFlash) { 330 CDBG("%s: Suppressing callback " 331 "because no flash exists for camera id: %d", 332 __func__, 333 camera_id); 334 } else { 335 char cameraIdStr[STRING_LENGTH_OF_64_BIT_NUMBER]; 336 snprintf(cameraIdStr, STRING_LENGTH_OF_64_BIT_NUMBER, 337 "%d", camera_id); 338 m_callbacks->torch_mode_status_change(m_callbacks, 339 cameraIdStr, 340 TORCH_MODE_STATUS_NOT_AVAILABLE); 341 } 342 } 343 344 return retVal; 345 } 346 347 /*=========================================================================== 348 * FUNCTION : releaseFlashFromCamera 349 * 350 * DESCRIPTION: Release control of the flash from the camera, and notify 351 * framework that the flash has become available. 352 * 353 * PARAMETERS : 354 * @camera_id : Camera id of the flash. 355 * 356 * RETURN : 357 * 0 : success 358 * -EINVAL : No camera present at camera_id or not inited. 359 * -ENOSYS : No callback available for torch_mode_status_change. 360 *==========================================================================*/ 361 int32_t QCameraFlash::releaseFlashFromCamera(const int camera_id) 362 { 363 int32_t retVal = 0; 364 365 if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { 366 ALOGE("%s: Invalid camera id: %d", __func__, camera_id); 367 retVal = -EINVAL; 368 } else if (!m_cameraOpen[camera_id]) { 369 CDBG("%s: Flash not reserved for camera id: %d", 370 __func__, 371 camera_id); 372 } else { 373 m_cameraOpen[camera_id] = false; 374 375 bool hasFlash = false; 376 char flashNode[QCAMERA_MAX_FILEPATH_LENGTH]; 377 378 QCamera3HardwareInterface::getFlashInfo(camera_id, 379 hasFlash, 380 flashNode); 381 382 if (m_callbacks == NULL || 383 m_callbacks->torch_mode_status_change == NULL) { 384 ALOGE("%s: Callback is not defined!", __func__); 385 retVal = -ENOSYS; 386 } else if (!hasFlash) { 387 CDBG("%s: Suppressing callback " 388 "because no flash exists for camera id: %d", 389 __func__, 390 camera_id); 391 } else { 392 char cameraIdStr[STRING_LENGTH_OF_64_BIT_NUMBER]; 393 snprintf(cameraIdStr, STRING_LENGTH_OF_64_BIT_NUMBER, 394 "%d", camera_id); 395 m_callbacks->torch_mode_status_change(m_callbacks, 396 cameraIdStr, 397 TORCH_MODE_STATUS_AVAILABLE_OFF); 398 } 399 } 400 401 return retVal; 402 } 403 404 }; // namespace qcamera 405