6 android QMI机制---Modem消息接收

原文:https://blog.csdn.net/u012439416/article/details/74277494 

6 Modem消息接收

3.1 消息初始化

初始化:qmi_modem_taskàqmii_init()àqmux_init()。qmux_init方法完成对控制通道的初始化后,

通过函数qmuxi_process_rx_sig方法开始从共享内存接收数据。调用流程如如下,

(void)qmi_set_sig_handler(QMI_QMUX_RX_SIGNAL, qmuxi_process_rx_sig, NULL);

在qmuxi_process_rx_sig方法中,首先通过dsm_dequeue()读取在队列中等待的QMUX消息,

赋值给指针qmux_pdu表示QMUX消息的首地址。

mux_pdu = dsm_dequeue( &qmux_s->io.rx_wm );

然后调用qmuxi_process_msg方法开始对AP侧发过来的QMUX消息解包。

qmuxi_process_msg( qmux_s, qmux_pdu );

qmuxi_process_msg方法首先拆分IF Type,通过函数dsm_pull8()进行解包。然后判断IF Type类型,

然后把QMUX Message通过qmuxi_input()继续处理。

在qmuxi_input()中,会拆分QMUX的消息头,将消息头大卸八块,包括length,control_flags,client_id,service_id,

然后调用qmi_framework_svc_recv方法将剩下的QMUX SDU从拆分出来的QMUX消息头中,

找到BP侧相对应的service处理。

if((svci == NULL) || (!(svci->registered)))
  {
    status =  qmi_framework_svc_recv( qmi_instance_by_qmux_state(qmux_s),
        (qmux_service_e_type) qmux_hdr.svc_type, qmux_hdr.clid, *qmux_pdu );
    *qmux_pdu = NULL;
    return status;
  }

在qmi_framework_svc_recv方法中,并不会马上根据service_id等对QMUX消息进行处理,这里也是一个接口,

将消息打包成BP侧的QMI_framework的一个command,发送出去。

qmi_framework_msg_hdr_type msg_hdr;

qmi_framework_svc_info_type * svc_info;

•••

svc_info = qmi_framework_svc_state[service];

定义一个qmi_framework_svc_info_type的指针变量,对svc_info的操作就等于对qmi_framework_svc_state的操作。

打包到msg_hdr

 msg_hdr.common_hdr.service = service;
  msg_hdr.common_hdr.client_id = client_id;
  msg_hdr.common_hdr.qmi_instance = (int32)qmi_instance;
  msg_hdr.common_hdr.transaction_id = msg_x_id;
  msg_hdr.msg_ctl_flag =  msg_ctl;
  msg_hdr.msg_len = remaining_bytes;

最后

svc_info->cfg.cbs.cmd_hdlr(&msg_hdr,&sdu_in);

这个机制是怎么样呢?以phone相关的qmi_voice.c为例。

3.2 消息分类处理

qmi_voice.c在qmi_voice_init方法进行初始化时,

mi_mmode_set_cmd_handler(QMI_MMODE_CMD_VOICE_FW_CB, qmi_voice_handle_fw_cmd);
•••
qmi_voicei_cfg.cmn_svc_cfg.fw_cfg.cbs.alloc_clid  = qmi_voice_fw_alloc_clid_cback;
qmi_voicei_cfg.cmn_svc_cfg.fw_cfg.cbs.dealloc_clid = qmi_voice_fw_dealloc_clid_cback;
qmi_voicei_cfg.cmn_svc_cfg.fw_cfg.cbs.init_cback  = qmi_voice_fw_init_cback;
qmi_voicei_cfg.cmn_svc_cfg.fw_cfg.cbs.cmd_hdlr  = qmi_voice_fw_req_cback;
  
qmi_voicei_cfg.cmn_svc_cfg.cmd_hdlr_array    = qmi_voicei_cmd_callbacks;
qmi_voicei_cfg.cmn_svc_cfg.cmd_num_entries   = VOICEI_CMD_MAX;
qmi_voicei_cfg.cmn_svc_cfg.service_id = QMUX_SERVICE_VOICE;
  
  /*-----------------------------------------------------------------------
  step 2:  calling QMI Framework API to register the service.
  ----------------------------------------------------------------------*/
  errval= qmi_framework_reg_service(QMUX_SERVICE_VOICE, 
&qmi_voicei_cfg.cmn_svc_cfg.fw_cfg);

