> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# QMI 客户端 API

> 创建 QMI 客户端、连接到服务、编码请求以及处理响应和指示。

QMI 客户端拥有一个句柄，将该句柄连接到某个服务实例，在需要时注册指示处理，并向服务发送请求。

## 客户端生命周期

客户端会经历以下阶段：

1. **创建句柄** —— 创建一个 QMI 句柄，并提供一个回调，用于接收服务和传输事件的通知。
2. **连接到服务** —— 通过指定服务 ID 和实例 ID 将句柄连接到某个服务。
3. **发送请求并接收响应** —— 向服务发送请求并接收响应。可选地注册一个回调，以接收来自服务的非请求触发的指示。
4. **断开并销毁** —— 从服务断开并销毁句柄。

在句柄销毁之前，请保持传入句柄创建函数的私有上下文有效。

## 创建句柄并连接

创建客户端的步骤：

1. 创建一个 QMI 句柄，并附带一个在发生服务或传输事件时调用的回调函数。
2. 通过指定服务 ID 和实例 ID 将句柄连接到某个服务。
3. 可选地注册一个服务事件通知器，以应对服务可用性变化。

## 消息描述符

描述符告知编解码器如何在你的 C 结构与 QMI 线路格式之间进行转换。一个描述符标识：

* 消息 ID（这是哪个操作或事件）
* 消息的最大长度
* 一组字段描述，每个描述指定数据类型、数组行为、字段标签以及在 C 结构中的位置

描述符可以表示原语值、定长和变长数组、嵌套结构以及可选字段。你只需描述一次消息，并将描述符复用于请求、响应和指示。

## 编码与解码

当你需要在请求助手之外构造或检查消息时，可以显式地编码和解码消息。编解码器负责在 C 结构和线路格式之间进行转换。

## 同步请求

发送请求并等待其响应，直到达到指定的超时时间。仅在调用方可以安全阻塞时使用此形式。从调用方角度看，超时属于事务失败；但它不能证明远端服务没有收到或没有处理该请求。

## 异步请求

发送请求但不等待响应。响应回调会收到消息 ID、解码后的响应存储以及调用方的私有回调数据。请求、响应存储、描述符和回调上下文必须在接口实现所要求的生命周期内保持有效。

## 指示回调

为非请求触发的服务事件注册指示回调。回调会收到消息 ID、消息缓冲区、消息长度和私有上下文。使用该消息 ID 对应的描述符解码指示，并将每个长度和可选字段视为不可信输入。

## 接收与销毁

只有在挂起的回调和事务都已经静默（quiesced）之后，才可销毁句柄。具体的拆解顺序应保证在释放之后没有回调可以访问句柄或客户端上下文。

## API 参考

### 回调函数原型

客户端框架在客户端生命周期的关键节点调用以下回调：

```c theme={null}
void qmi_client_notify_cb(qmi_client_type user_handle,
                          qmi_idl_service_object_type service_obj,
                          qmi_client_notify_event_type service_event,
                          void *notify_cb_data);

void qmi_client_recv_raw_msg_async_cb(qmi_client_type user_handle,
                                      unsigned int msg_id,
                                      void *resp_buf,
                                      unsigned int resp_buf_len,
                                      void *resp_cb_data,
                                      qmi_client_error_type transp_err);

void qmi_client_recv_msg_async_cb(qmi_client_type user_handle,
                                  unsigned int msg_id,
                                  void *resp_c_struct,
                                  unsigned int resp_c_struct_len,
                                  void *resp_cb_data,
                                  qmi_client_error_type transp_err);

void qmi_client_ind_cb(qmi_client_type user_handle,
                       unsigned int msg_id,
                       void *ind_buf,
                       unsigned int ind_buf_len,
                       void *resp_cb_data);

void qmi_client_error_cb(qmi_client_type user_handle,
                         qmi_client_error_type error,
                         void *err_cb_data);

void qmi_client_release_cb(void *release_cb_data);
```

### 连接类 API

以下函数管理客户端到服务的连接：

* `qmi_client_notifier_init(qmi_idl_service_object_type service_obj, qmi_client_os_params *os_params, qmi_client_type *user_handle)` —— 使用服务对象和 OS 相关参数初始化一个通知器，以接收服务可用性事件。

