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  *==========================================================================*/
getInstance()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  *==========================================================================*/
QCameraFlash()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  *==========================================================================*/
~QCameraFlash()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  *==========================================================================*/
registerCallbacks(const camera_module_callbacks_t * callbacks)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  *==========================================================================*/
initFlash(const int camera_id)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  *==========================================================================*/
setFlashMode(const int camera_id,const bool mode)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  *==========================================================================*/
deinitFlash(const int camera_id)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  *==========================================================================*/
reserveFlashForCamera(const int camera_id)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  *==========================================================================*/
releaseFlashFromCamera(const int camera_id)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