初始化的时候,用结构体指针&qmi_voicei _cfg,到qmi_framework里面注册服务,获取AP测发送过来的qmux,

可以关注给cmd_hdlr赋值的函数qmi_voice_fw_req_cback,这是从qmi_framework返回的回调函数。

因此,对于phone消息, qmi_framework_svc_recv都是回调qmi_voice_fw_req_cback进行处理,

qmi_voice_fw_req_cback方法读取QMUX消息的头指针,和QMUX SDU的首地址。发送到voice服务里面专门

的command_handle。
qmi_mmode_send_cmd(QMI_MMODE_CMD_VOICE_FW_CB, cmd_ptr);

在voice初始化可找到QMI_MMODE_CMD_VOICE_FW_CB对应的方法为qmi_voice_handle_fw_cmd。

qmi_mmode_send_cmd方法会调用qmi_voice_handle_fw_cmd方法,该方法根据不同的消息类型调用不同的

方法进行处理,
switch(qmi_info->id)
  {
    case QMI_MMODE_FW_INIT_CB:
      qmi_voicei_fw_init_cback_hdlr(qmi_info->data.qmi_fw_info.init_cb.num_instances);
      break;
    case QMI_MMODE_FW_ALLOC_CLID_CB:
      qmi_voicei_fw_alloc_clid_hdlr(&qmi_info->data.qmi_fw_info.alloc_clid.msg_hdr);
      break;
    case QMI_MMODE_FW_DEALLOC_CLID_CB:
      qmi_voicei_fw_dealloc_clid_hdlr(&qmi_info->data.qmi_fw_info.dealloc_clid.msg_hdr);
      break;
    case QMI_MMODE_FW_REQ_CB:
      qmi_voicei_fw_req_hdlr(&qmi_info->data.qmi_fw_info.req_cb.msg_hdr,
                               qmi_info->data.qmi_fw_info.req_cb.sdu_in);
      break;
    default:
      QM_MSG_ERROR("Unsupported qmi-voice fw cmd");
      break;
  }

qmi_voicei_fw_req_hdlr并不会马上对获取的消息进行处理,而是判断头消息中的client_id是否符合,

符合则通过函数qmi_mmode_svc_req_hdlr发送到request_handler中,

if( msg_hdr->common_hdr.client_id > 0 )
  {
    cl_sp = (qmi_voicei_client_state_type *) 
               qmi_voice_state.client[msg_hdr->common_hdr.client_id - 1];
    ASSERT(cl_sp);
   /*-------------------------------------------------------------------------
     Invoke the common svc request handler
    -------------------------------------------------------------------------*/
   qmi_mmode_svc_req_hdlr(&qmi_voicei_cfg.cmn_svc_cfg, msg_hdr, &cl_sp->common, 

到此,几乎所有的消息类型最后都会调用qmi_mmode_svc_req_hdlr方法发送到request_handler中。

3.3 消息分发

在qmi_mmode_svc_req_hdlr函数中,真正对QMUX消息进行处理。首先拆分头消息中的service_id,control_flag等。

svc_id = svc_cfg->service_id;

然后通过一个while循环开始对QMUX SDU进行解包。

while (sdu_in)
  {
    /*-----------------------------------------------------------------------
      Extract service message header
    -----------------------------------------------------------------------*/
    temp = dsm_pull16( &sdu_in );

解包函数dsm_pull16()作用,按照一定的大小,从&sdu_in这个地址中获取数据。获取完后,跳出while循环,

调用qmi_mmode_svci_dispatch_transaction方法进行处理。

qmi_mmode_svci_dispatch_transaction(&msg_hdr->common_hdr,svc_cfg,x_p);

其中参数x_p是解包后的qmux_sdu存放的buffer。

qmi_mmode_svci_input方法会通过request_handler对消息进行处理分发。

response_ptr = cmd_hdlr->request_hdlr( svc_cfg->svc_sp, cmd_buf_p, cl_sp, sdu_in );

request_hdlr方法是被封装了的,没法继续跟进,BP侧的接收处理到此结束。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值