高通QMI架构简介

 

 

什么是QMI?

Qualcom Message Interface  高通信息接口

 

背景:2005-2006年部署(原高通MSMTM接口),所有服务最初都是由DATA团队设计和维护的,功能是按照AT命令标准构建的,主要用于连接管理器类型应用程序,可通过USB连接(QMUX传输)连接到电脑。

2009年QMI取代RPC(Remote Procedure Call),QMI的范围开始扩大,无线电接口层(RILs)开始向QMI过渡,并定义了必要的支持;底层由更健壮的通信(IPC路由器传输)替代,通过共享内存方式(SMD)在片上SOC之间可用。

 

高通平台目前都是非对称多核心,最主要的是AP和Modem。两个处理器怎么进行通信呢,我们把AP和Modem当作两个主机,问题就变得了很简单,TCP/IP协议不是一种非常成功的进程间跨主机通信方式。高通没有采用这种方式,但是借鉴了TCP/IP的框架设计。它的框架是这样的,内核态:基于共享内存(SMD)实现链路层,扩展协议域;用户态,封装出类似于socket函数的接口,用于用户态使用。而我所描述的QMI就是用户态使用的API接口,这些接口非常类似于socket,只要有个socket编程的经验的是会容易理解的。

 

 

QMI提供什么?

支持同步和异步接口;

支持在在多个处理器之间进行通信;

具有良好的可扩展性;

支持多客户端并发运行;

支持多个服务端并发运行,且每个服务端还对应多个客户端;

每个服务端还支持版本信息;

QMI架构

 

Messages

Request message ——一条request消息由客户端发往服务端,并由服务端进行处理。

 

Reponse message——每一个request的消息都会有一个reponse消息与之对应,类似于一个函数的返回值。如果请求消息等效于调用函数,则响应消息等效于返回给调用方的结果。

 

Indiction message——这类消息是由服务端发给客户端的异步消息,在任何indication message发送之前,客户端首先需要通过request message与服务端建立连接,indication消息可以在任何时候发送。

消息的特点:

  1. 消息由Type-Length-Value(TLV)单元构成;
  2. 类型和长度是固定大小,而值是可变长度的;
  3. 每个消息中可以出现多个tlv值;
  4. 可以在该值中显示多个数据元素;
  5. 对于每个消息的TLV id都是唯一的;

消息的结构:

  1. 由传输头和服务级消息组成
  2. 每个传输的传输头都是唯一的

Service Message服务级负载对于所有传输都是通用的,幷包含以下元素

消息ID

消息长度

零或多个可变长度的tlv

Clients

  1. 任何想要使用QMI的内部或外部客户端应用程序

 

Services

  1. 任何想要使用QMI的内部应用服务程序

Common Libraries

  1. 为客户端(QCCI)和服务(QCSI)提供功能
  2. 通用API适用于所有平台/传输
  3. 封装传输和特定于平台的更改,以便共享客户机/服务代码
  4. 为每个服务消息提供编码/解码支持

 

Transports

QMUX

  1. 高通多路复用协议(QMUX);
  2. 原始传输通过一个有线USB以太网适配器;
  3. 支持MPSS处理器上的服务;
  4. 支持在应用程序(APPS)处理器或usb连接的主PC上的客户端;
  5. QMUX的客户端是用于特定于平台的,不同平台可能有差异;

 

IPC Router

  1. IPC路由器是一个面向消息(message-oriented)的路由器,用于支持Qualcomm QCCI QCSI;
  2. 增强了同一设备上处理器之间的传输;
  3. 通过SMD在路由节点之间传递QMI有效负载;
  4. 支持任何处理器上的客户端和服务;
  5. API对于所有平台都是通用的,即使实现不同;

 

QMI IDL

QMI接口是用接口定义语言(IDL)编写的,IDL编译器自动生成文件 .c和.h

 

编码/解码库

  1. 库是独立的,并且与自动生成的文件解耦
  2. 编码/解码消息的元信息将在.c作为Service_Object生成
  3. 在服务/客户机启动期间,元信息将注册到QCSI/QCCI进行消息编码/解码
  4. 客户端/服务可以使用QCCI/QCSI API发送/接收消息

QMI消息编码标准

1. 不使用浮点型数据,而是使用Q16类型的固定点数,即提供16位2位补码整数部分和16位小数部分的定点实现。

2. 命名约定

  1. 为了使所有消息实现保持一致,service端需要固定的独有的前缀
  2. 结构体以_type结尾
  3. 枚举以_enum结尾
  4. 请求消息以_req_msg结尾,类型以_REQ结尾
  5. 消息回应以_resp_msg结尾,类型以_RESP结尾
  6. 指示消息以_ind_msg结尾,类型以_IND结尾

 

 

QMI QCCI

QCCI是一套用于客户端从服务器接收信息或者发送消息到服务器的API集合。

 

以下步骤描述初始化客户机:

 

