| /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| |
| // System dependencies |
| #include <stdio.h> |
| #include <fcntl.h> |
| #include <media/msm_cam_sensor.h> |
| |
| // Camera dependencies |
| #include "HAL3/QCamera3HWI.h" |
| #include "QCameraFlash.h" |
| |
| extern "C" { |
| #include "mm_camera_dbg.h" |
| } |
| |
| #define STRING_LENGTH_OF_64_BIT_NUMBER 21 |
| |
| volatile uint32_t gCamHal3LogLevel = 1; |
| |
| namespace qcamera { |
| |
| /*=========================================================================== |
| * FUNCTION : getInstance |
| * |
| * DESCRIPTION: Get and create the QCameraFlash singleton. |
| * |
| * PARAMETERS : None |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| QCameraFlash& QCameraFlash::getInstance() |
| { |
| static QCameraFlash flashInstance; |
| return flashInstance; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : QCameraFlash |
| * |
| * DESCRIPTION: default constructor of QCameraFlash |
| * |
| * PARAMETERS : None |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| QCameraFlash::QCameraFlash() : m_callbacks(NULL) |
| { |
| memset(&m_flashOn, 0, sizeof(m_flashOn)); |
| memset(&m_cameraOpen, 0, sizeof(m_cameraOpen)); |
| for (int pos = 0; pos < MM_CAMERA_MAX_NUM_SENSORS; pos++) { |
| m_flashFds[pos] = -1; |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : ~QCameraFlash |
| * |
| * DESCRIPTION: deconstructor of QCameraFlash |
| * |
| * PARAMETERS : None |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| QCameraFlash::~QCameraFlash() |
| { |
| for (int pos = 0; pos < MM_CAMERA_MAX_NUM_SENSORS; pos++) { |
| if (m_flashFds[pos] >= 0) |
| { |
| setFlashMode(pos, false); |
| close(m_flashFds[pos]); |
| m_flashFds[pos] = -1; |
| } |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : registerCallbacks |
| * |
| * DESCRIPTION: provide flash module with reference to callbacks to framework |
| * |
| * PARAMETERS : None |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| int32_t QCameraFlash::registerCallbacks( |
| const camera_module_callbacks_t* callbacks) |
| { |
| int32_t retVal = 0; |
| m_callbacks = callbacks; |
| return retVal; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : initFlash |
| * |
| * DESCRIPTION: Reserve and initialize the flash unit associated with a |
| * given camera id. This function is blocking until the |
| * operation completes or fails. Each flash unit can be "inited" |
| * by only one process at a time. |
| * |
| * PARAMETERS : |
| * @camera_id : Camera id of the flash. |
| * |
| * RETURN : |
| * 0 : success |
| * -EBUSY : The flash unit or the resource needed to turn on the |
| * the flash is busy, typically because the flash is |
| * already in use. |
| * -EINVAL : No flash present at camera_id. |
| *==========================================================================*/ |
| int32_t QCameraFlash::initFlash(const int camera_id) |
| { |
| int32_t retVal = 0; |
| bool hasFlash = false; |
| char flashNode[QCAMERA_MAX_FILEPATH_LENGTH]; |
| char flashPath[QCAMERA_MAX_FILEPATH_LENGTH] = "/dev/"; |
| |
| if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { |
| LOGE("Invalid camera id: %d", camera_id); |
| return -EINVAL; |
| } |
| |
| QCamera3HardwareInterface::getFlashInfo(camera_id, |
| hasFlash, |
| flashNode); |
| |
| strlcat(flashPath, |
| flashNode, |
| sizeof(flashPath)); |
| |
| if (!hasFlash) { |
| LOGE("No flash available for camera id: %d", |
| camera_id); |
| retVal = -ENOSYS; |
| } else if (m_cameraOpen[camera_id]) { |
| LOGE("Camera in use for camera id: %d", |
| camera_id); |
| retVal = -EBUSY; |
| } else if (m_flashFds[camera_id] >= 0) { |
| LOGD("Flash is already inited for camera id: %d", |
| camera_id); |
| } else { |
| m_flashFds[camera_id] = open(flashPath, O_RDWR | O_NONBLOCK); |
| |
| if (m_flashFds[camera_id] < 0) { |
| LOGE("Unable to open node '%s'", |
| flashPath); |
| retVal = -EBUSY; |
| } else { |
| struct msm_flash_cfg_data_t cfg; |
| struct msm_flash_init_info_t init_info; |
| memset(&cfg, 0, sizeof(struct msm_flash_cfg_data_t)); |
| memset(&init_info, 0, sizeof(struct msm_flash_init_info_t)); |
| init_info.flash_driver_type = FLASH_DRIVER_DEFAULT; |
| cfg.cfg.flash_init_info = &init_info; |
| cfg.cfg_type = CFG_FLASH_INIT; |
| retVal = ioctl(m_flashFds[camera_id], |
| VIDIOC_MSM_FLASH_CFG, |
| &cfg); |
| if (retVal < 0) { |
| LOGE("Unable to init flash for camera id: %d", |
| camera_id); |
| close(m_flashFds[camera_id]); |
| m_flashFds[camera_id] = -1; |
| } |
| |
| /* wait for PMIC to init */ |
| usleep(5000); |
| } |
| } |
| |
| LOGD("X, retVal = %d", retVal); |
| return retVal; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : setFlashMode |
| * |
| * DESCRIPTION: Turn on or off the flash associated with a given handle. |
| * This function is blocking until the operation completes or |
| * fails. |
| * |
| * PARAMETERS : |
| * @camera_id : Camera id of the flash |
| * @on : Whether to turn flash on (true) or off (false) |
| * |
| * RETURN : |
| * 0 : success |
| * -EINVAL : No camera present at camera_id, or it is not inited. |
| * -EALREADY: Flash is already in requested state |
| *==========================================================================*/ |
| int32_t QCameraFlash::setFlashMode(const int camera_id, const bool mode) |
| { |
| int32_t retVal = 0; |
| struct msm_flash_cfg_data_t cfg; |
| |
| if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { |
| LOGE("Invalid camera id: %d", camera_id); |
| retVal = -EINVAL; |
| } else if (mode == m_flashOn[camera_id]) { |
| LOGD("flash %d is already in requested state: %d", |
| camera_id, |
| mode); |
| retVal = -EALREADY; |
| } else if (m_flashFds[camera_id] < 0) { |
| LOGE("called for uninited flash: %d", camera_id); |
| retVal = -EINVAL; |
| } else { |
| memset(&cfg, 0, sizeof(struct msm_flash_cfg_data_t)); |
| for (int i = 0; i < MAX_LED_TRIGGERS; i++) |
| cfg.flash_current[i] = QCAMERA_TORCH_CURRENT_VALUE; |
| cfg.cfg_type = mode ? CFG_FLASH_LOW: CFG_FLASH_OFF; |
| |
| retVal = ioctl(m_flashFds[camera_id], |
| VIDIOC_MSM_FLASH_CFG, |
| &cfg); |
| if (retVal < 0) { |
| LOGE("Unable to change flash mode to %d for camera id: %d", |
| mode, camera_id); |
| } else |
| { |
| m_flashOn[camera_id] = mode; |
| } |
| } |
| return retVal; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : deinitFlash |
| * |
| * DESCRIPTION: Release the flash unit associated with a given camera |
| * position. This function is blocking until the operation |
| * completes or fails. |
| * |
| * PARAMETERS : |
| * @camera_id : Camera id of the flash. |
| * |
| * RETURN : |
| * 0 : success |
| * -EINVAL : No camera present at camera_id or not inited. |
| *==========================================================================*/ |
| int32_t QCameraFlash::deinitFlash(const int camera_id) |
| { |
| int32_t retVal = 0; |
| |
| if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { |
| LOGE("Invalid camera id: %d", camera_id); |
| retVal = -EINVAL; |
| } else if (m_flashFds[camera_id] < 0) { |
| LOGE("called deinitFlash for uninited flash"); |
| retVal = -EINVAL; |
| } else { |
| setFlashMode(camera_id, false); |
| |
| struct msm_flash_cfg_data_t cfg; |
| cfg.cfg_type = CFG_FLASH_RELEASE; |
| retVal = ioctl(m_flashFds[camera_id], |
| VIDIOC_MSM_FLASH_CFG, |
| &cfg); |
| if (retVal < 0) { |
| LOGE("Failed to release flash for camera id: %d", |
| camera_id); |
| } |
| |
| close(m_flashFds[camera_id]); |
| m_flashFds[camera_id] = -1; |
| } |
| |
| return retVal; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : reserveFlashForCamera |
| * |
| * DESCRIPTION: Give control of the flash to the camera, and notify |
| * framework that the flash has become unavailable. |
| * |
| * PARAMETERS : |
| * @camera_id : Camera id of the flash. |
| * |
| * RETURN : |
| * 0 : success |
| * -EINVAL : No camera present at camera_id or not inited. |
| * -ENOSYS : No callback available for torch_mode_status_change. |
| *==========================================================================*/ |
| int32_t QCameraFlash::reserveFlashForCamera(const int camera_id) |
| { |
| int32_t retVal = 0; |
| |
| if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { |
| LOGE("Invalid camera id: %d", camera_id); |
| retVal = -EINVAL; |
| } else if (m_cameraOpen[camera_id]) { |
| LOGD("Flash already reserved for camera id: %d", |
| camera_id); |
| } else { |
| if (m_flashOn[camera_id]) { |
| setFlashMode(camera_id, false); |
| deinitFlash(camera_id); |
| } |
| m_cameraOpen[camera_id] = true; |
| |
| bool hasFlash = false; |
| char flashNode[QCAMERA_MAX_FILEPATH_LENGTH]; |
| |
| QCamera3HardwareInterface::getFlashInfo(camera_id, |
| hasFlash, |
| flashNode); |
| |
| if (m_callbacks == NULL || |
| m_callbacks->torch_mode_status_change == NULL) { |
| LOGE("Callback is not defined!"); |
| retVal = -ENOSYS; |
| } else if (!hasFlash) { |
| LOGD("Suppressing callback " |
| "because no flash exists for camera id: %d", |
| camera_id); |
| } else { |
| char cameraIdStr[STRING_LENGTH_OF_64_BIT_NUMBER]; |
| snprintf(cameraIdStr, STRING_LENGTH_OF_64_BIT_NUMBER, |
| "%d", camera_id); |
| m_callbacks->torch_mode_status_change(m_callbacks, |
| cameraIdStr, |
| TORCH_MODE_STATUS_NOT_AVAILABLE); |
| } |
| } |
| |
| return retVal; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : releaseFlashFromCamera |
| * |
| * DESCRIPTION: Release control of the flash from the camera, and notify |
| * framework that the flash has become available. |
| * |
| * PARAMETERS : |
| * @camera_id : Camera id of the flash. |
| * |
| * RETURN : |
| * 0 : success |
| * -EINVAL : No camera present at camera_id or not inited. |
| * -ENOSYS : No callback available for torch_mode_status_change. |
| *==========================================================================*/ |
| int32_t QCameraFlash::releaseFlashFromCamera(const int camera_id) |
| { |
| int32_t retVal = 0; |
| |
| if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { |
| LOGE("Invalid camera id: %d", camera_id); |
| retVal = -EINVAL; |
| } else if (!m_cameraOpen[camera_id]) { |
| LOGD("Flash not reserved for camera id: %d", |
| camera_id); |
| } else { |
| m_cameraOpen[camera_id] = false; |
| |
| bool hasFlash = false; |
| char flashNode[QCAMERA_MAX_FILEPATH_LENGTH]; |
| |
| QCamera3HardwareInterface::getFlashInfo(camera_id, |
| hasFlash, |
| flashNode); |
| |
| if (m_callbacks == NULL || |
| m_callbacks->torch_mode_status_change == NULL) { |
| LOGE("Callback is not defined!"); |
| retVal = -ENOSYS; |
| } else if (!hasFlash) { |
| LOGD("Suppressing callback " |
| "because no flash exists for camera id: %d", |
| camera_id); |
| } else { |
| char cameraIdStr[STRING_LENGTH_OF_64_BIT_NUMBER]; |
| snprintf(cameraIdStr, STRING_LENGTH_OF_64_BIT_NUMBER, |
| "%d", camera_id); |
| m_callbacks->torch_mode_status_change(m_callbacks, |
| cameraIdStr, |
| TORCH_MODE_STATUS_AVAILABLE_OFF); |
| } |
| } |
| |
| return retVal; |
| } |
| |
| }; // namespace qcamera |