S5PV210 ANDROID 为摄像头增加闪光灯

首先找到android拍照的时候所执行的函数代码在:

packages/apps/Camera/src/com/android/camera/Camera.java

[java] view plain copy
  1. mCameraDevice.setParameters(mParameters);  
  2. mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback,  
  3.         mPostViewPictureCallback, new JpegPictureCallback(loc));  
  4. mPreviewing = false;  


据我理解,这里就是拍照的时候所执行的,而这里应该是调用的camera库里的takepicture下面我们找到库文件:

device/samsung/proprietary/libcamera

库文件就在这里,下面我们进入SeccameraHWInterface.cpp文件查找takepicture如下:

[cpp] view plain copy
  1. status_t CameraHardwareSec::takePicture()  
  2. {  
  3.     LOGV("%s :", __func__);  
  4.   
  5.     stopPreview();  
  6.   
  7.     Mutex::Autolock lock(mStateLock);  
  8.     if (mCaptureInProgress) {  
  9.         LOGE("%s : capture already in progress", __func__);  
  10.         return INVALID_OPERATION;  
  11.     }  
  12.   
  13.     if (mPictureThread->run("CameraPictureThread", PRIORITY_DEFAULT) != NO_ERROR) {  
  14.         LOGE("%s : couldn't run picture thread", __func__);  
  15.         return INVALID_OPERATION;  
  16.     }  
  17.     mCaptureInProgress = true;  
  18.   
  19.     return NO_ERROR;  
  20. }  


里面的mPictureThread->run就是拍照的东西了,具体我就不分析了。接下来我们找下闪光灯的接口

在SecCamera.h里你会发现下面三个函数接口:

[cpp] view plain copy
  1. bool            getFlashSupport(void);  
  2. int             setFlashMode(int flash_mode);  
  3. int             getFlashMode(void);  

其中setFlashMode即为设置闪光灯的接口,找到这个函数

在SecCamera.cpp里如下:

[cpp] view plain copy
  1. int SecCamera::setFlashMode(int flash_mode)  
  2. {  
  3.     LOGV("%s(flash_mode(%d))", __func__, flash_mode);  
  4.   
  5.     if (flash_mode <= FLASH_MODE_BASE || FLASH_MODE_MAX <= flash_mode) {  
  6.         LOGE("ERR(%s):Invalid flash_mode (%d)", __func__, flash_mode);  
  7.         return -1;  
  8.     }  
  9.   
  10.     if (m_params->flash_mode != flash_mode) {  
  11.         m_params->flash_mode = flash_mode;  
  12.         if (m_flag_camera_start) {  
  13.             if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FLASH_MODE, flash_mode) < 0) {  
  14.                 LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FLASH_MODE", __func__);  
  15.                 return -1;  
  16.             }  
  17.         }  
  18.     }  
  19.     return 0;  
  20. }  

这里又会调用fimc_v4l2_s_ctrl函数代码如下:

[cpp] view plain copy
  1. static int fimc_v4l2_s_ctrl(int fp, unsigned int id, unsigned int value)  
  2. {  
  3.     struct v4l2_control ctrl;  
  4.     int ret;  
  5.   
  6.     ctrl.id = id;  
  7.     ctrl.value = value;  
  8.     //LOGD("%s :--------------------------value is %d",__func__,value);//add dao  
  9.     ret = ioctl(fp, VIDIOC_S_CTRL, &ctrl);  
  10.     if (ret < 0) {  
  11.         LOGE("ERR(%s):VIDIOC_S_CTRL(id = %#x (%d), value = %d) failed ret = %d\n",  
  12.              __func__, id, id-V4L2_CID_PRIVATE_BASE, value, ret);  
  13.   
  14.         return ret;  
  15.     }  
  16.   
  17.     return ctrl.value;  
  18. }  


在这里进行了ioctl下面我们到内核里面去看看。
在内核下面的drivers/media/video/v4l2-ioctl.c有如下代码:

[cpp] view plain copy
  1. case VIDIOC_S_CTRL:  
  2. {  
  3.     struct v4l2_control *p = arg;  
  4.     struct v4l2_ext_controls ctrls;  
  5.     struct v4l2_ext_control ctrl;  
  6.   
  7.     if (!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)  
  8.         break;  
  9.   
  10.     dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);  
  11.   
  12.     if (ops->vidioc_s_ctrl) {  
  13.         ret = ops->vidioc_s_ctrl(file, fh, p);  
  14.         break;  
  15.     }  
  16.     if (!ops->vidioc_s_ext_ctrls)  
  17.         break;  
  18.   
  19.     ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);  
  20.     ctrls.count = 1;  
  21.     ctrls.controls = &ctrl;  
  22.     ctrl.id = p->id;  
  23.     ctrl.value = p->value;  
  24.     if (check_ext_ctrls(&ctrls, 1))  
  25.         ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);  
  26.     break;  
  27. }  


很快我就想到了摄像头驱动里有这样的设置:

代码在drivers/media/video/samsung/ficm/ov2640.c

[cpp] view plain copy
  1. static const struct v4l2_subdev_core_ops ov2640_core_ops = {  
  2.     .init = ov2640_init,    /* initializing API */  
  3.     .s_config = ov2640_s_config,    /* Fetch platform data */  
  4.     .queryctrl = ov2640_queryctrl,  
  5.     .querymenu = ov2640_querymenu,  
  6.     .g_ctrl = ov2640_g_ctrl,  
  7.     .s_ctrl = ov2640_s_ctrl,  
  8. };  