1. QMI客户机创建一个通知句柄来接收服务到达和退出事件通知。然后是客户端

用notifier句柄注册一个通知回调函数;

 

2. 当服务到达时,将设置信号,并调用通知回调函数来客户端关于服务到达的消息;

 

3.QMI客户机在收到服务到达通知后解析服务地址;

 

4. QMI客户机初始化服务的客户机句柄,该服务的地址在步骤3中解析。然后,这个客户端句柄用于与相关的QMI服务交换QMI消息;

 

5. 初始化客户端句柄时,将向客户端句柄注册一个错误回调函数。此错误回调用于接收关于服务重启或子系统重启的任何通知;

 

6. 此时,QMI客户机可以释放notifier句柄,以避免任何资源泄漏;

 

7. QMI客户机同步或异步发送请求消息,如上图所示;

 

8. 当所有相关的QMI消息通信完成时,QMI客户机释放客户机句柄。

 

QCCI APIs Callback function prototypes

  1. qmi_client_recv_raw_msg_async_cb
  2. qmi_client_recv_msg_async_cb
  3. qmi_client_ind_cb

Connection APIs

  1. qmi_client_notifier_init
  2. qmi_client_init
  3. qmi_client_get_service_list

Message sending APIs

  1. qmi_client_send_raw_msg_sync
  2. qmi_client_send_msg_sync
  3. qmi_client_delete_async_txn

Release connection APIs

  1. qmi_client_release

Encode and decode APIs

  1. qmi_client_message_encode
  2. qmi_client_message_decode

QMI QCSI

QCSI是用于接收客户端的请求及对其作出响应。另外,它也用来发送指示消息(indication message)以及对消息进行编解码(encode/decode),这个消息由server端主动发出。

消息的类型有如下三种:

Request message ——一条request消息由客户端发往服务端,并由服务端进行处理。

Reponse message——每一个request的消息都会有一个reponse消息与之对应,类似于一个函数的返回值。如果请求消息等效于调用函数,则响应消息等效于返回给调用方的结果。

Indiction message——这类消息是由服务端发给客户端的异步消息。在任何indication message发送之前,客户端首先需要通过request message与服务端建立连接。indication消息可以在任何时候发送。Callback function prototypes

  1. qmi_csi_connect
  2. qmi_csi_disconnect
  3. qmi_csi_process_req

Registration APIs

  1. qmi_csi_register
  2. qmi_csi_unregister

Message sending APIs

  1. qmi_csi_send_resp
  2. qmi_csi_send_ind
  3. qmi_csi_send_broadcast_ind

Event handling APIs

  1. qmi_csi_handle_event

QMI SERVER

这个api构建在QCSI框架之上

其主要目的是方便客户机以更少的工作量实现服务器

该框架允许用户编写基于对象的服务器,扩展核心服务器对象。核心服务器对象提供每个服务都需要的通用功能

 

Callback Function Prototypes

  1. qmi_csi_connect
  2. qmi_csi_disconnect
  3. qmi_csi_process_req

Constructor/Destructor APIs

  1. qmi_core_server_new
  2. qmi_core_server_delete

Registration APIs

  1. qmi_core_server_register
  2. qmi_core_server_unregister
  3. qmi_core_server_register_client
  4. qmi_core_server_unregister_client

Message Dispatch APIs

  1. qmi_core_server_dispatch_msg
  2. qmi_core_server_send_ind
  3. qmi_core_server_send_resp

QMUX

QMI Multiplexing Protocol(QMUX):QMI的复用协议

消息从控制点经过类似socket的线程传到QMI接口后,QMI负责对数据进行封装,加上QMUX消息的头,发送到QMUX层,

再通过QMUX层传到共享内存到BP侧。

QMUX消息的格式:

 

整个QMUX控制信道的结构如上图,

  1. I/FType:QMI将控制点数据封装后,发送到QMUX前,加的消息头,长度为一个byte,值通常为0x01,表示这个消息为QMUX消息,如果是其他值,则为其他消息。
  2. Length: QMUX消息的长度,不包括I/F Type。
  3. ControlFlags:控制位,表示消息传输的方向。长度为1个byte,只有第7个bit是标志位,其他位为0,bit7=1说明QMUX消息由服务端发送,bit7=0由控制点发送。
  4. Clien ID: 控制点的标识,在控制点和服务端都需要赋值,当在服务端发出的消息Client ID的值为0xFF,表示该消息为广播消息,由服务端主动发出,被所有控制点搜到。

QMUX SDU和TLV结构:

在整个控制信道的消息中,出去消息标识头I/F Type,和QMUX消息头,数据传输在QMUXSDU中完成,QMUX SDU里面的数据需要支持Type Length Value(TLV)的格式。

 

TLV格式的数据存放在QMI Service Message里面的Value中。

  1. Control Flags:表示消息是请求、响应还是指示。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章