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