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