* `qmi_client_init(qmi_service_info *service_info, qmi_idl_service_object_type service_obj, qmi_client_ind_cb ind_cb, void *ind_cb_data, qmi_client_os_params *os_params, qmi_client_type *user_handle)` —— 为特定服务实例创建一个客户端句柄。

* `qmi_client_init_instance(qmi_idl_service_object_type service_obj, qmi_service_instance instance_id, qmi_client_ind_cb ind_cb, void *ind_cb_data, qmi_client_os_params *os_params, uint32_t timeout, qmi_client_type *user_handle)` —— 为具有特定实例 ID 的服务创建客户端句柄，并可选支持超时。

* `qmi_client_get_service_list(qmi_idl_service_object_type service_obj, qmi_service_info *service_info_array, uint32_t num_entries, uint32_t *num_services)` —— 查询与某服务对象匹配的可用服务。

* `qmi_client_get_any_service(qmi_idl_service_object_type service_obj, qmi_service_info *service_info)` —— 获取匹配某服务对象的第一个可用服务。

* `qmi_client_get_service_instance(qmi_idl_service_object_type service_obj, qmi_service_instance instance_id, qmi_service_info *service_info)` —— 通过实例 ID 获取一个特定的服务实例。

* `qmi_client_register_error_cb(qmi_client_type user_handle, qmi_client_error_cb err_cb, void *err_cb_data)` —— 注册一个回调，在服务终止或注销时被调用。

* `qmi_client_register_notify_cb(qmi_client_type user_handle, qmi_client_notify_cb notify_cb, void *notify_cb_data)` —— 注册一个用于服务可用性事件的回调。

### 消息发送 API

以下函数向服务发送请求：

* `qmi_client_send_raw_msg_sync(qmi_client_type user_handle, unsigned int msg_id, void *req_buf, unsigned int req_buf_len, void *resp_buf, unsigned int resp_buf_len, unsigned int resp_buf_recv_len, unsigned int timeout_msecs)` —— 发送请求并等待响应（原始格式）。

* `qmi_client_send_msg_sync(qmi_client_type user_handle, unsigned int msg_id, void *req_c_struct, unsigned int req_c_struct_len, void *resp_c_struct, unsigned int resp_c_struct_len, unsigned int resp_c_struct_recv_len, unsigned int timeout_msecs)` —— 发送请求，自动进行编码和解码。

* `qmi_client_send_raw_msg_async(qmi_client_type user_handle, unsigned int msg_id, void *req_buf, unsigned int req_buf_len, void *resp_buf, unsigned int resp_buf_len, qmi_client_async_rsp_cb resp_cb, void *resp_cb_data, qmi_txn_handle *txn_handle)` —— 发送请求但不等待（原始格式）。

* `qmi_client_send_msg_async(qmi_client_type user_handle, unsigned int msg_id, void *req_c_struct, unsigned int req_c_struct_len, void *resp_c_struct, unsigned int resp_c_struct_len, qmi_client_recv_msg_async_cb resp_cb, void *resp_cb_data, qmi_txn_handle *txn_handle)` —— 发送请求，自动编码。

* `qmi_client_delete_async_txn(qmi_client_type user_handle, qmi_txn_handle async_txn_handle)` —— 取消一个挂起的异步请求。

* `qmi_client_get_async_txn_id(qmi_client_type user_handle, qmi_txn_handle async_txn_handle, uint32_t *txn_id)` —— 获取挂起异步请求的事务 ID（已弃用）。

### 编解码 API

以下函数在 C 结构和 QMI 线路格式之间进行转换：

* `qmi_client_message_encode(qmi_client_type user_handle, qmi_idl_type_of_message_type req_resp_ind, unsigned int message_id, const void *p_src, unsigned int src_len, void *p_dst, unsigned int dst_len, unsigned int *dst_encoded_len)` —— 将 C 结构编码为 QMI 线路格式。

* `qmi_client_message_decode(qmi_client_type user_handle, qmi_idl_type_of_message_type req_resp_ind, unsigned int message_id, const void *p_src, unsigned int src_len, void *p_dst, unsigned int dst_len)` —— 将 QMI 线路格式消息解码为 C 结构。

### 释放 API

* `qmi_client_release_async(qmi_client_type user_handle, qmi_client_release_cb release_cb, void *release_cb_data)` —— 异步释放客户端句柄。
