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_flash_cfg_data_t cfg; 179 struct msm_flash_init_info_t init_info; 180 memset(&cfg, 0, sizeof(struct msm_flash_cfg_data_t)); 181 memset(&init_info, 0, sizeof(struct msm_flash_init_info_t)); 182 init_info.flash_driver_type = FLASH_DRIVER_DEFAULT; 183 cfg.cfg.flash_init_info = &init_info; 184 cfg.cfg_type = CFG_FLASH_INIT; 185 retVal = ioctl(m_flashFds[camera_id], 186 VIDIOC_MSM_FLASH_CFG, 187 &cfg); 188 if (retVal < 0) { 189 ALOGE("%s: Unable to init flash for camera id: %d", 190 __func__, 191 camera_id); 192 close(m_flashFds[camera_id]); 193 m_flashFds[camera_id] = -1; 194 } 195 196 /* wait for PMIC to init */ 197 usleep(5000); 198 } 199 } 200 201 CDBG("%s: X, retVal = %d", __func__, retVal); 202 return retVal; 203 } 204 205 /*=========================================================================== 206 * FUNCTION : setFlashMode 207 * 208 * DESCRIPTION: Turn on or off the flash associated with a given handle. 209 * This function is blocking until the operation completes or 210 * fails. 211 * 212 * PARAMETERS : 213 * @camera_id : Camera id of the flash 214 * @on : Whether to turn flash on (true) or off (false) 215 * 216 * RETURN : 217 * 0 : success 218 * -EINVAL : No camera present at camera_id, or it is not inited. 219 * -EALREADY: Flash is already in requested state 220 *==========================================================================*/ 221 int32_t QCameraFlash::setFlashMode(const int camera_id, const bool mode) 222 { 223 int32_t retVal = 0; 224 struct msm_flash_cfg_data_t cfg; 225 226 if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { 227 ALOGE("%s: Invalid camera id: %d", __func__, camera_id); 228 retVal = -EINVAL; 229 } else if (mode == m_flashOn[camera_id]) { 230 CDBG("%s: flash %d is already in requested state: %d", 231 __func__, 232 camera_id, 233 mode); 234 retVal = -EALREADY; 235 } else if (m_flashFds[camera_id] < 0) { 236 ALOGE("%s: called for uninited flash: %d", __func__, camera_id); 237 retVal = -EINVAL; 238 } else { 239 memset(&cfg, 0, sizeof(struct msm_flash_cfg_data_t)); 240 for (int i = 0; i < MAX_LED_TRIGGERS; i++) 241 cfg.flash_current[i] = QCAMERA_TORCH_CURRENT_VALUE; 242 cfg.cfg_type = mode ? CFG_FLASH_LOW: CFG_FLASH_OFF; 243 244 retVal = ioctl(m_flashFds[camera_id], 245 VIDIOC_MSM_FLASH_CFG, 246 &cfg); 247 if (retVal < 0) 248 ALOGE("%s: Unable to change flash mode to %d for camera id: %d", 249 __func__, mode, camera_id); 250 else 251 m_flashOn[camera_id] = mode; 252 } 253 return retVal; 254 } 255 256 /*=========================================================================== 257 * FUNCTION : deinitFlash 258 * 259 * DESCRIPTION: Release the flash unit associated with a given camera 260 * position. This function is blocking until the operation 261 * completes or fails. 262 * 263 * PARAMETERS : 264 * @camera_id : Camera id of the flash. 265 * 266 * RETURN : 267 * 0 : success 268 * -EINVAL : No camera present at camera_id or not inited. 269 *==========================================================================*/ 270 int32_t QCameraFlash::deinitFlash(const int camera_id) 271 { 272 int32_t retVal = 0; 273 274 if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { 275 ALOGE("%s: Invalid camera id: %d", __func__, camera_id); 276 retVal = -EINVAL; 277 } else if (m_flashFds[camera_id] < 0) { 278 ALOGE("%s: called deinitFlash for uninited flash", __func__); 279 retVal = -EINVAL; 280 } else { 281 setFlashMode(camera_id, false); 282 283 struct msm_flash_cfg_data_t cfg; 284 cfg.cfg_type = CFG_FLASH_RELEASE; 285 retVal = ioctl(m_flashFds[camera_id], 286 VIDIOC_MSM_FLASH_CFG, 287 &cfg); 288 if (retVal < 0) { 289 ALOGE("%s: Failed to release flash for camera id: %d", 290 __func__, 291 camera_id); 292 } 293 294 close(m_flashFds[camera_id]); 295 m_flashFds[camera_id] = -1; 296 } 297 298 return retVal; 299 } 300 301 /*=========================================================================== 302 * FUNCTION : reserveFlashForCamera 303 * 304 * DESCRIPTION: Give control of the flash to the camera, and notify 305 * framework that the flash has become unavailable. 306 * 307 * PARAMETERS : 308 * @camera_id : Camera id of the flash. 309 * 310 * RETURN : 311 * 0 : success 312 * -EINVAL : No camera present at camera_id or not inited. 313 * -ENOSYS : No callback available for torch_mode_status_change. 314 *==========================================================================*/ 315 int32_t QCameraFlash::reserveFlashForCamera(const int camera_id) 316 { 317 int32_t retVal = 0; 318 319 if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { 320 ALOGE("%s: Invalid camera id: %d", __func__, camera_id); 321 retVal = -EINVAL; 322 } else if (m_cameraOpen[camera_id]) { 323 CDBG("%s: Flash already reserved for camera id: %d", 324 __func__, 325 camera_id); 326 } else { 327 if (m_flashOn[camera_id]) { 328 setFlashMode(camera_id, false); 329 deinitFlash(camera_id); 330 } 331 m_cameraOpen[camera_id] = true; 332 333 bool hasFlash = false; 334 char flashNode[QCAMERA_MAX_FILEPATH_LENGTH]; 335 336 QCamera3HardwareInterface::getFlashInfo(camera_id, 337 hasFlash, 338 flashNode); 339 340 if (m_callbacks == NULL || 341 m_callbacks->torch_mode_status_change == NULL) { 342 ALOGE("%s: Callback is not defined!", __func__); 343 retVal = -ENOSYS; 344 } else if (!hasFlash) { 345 CDBG("%s: Suppressing callback " 346 "because no flash exists for camera id: %d", 347 __func__, 348 camera_id); 349 } else { 350 char cameraIdStr[STRING_LENGTH_OF_64_BIT_NUMBER]; 351 snprintf(cameraIdStr, STRING_LENGTH_OF_64_BIT_NUMBER, 352 "%d", camera_id); 353 m_callbacks->torch_mode_status_change(m_callbacks, 354 cameraIdStr, 355 TORCH_MODE_STATUS_NOT_AVAILABLE); 356 } 357 } 358 359 return retVal; 360 } 361 362 /*=========================================================================== 363 * FUNCTION : releaseFlashFromCamera 364 * 365 * DESCRIPTION: Release control of the flash from the camera, and notify 366 * framework that the flash has become available. 367 * 368 * PARAMETERS : 369 * @camera_id : Camera id of the flash. 370 * 371 * RETURN : 372 * 0 : success 373 * -EINVAL : No camera present at camera_id or not inited. 374 * -ENOSYS : No callback available for torch_mode_status_change. 375 *==========================================================================*/ 376 int32_t QCameraFlash::releaseFlashFromCamera(const int camera_id) 377 { 378 int32_t retVal = 0; 379 380 if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { 381 ALOGE("%s: Invalid camera id: %d", __func__, camera_id); 382 retVal = -EINVAL; 383 } else if (!m_cameraOpen[camera_id]) { 384 CDBG("%s: Flash not reserved for camera id: %d", 385 __func__, 386 camera_id); 387 } else { 388 m_cameraOpen[camera_id] = false; 389 390 bool hasFlash = false; 391 char flashNode[QCAMERA_MAX_FILEPATH_LENGTH]; 392 393 QCamera3HardwareInterface::getFlashInfo(camera_id, 394 hasFlash, 395 flashNode); 396 397 if (m_callbacks == NULL || 398 m_callbacks->torch_mode_status_change == NULL) { 399 ALOGE("%s: Callback is not defined!", __func__); 400 retVal = -ENOSYS; 401 } else if (!hasFlash) { 402 CDBG("%s: Suppressing callback " 403 "because no flash exists for camera id: %d", 404 __func__, 405 camera_id); 406 } else { 407 char cameraIdStr[STRING_LENGTH_OF_64_BIT_NUMBER]; 408 snprintf(cameraIdStr, STRING_LENGTH_OF_64_BIT_NUMBER, 409 "%d", camera_id); 410 m_callbacks->torch_mode_status_change(m_callbacks, 411 cameraIdStr, 412 TORCH_MODE_STATUS_AVAILABLE_OFF); 413 } 414 } 415 416 return retVal; 417 } 418 419 }; // namespace qcamera 420