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);
閱讀更多 登錄後自動展開
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章