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发送的流程相似,不详细介绍。
- android QMI机制---modem消息发送
- android QMI机制---Modem消息接收
- android QMI机制---QCRIL消息发送
- android QMI机制---底层消息发送
- android QMI机制---概论
- android QMI机制---QMUX
- android QMI机制---Qcril初始化流程
- 高通Modem qmi log
- qualcomm qmi(modem-linux通信)
- android应用程序消息处理机制之消息发送
- 流程发送消息机制
- jms消息发送机制
- Handle发送消息机制
- OC-消息发送机制
- 消息发送机制
- MFC 消息发送机制
- iOS_Runtime1_消息发送机制
- 消息发送机制
- C/C++面试题(一)
- 数据结构 C语言 队列 迷宫问题
- 文件I/O(不带缓存)++标准I/O(带缓存)
- java线程池 -- 大话笔记
- 从Adobe调查问卷看原型设计工具大战
- android QMI机制---modem消息发送
- ZOJ3876 May Day Holiday【日期计算】
- win10 物联网编程资料
- unity3D学习笔记之七 RectTransform与屏幕适配
- 剑指offer | 训练题49:数组中重复的数字
- 数学建模--整数规划
- Linux系统编程——进程间通信:消息队列
- POJ 2718 Smallest Difference(双重DFS)
- SIGCHI Latex Format display subfigures