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