这里有一个s_ctrl,事实证明确实是执行了ov2640_s_ctrl至于怎么调用过来的没有深入研究。

下面我们看到这个函数开始的部分

[cpp] view plain copy
  1. static int ov2640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)  
  2. {  
  3.     struct i2c_client *client = v4l2_get_subdevdata(sd);  
  4.     struct ov2640_state *state = to_state(sd);  
  5.     int err = 0;  
  6.     int value = ctrl->value;  
  7.       
  8.     switch (ctrl->id) {  
  9.   
  10.     case V4L2_CID_CAMERA_FLASH_MODE:  
  11.     case V4L2_CID_CAMERA_BRIGHTNESS:  
  12.         break;  


第一个就是闪光灯的选项,文件系统里面设置闪光灯的就是传入的这个,可没作任何处理就直接跳出了。下面我在增加闪光灯驱动:

[cpp] view plain copy
  1. static int flash_ctrl(int mode)  
  2. {  
  3.     int err;  
  4.   
  5.     err = gpio_request(S5PV210_GPD0(2), "GPD0"); //power  
  6.     if (err) {  
  7.         printk(KERN_ERR "failed to request GPD0 for "  
  8.                 "flashlight power control\n");  
  9.         return err;  
  10.     }  
  11.     gpio_direction_output(S5PV210_GPD0(2), 1);  
  12.   
  13.     err = gpio_request(S5PV210_GPD0(3), "GPD0"); //mode  
  14.     if (err) {  
  15.         printk(KERN_ERR "failed to request GPD0 for "  
  16.                 "flashlight mode control\n");  
  17.         return err;  
  18.     }  
  19.     /* 
  20.         high is flash mode,low is torch mode 
  21.     */  
  22.     switch(mode) {  
  23.         case FLASH_MODE_ON:  
  24.             gpio_direction_output(S5PV210_GPD0(3), 1);  
  25.             break;  
  26.         case FLASH_MODE_TORCH:  
  27.             gpio_direction_output(S5PV210_GPD0(3), 0);  
  28.             break;  
  29.         default:  
  30.             break;  
  31.     }  
  32.     mdelay(100);  
  33.     gpio_direction_output(S5PV210_GPD0(2), 0);  
  34.   
  35.     gpio_free(S5PV210_GPD0(2));  
  36.     gpio_free(S5PV210_GPD0(3));  
  37.     return err;  
  38. }  


电路我就不发出来了,流程搞清楚了,大家就好弄了。

修改ov2640_s_ctrl为:

[cpp] view plain copy
  1. case V4L2_CID_CAMERA_FLASH_MODE:  
  2.   
  3.     err = flash_ctrl(value);  
  4.     break;  


只修改相关设置,其它的不变。现在接口已经全部写好,在回到文件系统里。
在拍照之前加上闪光灯设置,这个可以在库里设置也可以在app里设置,我直接在库里设置的,路径我就不在打了,前面的相关函数已经全部给出了,如下:

[cpp] view plain copy
  1. status_t CameraHardwareSec::takePicture()  
  2. {  
  3.     LOGV("%s :", __func__);  
  4.   
  5.     stopPreview();  
  6.   
  7.     Mutex::Autolock lock(mStateLock);  
  8.     if (mCaptureInProgress) {  
  9.         LOGE("%s : capture already in progress", __func__);  
  10.         return INVALID_OPERATION;  
  11.     }  
  12.   
  13.     mSecCamera->setFlashMode(FLASH_MODE_ON);//add by dao  
  14.   
  15.     if (mPictureThread->run("CameraPictureThread", PRIORITY_DEFAULT) != NO_ERROR) {  
  16.         LOGE("%s : couldn't run picture thread", __func__);  
  17.         return INVALID_OPERATION;  
  18.     }  
  19.     mCaptureInProgress = true;  
  20.   
  21.     return NO_ERROR;  
  22. }  


在拍照之前设置FlashMode为FLASH_MODE_ON模式,结果发现这样不行,搞了半天终于发现问题所在,直接把setFlashMode改为如下:

[cpp] view plain copy
  1. int SecCamera::setFlashMode(int flash_mode)  
  2. {  
  3.     LOGV("%s(flash_mode(%d))", __func__, flash_mode);  
  4.   
  5.     fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FLASH_MODE, flash_mode);  
  6. /* 
  7.     if (flash_mode <= FLASH_MODE_BASE || FLASH_MODE_MAX <= flash_mode) { 
  8.         LOGE("ERR(%s):Invalid flash_mode (%d)", __func__, flash_mode); 
  9.         return -1; 
  10.     } 
  11.  
  12.     if (m_params->flash_mode != flash_mode) { 
  13.         m_params->flash_mode = flash_mode; 
  14.         if (m_flag_camera_start) { 
  15.             if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FLASH_MODE, flash_mode) < 0) { 
  16.                 LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FLASH_MODE", __func__); 
  17.                 return -1; 
  18.             } 
  19.         } 
  20.     } 
  21. */  
  22.     return 0;  
  23. }  


重新编译库和内核,下载,结果测试成功。

你可能感兴趣的:(S5PV210 ANDROID 为摄像头增加闪光灯)