camera daemon进程

一、守护进程启动包含的路径文件
1) 确定daemon进程编译路径
代码路径:vendor/qcom/proprietary/mm-camera/Android.mk
概述:确定生成mm-qcamera-daemon的路径
代码路径:vendor/qcom/proprietary/mm-camera/mm-camera2/server-imaging/Android.mk
概述:确定生成 mm-qcamera-daemon的包含的文件
1
LOCAL_MODULE:= mm-qcamera-daemon    LOCAL_MODULE模块必须定义,以表示Android.mk中的每一个模块。名字必须唯一且不包含空格。
2
LOCAL_SRC_FILES:= server.c  server_process.c
3
4
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/******可以知道守护进程处理的文件路径范围******/
5
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../includes/
6
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/bus/
7
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/controller/
8
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/object/
9
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/includes/
10
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/tools/
11
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/event/
12
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/pipeline/
13
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/stream/
14
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/module/
15
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/port/
16
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/debug/
17
18
19
LOCAL_SHARED_LIBRARIES:= libcutils libdl liboemcamera \   /***库文件路径:out\target\product\msm8909\system\vendor\lib\libmmcamera2_stats_modules.so
20
                                   libmmcamera2_stats_modules \
21
                                   libmmcamera2_iface_modules \
22
                                   libmmcamera2_isp_modules \
23
                                   libmmcamera2_sensor_modules \
24
                                   libmmcamera2_pproc_modules \
25
                                   libmmcamera2_imglib_modules
代码路径:device/qcom/msm8909/init.target.rc
概述:启动mm-qcamera-daemon服务
代码路径:device/qcom/common/rootdir/etc/init.qcom.rc
概述:为域套接字的通信创建文件
1
#Create folder for mm-qcamera-daemon
2
    mkdir /data/camera 0770 media camera
二、守护进程具体的内容
1) 初始化模块

函数分析:
1) 代码路径:vendor/qcom/proprietary/mm-camera/mm-camera2/server-imaging/server_process.c
函数:server_process_module_init();
概述:对modules_list数组中的模块进行初始化
1
static mct_module_init_name_t modules_list[] = {
2
  {"sensor", module_sensor_init,   module_sensor_deinit, NULL},
3
  {"iface",  module_iface_init,   module_iface_deinit, NULL},
4
  {"isp",    module_isp_init,      module_isp_deinit, NULL},
5
  {"stats",  stats_module_init,    stats_module_deinit, NULL},
6
  {"pproc",  pproc_module_init,    pproc_module_deinit, NULL},
7
  {"imglib", module_imglib_init, module_imglib_deinit, NULL},
8
};
2) 代码路径:kernel/drivers/media/platform/msm/camera_v2/camera/camera.c
函数:int camera_init_v4l2(struct device *dev, unsigned int *session);
函数ioctl(hal_fd->fd[0], VIDIOC_SUBSCRIBE_EVENT, &subscribe);打开的文件是dev/video0,所以ioctl调用是这video_register_device注册的ioctl_ops。
这里主要关注的两个函是
函数:static unsigned int  camera_v4l2_poll(struct file *filep,   struct poll_table_struct *wait)
作用:select函数通过设备文件的poll函数来检查是否可读、可写。(用户空间的select系统调用对应内核中的poll函数)
参考文章: http://blog.csdn.net/waldmer/article/details/18735517  关于select的调用方法
                   http://blog.csdn.net/gtkknd/article/details/7229576   关于返回值的解析
1
static unsigned int camera_v4l2_poll(struct file *filep,   struct poll_table_struct *wait)
2
{
3
    int rc = 0;
4
    struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
5
    if (sp->is_vb2_valid == 1)
6
        rc = vb2_poll(&sp->vb2_q, filep, wait);
7
8
    poll_wait(filep, &sp->fh.wait, wait);
9
    if (v4l2_event_pending(&sp->fh))
10
        rc |= POLLPRI;
11
    return rc;
12
}
13
在函数camera_v4l2_poll()中的v4l2_event_pending()函数返回的是fh->navailable;
函数:static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev,  const struct timespec *ts)
作用: fh->sequence++;
函数:static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
作用: fh->sequence--;
例如MSM_CAMERA_NEW_SESSION的过程
HAL层:调用int32_t mm_camera_open(mm_camera_obj_t *my_obj)打开camera
kernel层:static int camera_v4l2_open(struct file *filep)  ---->  camera_pack_event(filep, MSM_CAMERA_NEW_SESSION, 0, -1, &event);---->  
                  rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);---->  v4l2_event_queue(vdev, event);----> __v4l2_event_queue_fh(fh, ev, &timestamp);
                  ----> fh->sequence++; ---> static unsigned int camera_v4l2_poll(struct file *filep,  struct poll_table_struct *wait) ---> rc |= POLLPRI; POLLPRI表示 可读
vendor层:ret = select(select_fds.select_fd + 1, &(select_fds.fds), NULL, NULL, NULL)---> ioctl(fd_info->fd[0], VIDIOC_DQEVENT, &event)---> fh->sequence--;
                   通过select系统调用获得kernel的fd的状态改变,从而进行事件的处理,同时调用 VIDIOC_DQEVENT使得fh->sequence--

3)代码路径:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct/tools/mct_list.c
函数:boolean mct_list_traverse(mct_list_t *mct_list, mct_list_traverse_func traverse,  void *user_data);
函数:mct_list_traverse(listen_fd_list, server_reset_select_fd, &select_fds);
作用:Traverse whole list
1
boolean mct_list_traverse(mct_list_t *mct_list, mct_list_traverse_func traverse, void *user_data)
2
{
3
  mct_list_t *temp_list;
4
  uint32_t num;
5
6
  if (mct_list && traverse) {
7
    if (traverse(mct_list->data, user_data) == FALSE)
8
      return FALSE;
9
10
    num = mct_list->next_num;
11
    if (num > 0 && mct_list->next) {
12
      temp_list = mct_list->next[0];
13
      while (num--) {
14
        mct_list_traverse(temp_list, traverse, user_data);/***递归地遍历执行traverse(mct_list->data, user_data)函数***/
