android QMI机制---modem消息发送

来源:互联网 发布:循序渐进学java 编辑:程序博客网 时间:2024/06/07 02:03

7 modem消息发送

一般BP侧处理完请求后,都会回应一个响应给AP,一般是用宏QMI_SVC_PKT_PUSH将要作为响应

的消息发送出去。qmi_svc_utils.h中QMI_SVC_PKT_PUSH定义如下,

#define QMI_SVC_PKT_PUSH(pkt,val,len)  ( len == dsm_pushdown_packed(pkt,\      val,\ len,\ DSM_DS_SMALL_ITEM_POOL ) )

将val里面的数据,传len个长度到pkt的buffer里面,然后发送出去。Val和len是我们要作为响应的数据

和数据包大小。QMI_SVC_PKT_PUSH()只能传单一的参数,根据上文说明的QMUX消息中TLV格式

的原理,可以用多个QMI_SVC_PKT_PUSH连着用,这样可以将多个数据或参数打包到同一条消息中发送。

例如,在voice服务中,用多个QMI_SVC_PKT_PUSH回传消息。

QMI_SVC_PKT_PUSH(&response, (void*)&info->call_id, sizeof(info->call_id))) )•••QMI_SVC_PKT_PUSH(&response, (void *)&tag, VOICEI_TLV_TAG_SIZE)•••

最后还要记得写上TLV的总长度,和标志位。标志位必须和AP侧发出的请求相对应,如AP侧发出请求为0x21,

返回的标志位rec_tag也必须为0x21,方便返回AP后查表处理。将TLV消息放入response这个buffer后,

会继续打包QMUX的消息头,然后通过函数qmi_mmode_svc_send_response()发送出去。调用流程图如下,


/* Send the response */  status = qmi_mmode_svc_send_response( &common_hdr,cmd_buf_p, msg_ptr);

回传的消息也是需要严格按照QMUX消息的格式的, qmi_mmode_svc_send_response方法中按照格式对

QMUX消息进行重组,

msg_hdr.common_hdr.client_id      = common_hdr->client_id; msg_hdr.common_hdr.qmi_instance   = common_hdr->qmi_instance;  msg_hdr.common_hdr.service        = common_hdr->service;  msg_hdr.common_hdr.transaction_id = x_p->x_id;msg_hdr.msg_ctl_flag = QMI_FLAG_MSGTYPE_RESP;if( x_p->n_cmds > 1 ){  msg_hdr.msg_ctl_flag |= QMI_FLAG_MASK_COMPOUND;}msg_hdr.msg_len  = (uint16) dsm_length_packet(msg_ptr);qmi_framework_svc_send_response( &msg_hdr, msg_ptr );

指针msg_ptr,读取x_p->resp_list[]中的响应消息,msg_hdr为qmux消息的头。通过函数

qmi_framework_svc_send_respnse()发到qmi_framework,这只是qmi_framework的一个接口,

会调用qmi_frameworki_svc_send方法,直接调用qmi_frameworki_svc_send方法,

status = qmi_frameworki_svc_send( msg_hdr,                                QMI_CMD_FRAMEWORK_SEND_RESPONSE,                               msg_ptr );

qmi_frameworki_svc_send方法首先对接收到QMUX消息进行处理,将消息头和内容放到结构体

qmi_framework_msg_buf的成员变量中,

memscpy( &qmi_framework_msg_buf->msg_hdr, sizeof (*msg_hdr), msg_hdr,           sizeof (*msg_hdr) );qmi_framework_msg_buf->dsm_item = msg_ptr;

然后调用qmi_framework_process_svc_send方法,

return qmi_framework_process_svc_send((void *)qmi_framework_msg_buf, qmi_cmd );

qmi_framework_process_svc_send方法首先校验QMI服务给qmi_framework发出的command,

判断这次从BP侧发出的消息是一个响应AP侧请求的response还是主动发给AP的一个indicated。

if((qmi_cmd_id_e_type)qmi_cmd == QMI_CMD_FRAMEWORK_SEND_RESPONSE )  {    msg_type = QMI_FLAG_MSGTYPE_RESP;  }  else if((qmi_cmd_id_e_type)qmi_cmd == QMI_CMD_FRAMEWORK_SEND_IND)  {    msg_type = QMI_FLAG_MSGTYPE_IND;

然后判断消息头的有效性,最后通过函数qmi_frameworki_qmux_send()发送到BP侧QMI的接口,

if (FALSE == qmi_frameworki_validate_msg_hdr(msg_hdr, msg_type )){  LOG_MSG_ERROR_1 ("Msg header validation failed - unable to send Response for cmd %d",                   msg_hdr->msg_ctl_flag);    goto func_end;  }  return qmi_frameworki_qmux_send(msg_buf, msg_type, ind_cmd_id, msg_ptr);

qmi_frameworki_qmux_send方法首先会对QMUX消息进行一个过滤,如果消息异常,则丢弃。

if ( qmi_svc_filter_message( (qmi_instance_e_type) msg_buf->msg_hdr.common_hdr.qmi_instance, msg_buf->msg_hdr.common_hdr.service,            msg_type, int_cmd_id) ){•••

然后调用QMUX层的接口qmux_sio_send方法进行处理,

qmux_sio_send ( (qmi_instance_e_type)msg_buf->msg_hdr.common_hdr.qmi_instance,   msg_buf->msg_hdr.common_hdr.service, msg_buf->msg_hdr.common_hdr.client_id, msg_ptr);

qmux_sio_send方法首先调用dsm_length_packet方法对消息进行组装,

if( dsm_length_packet(qmux_sdu) == 0)

然后组合上IF Type完成整个消息重组,

iftype = (byte)qmux_state[ qmi_instance ].io.port_info.frame_mode;

最后通过IO口的传输函数发送到AP侧,

if( QMUX_DEVSTREAM_CONTROL != qmux_state[qmi_instance].io.port_info.qmi_stream )  {    sio_transmit( qmux_state[qmi_instance].io.sio_handle, qmux_sdu );  }  else  {    sio_control_transmit( qmux_state[qmi_instance].io.sio_handle, qmux_sdu );  }

这样,消息就从modem侧发出来了。

8 QCRLC消息接收

在qmi_qmux.c的qmi_qmux_pwr_up_init方法中,

QMI_QMUX_IO_PLATFORM_PWR_UP_INIT(qmi_qmux_rx_msg,qmi_qmux_event_cb);

qmi_qmux_rx_msg会接收处理BP侧回发的消息, 主要是对从BP侧接收到的消息进行解包,

判断BP侧的消息类型是响应还是指示,转发给上层client端处理。根据QMUX消息结构的长度,

选择是用1个字节的方式读取还是2个字节的方式读取,

/* Read the I/F byte, make sure it is a 1 */READ_8_BIT_VAL(msg_ptr,i_f_byte);if (i_f_byte != 1){    QMI_ERR_MSG_1 ("qmi_qmux: Received invalid I/F byte = %d\n",i_f_byte);     return;}/* Read the message length */READ_16_BIT_VAL(msg_ptr, length);

判断消息类型是BP侧群发的广播,还是专门针对某个client端的响应。

if (client_id == QMI_QMUX_INVALID_QMI_CLIENT_ID){      qmi_qmux_rx_client_broadcast (conn_id, service_id, client_id, control_flags,                   msg_ptr, msg_len);}else{   qmi_qmux_rx_client_msg (conn_id, service_id, client_id, control_flags,                     msg_ptr, msg_len);    }

接下去的流程,和之前AP发送的流程相似,不详细介绍。