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
42volatile uint32_t gCamHal3LogLevel = 1;
43
44namespace qcamera {
45
46/*===========================================================================
47 * FUNCTION   : getInstance
48 *
49 * DESCRIPTION: Get and create the QCameraFlash singleton.
50 *
51 * PARAMETERS : None
52 *
53 * RETURN     : None
54 *==========================================================================*/
55QCameraFlash& 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 *==========================================================================*/
70QCameraFlash::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 *==========================================================================*/
88QCameraFlash::~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 *==========================================================================*/
109int32_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 *==========================================================================*/
135int32_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 = -ENOSYS;
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 *==========================================================================*/
221int32_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 *==========================================================================*/
270int32_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 *==========================================================================*/
315int32_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 *==========================================================================*/
376int32_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