15
        temp_list++;
16
      }
17
    }
18
  }
19
20
  return TRUE;
21
}
函数:static boolean server_reset_select_fd(void *data, void *user_data)
作用:
1
static boolean server_reset_select_fd(void *data, void *user_data)
2
{
3
  read_fd_info_t      *fd_info  = (read_fd_info_t *)data;
4
  server_select_fds_t *selected = (server_select_fds_t *)user_data;
5
  FD_SET(fd_info->fd[0], &(selected->fds)); /***FD_SET(int fd, fd_set *fdset);  将fd加入set集合***/
6
  selected->select_fd = MTYPE_MAX(selected->select_fd, fd_info->fd[0]);/***FD_SET(int fd, fd_set *fdset);  将fd加入set集合***/
7
8
  return TRUE;
9
}
10
Camera daemon handles the following types of domain socket messages:
    域套接字
  消息类型:
   Buffer mapping –Handled via type RD_DS_FD_HAL 对应于  hal_ds_fd->fd[0]
   消息来源:     
      hal_ds_fd->session = proc_ret.new_session_info.session_idx;
      hal_ds_fd->fd[0] = proc_ret.new_session_info.hal_ds_fd;/***域套接字***/
      hal_ds_fd->type = RD_DS_FD_HAL;
   VIDIOC_SUBSCRIBE_EVENT
   消息类型:
       Video node updates from kernel –Handled via type RD_FD_HAL 对应于 hal_fd->fd[0]
   消息来源:
        hal_fd->fd[0] = open(dev_name, O_RDWR | O_NONBLOCK); /****dev_name = dev/video0***/
        hal_fd->type = RD_FD_HAL;
       ioctl(hal_fd->fd[0], VIDIOC_SUBSCRIBE_EVENT, &subscribe)
   管道
   消息类型:
      Updates from MCT (over Unix pipe) –Handled via type RD_PIPE_FD_MCT  对应于 mct_fds->fd[0]
   消息来源:
      mct_fds->session = proc_ret.new_session_info.session_idx;
      mct_fds->fd[0] = proc_ret.new_session_info.mct_msg_rd_fd;/***管道***/
      mct_fds->fd[1] = proc_ret.new_session_info.mct_msg_wt_fd;/***管道***/
      mct_fds->type = RD_PIPE_FD_MCT;
通过下面三个函数将三个不同类型的fd全部添加到 listen_fd_list这个链表中,最后通过mct_list_traverse(listen_fd_list, server_reset_select_fd, &select_fds);获取最大的 fd作为select函数的第一个参数。
listen_fd_list = mct_list_append(listen_fd_list,hal_ds_fd, NULL, NULL)
|---> mct_list_t* mct_list_append(mct_list_t *mct_list, void *data, void *appendto, mct_list_find_func list_find)
      |---> new_list = mct_list_new(data);

listen_fd_list = mct_list_append(listen_fd_list, mct_fds, NULL, NULL)
|---> mct_list_t* mct_list_append(mct_list_t *mct_list, void *data, void *appendto, mct_list_find_func list_find)
      |---> new_list = mct_list_new(data);

listen_fd_list = mct_list_append(listen_fd_list, hal_fd, NULL, NULL)
|---> mct_list_t* mct_list_append(mct_list_t *mct_list, void *data, void *appendto, mct_list_find_func list_find)
      |---> new_list = mct_list_new(data);
阅读更多

猜你喜欢

转载自blog.csdn.net/huifeidedabian/article/details/77949419
今日推荐