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