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_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  *==========================================================================*/
setFlashMode(const int camera_id,const bool mode)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  *==========================================================================*/
deinitFlash(const int camera_id)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  *==========================================================================*/
reserveFlashForCamera(const int camera_id)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  *==========================================================================*/
releaseFlashFromCamera(const int camera_id)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