QualComm Android5.1 Camera浅谈-daemon进程

来源:互联网 发布:matlab编程题目 编辑:程序博客网 时间:2024/05/20 01:35

转载来自:http://blog.csdn.net/a04081122/article/details/52981001

vendor\qcom\proprietary\mm-camera\mm-camera2\server-imaging\server.c //daemon进程开始

int main(int argc, char *argv[])
{

1. serv_hal_node_name = malloc((size_t)MAX_DEV_NAME_SIZE);  为节点分配内存

  if (get_server_node_name(serv_hal_node_name) == FALSE)//找到/dev/video0节点

  hal_fd = malloc(sizeof(read_fd_info_t));

  snprintf(dev_name, sizeof(dev_name), "/dev/%s", serv_hal_node_name);
  hal_fd->fd[0] = open(dev_name, O_RDWR | O_NONBLOCK);//打开/dev/video0节点,并设置type为RD_FD_HAL
  hal_fd->type = RD_FD_HAL;
  if (!(listen_fd_list = mct_list_append(listen_fd_list, hal_fd, NULL, NULL))) //将hal_fd加入到监听链表listen_fd_list中
 

 2.  if(server_process_module_sensor_init() == FALSE)

  if (server_process_module_init() == FALSE)

//调用server_process.c中的各个module的init函数,并通过mct_list_append()函数,将每个模块的init函数生成的mct_module_t加入到static mct_list_t *modules = NULL链表中。

static mct_module_init_name_t modules_list[] = {
  {"sensor", module_sensor_init,   module_sensor_deinit, NULL},
  {"iface",  module_iface_init,   module_iface_deinit, NULL},
  {"isp",    module_isp_init,      module_isp_deinit, NULL},
  {"stats",  stats_module_init,    stats_module_deinit, NULL},
  {"pproc",  pproc_module_init,    pproc_module_deinit, NULL},
  {"imglib", module_imglib_init, module_imglib_deinit, NULL},
};

其中,module_sensor_init()函数中,通过判断entity.type == MEDIA_ENT_T_V4L2_SUBDEV &&entity.group_id == MSM_CAMERA_SUBDEV_SENSOR_INIT,找到相应的

/dev/v4l-subdevX节点并打开,并通过LOG_IOCTL(fd, VIDIOC_MSM_SENSOR_INIT_CFG, &cfg),将sensor IC的有关信息拷贝到内核空间,调用msm_sensor_driver_probe()函数,
/* Power up and probe sensor */
rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);

rc为0,表明sensro I2C通信正常,接着通过

msm_sensor_driver_create_i2c_v4l_subdev(),生成了/dev/media1&/dev/video1(后)和/dev/media2&/dev/video2(前)节点,并通过msm_sd_register(&s_ctrl->msm_sd)注册前后摄像头的sensor。

 用户空间的module_sensor_find_sensor_subdev(module_ctrl)和module_sensor_find_other_subdev(module_ctrl)函数,把前后sensor,actuator,csi,isp等从设备的文件节点一一确定好,并加入到module_ctrl->sensor_bundle链表中。

 /* Subcribe V4L2 event */
  memset(&subscribe, 0, sizeof(struct v4l2_event_subscription));
  subscribe.type = MSM_CAMERA_V4L2_EVENT_TYPE;
  for (i = MSM_CAMERA_EVENT_MIN + 1; i < MSM_CAMERA_EVENT_MAX; i++) {
    subscribe.id = i;
    if (ioctl(hal_fd->fd[0], VIDIOC_SUBSCRIBE_EVENT, &subscribe) < 0)  //通过服务设备文件的ioctl接口,订阅所有的事件(enent id)
      goto subscribe_failed;
  }


  select_fds.select_fd = hal_fd->fd[0];

3. do {


    FD_ZERO(&(select_fds.fds));
    mct_list_traverse(listen_fd_list, server_reset_select_fd, &select_fds);


    /* no timeout */
    ret = select(select_fds.select_fd + 1, &(select_fds.fds), NULL, NULL, NULL);


    if (ret > 0) {


      mct_list_t     *find_list;
      read_fd_info_t *fd_info;


      find_list = mct_list_find_custom(listen_fd_list, &(select_fds.fds),
        server_check_listen_fd);
      if (!find_list)
        continue;


      fd_info = (read_fd_info_t *)find_list->data;
      CDBG("CAMERA_DAEMON:fd_info->fd[0]\n",fd_info->fd[0]);
      switch (fd_info->type) {
      case RD_FD_HAL: {


        if (ioctl(fd_info->fd[0], VIDIOC_DQEVENT, &event) < 0)//下命令让服务模块的事件出队列进行处理
          continue;


        /* server process HAL event:
         *
         *   1. if it returns success, it means the event message has been
         *      posted to MCT, don't need to send CMD ACK back to kernel
         *      immediately, because MCT will notify us after process;
         *
         *   2. if it returns failure, it means the event message was not
         *      posted to MCT successfully, hence we need to send CMD ACK back
         *      to kernel immediately so that HAL thread which sends this
         *      event can be blocked.
         */
        if (event.id == MSM_CAMERA_NEW_SESSION) {
          serv_in.it_value.tv_sec = 5;
          serv_in.it_value.tv_nsec = 0;
          serv_in.it_interval.tv_sec = serv_in.it_value.tv_sec;
          serv_in.it_interval.tv_nsec = serv_in.it_value.tv_nsec;
          timer_settime(serv_timerid, 0, &serv_in, &serv_out);
        } else if (event.id == MSM_CAMERA_DEL_SESSION) {
          serv_in.it_value.tv_sec = 5;
          serv_in.it_value.tv_nsec = 0;
          serv_in.it_interval.tv_sec = serv_in.it_value.tv_sec;
          serv_in.it_interval.tv_nsec = serv_in.it_value.tv_nsec;
          timer_settime(serv_timerid, 0, &serv_in, &serv_out);
}
        proc_ret = server_process_hal_event(&event);
        serv_in.it_value.tv_sec = 0;
        serv_in.it_value.tv_nsec = 0;
        serv_in.it_interval.tv_sec = serv_in.it_value.tv_sec;
        serv_in.it_interval.tv_nsec = serv_in.it_value.tv_nsec;
        timer_settime(serv_timerid, 0, &serv_in, &serv_out);
      }
        break;


      case RD_DS_FD_HAL:
        /* server process message sent by HAL through Domain Socket */
        proc_ret = server_process_hal_ds_packet(fd_info->fd[0],
          fd_info->session);
        break;


      case RD_PIPE_FD_MCT:
        /* server process message sent by media controller
         * through pipe: */
        proc_ret = server_process_mct_msg(fd_info->fd[0],
          fd_info->session);
        break;


      default:
        continue;
      } /* switch (fd_info->type) */


      switch (proc_ret.result) {
      case RESULT_NEW_SESSION: {
       struct msm_v4l2_event_data *ret_data =
        (struct msm_v4l2_event_data *)proc_ret.ret_to_hal.ret_event.u.data;
       if( ret_data->status == MSM_CAMERA_CMD_SUCESS) {
        hal_ds_fd = malloc(sizeof(read_fd_info_t));
        if (!hal_ds_fd) {
          /* Shouldn't end directly, need to shutdown MCT thread */
          goto server_proc_new_session_error;
        } else {
          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;
        }


        mct_fds = malloc(sizeof(read_fd_info_t));
        if (!mct_fds) {
          free(hal_ds_fd);
          goto server_proc_new_session_error;
        } else {
          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;
        }


        if (!(listen_fd_list = mct_list_append(listen_fd_list,
            hal_ds_fd, NULL, NULL))) {
          free(hal_ds_fd);
          free(mct_fds);
          goto server_proc_new_session_error;
        }


        if (!(listen_fd_list = mct_list_append
             (listen_fd_list, mct_fds, NULL, NULL))) {
          free(hal_ds_fd);
          free(mct_fds);
          goto server_proc_new_session_error;
        }
        } else {
          CDBG_ERROR("%s: New session [%d] creation failed with error",
            __func__, ret_data->session_id);
        }
        goto check_proc_ret;
      } /* RESULT_NEW_SESSION */
        break;


      case RESULT_DEL_SESSION: {
        mct_list_t     *find_list;
        read_fd_info_t fd_info_match;
        read_fd_info_t *ds_fd_info = NULL, *mct_fd_info = NULL;
        struct msm_v4l2_event_data *event_data = (struct msm_v4l2_event_data *)
          &proc_ret.ret_to_hal.ret_event.u.data[0];


        /* this is for Domain Socket FD */
        fd_info_match.type    = RD_DS_FD_HAL;
        fd_info_match.session = event_data->session_id;


        find_list = mct_list_find_custom(listen_fd_list, &fd_info_match,
          server_find_listen_fd);
        if (find_list) {
          ds_fd_info = (read_fd_info_t *)find_list->data;
          listen_fd_list = mct_list_remove(listen_fd_list, ds_fd_info);
          FD_CLR(ds_fd_info->fd[0], &select_fds.fds);
          close(ds_fd_info->fd[0]);
          free(ds_fd_info);
        }


        /* this is for MCT FD */
        fd_info_match.type    = RD_PIPE_FD_MCT;


        find_list = mct_list_find_custom(listen_fd_list, &fd_info_match,
          server_find_listen_fd);
        if (find_list) {
          mct_fd_info = (read_fd_info_t *)find_list->data;
          listen_fd_list = mct_list_remove(listen_fd_list, mct_fd_info);
          FD_CLR(mct_fd_info->fd[0], &select_fds.fds);
          close(mct_fd_info->fd[0]);
          close(mct_fd_info->fd[1]);
          free(mct_fd_info);
        }
      } /* case RESULT_DEL_SESSION */
         goto check_proc_ret;
        break;


      case RESULT_FAILURE:
        goto server_proc_error;
        break;


      case RESULT_SUCCESS:
        goto check_proc_ret;
        break;


      default:
        break;
      } /* switch (proc_ret.result) */


server_proc_new_session_error:
      event.id = MSM_CAMERA_DEL_SESSION;
      server_process_hal_event(&event);


server_proc_error:
      proc_ret.ret_to_hal.ret = TRUE;


check_proc_ret:
      if (proc_ret.ret_to_hal.ret == TRUE) {
        switch (proc_ret.ret_to_hal.ret_type) {
        /* @MSM_CAM_V4L2_IOCTL_CMD_ACK is Ack-knowledge to HAL's
         *   control command, which has command processing status.
         */
        case SERV_RET_TO_HAL_CMDACK:
          ioctl(hal_fd->fd[0], MSM_CAM_V4L2_IOCTL_CMD_ACK,
            (struct msm_v4l2_event_data *)&(proc_ret.ret_to_hal.ret_event.u.data));
          break;


        /* @MSM_CAM_V4L2_IOCTL_NOTIFY is MCT originated event such
         *   as meta data, SOF etc. Normally it comes
         *  1. domain socket buffer mapping process;
         *  2. from MCT.
         */
        case SERV_RET_TO_HAL_NOTIFY:
          ioctl(hal_fd->fd[0], MSM_CAM_V4L2_IOCTL_NOTIFY,
            &(proc_ret.ret_to_hal.ret_event.u.data));
          break;


        /* @MMSM_CAM_V4L2_IOCTL_NOTIFY_META is Meta data notification
         *   sent back to HAL during streaming. It is generated by
         *   BUS message.
         */
        case SERV_RET_TO_KERNEL_NOTIFY_POSSIBLE_FREEZE:
          ioctl(hal_fd->fd[0], MSM_CAM_V4L2_IOCTL_NOTIFY_FREEZE,
            &(proc_ret.ret_to_hal.ret_event.u.data));
          break;
        case SERV_RET_TO_HAL_NOTIFY_ERROR:
          ioctl(hal_fd->fd[0], MSM_CAM_V4L2_IOCTL_NOTIFY_ERROR,
            &(proc_ret.ret_to_hal.ret_event.u.data));
          break;


        default:
          break;
        }
      }
    } else {
      /* select failed. it cannot time out.*/
      /* TO DO: HANDLE ERROR */
    }
  } while (1);

0 0
原创粉丝点击