# USBNET功能 ***Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.*** --- # 功能概述 USBNET是基于USB接口实现网络共享的技术统称,在Linux内核中对应USBNET驱动框架,支持ECM、NCM、RNDIS、MBIM等多种协议。其核心机制是在USB通信中模拟标准网络设备:主机的网络协议栈通过虚拟USB网络适配器与设备相连,设备作为网关将流量转发至移动网络,从而使主机能够通过设备的移动网络访问互联网。 ## 基本要素 1. **USB设备:** 蜂窝模块或内置模块的终端设备。作为USB从设备,需实现特定的USB接口类型,向主机声明自身为网络适配器。 2. **主机驱动:** 运行在主机操作系统上的软件,用于识别USB设备并驱动其呈现的网络接口。不同的USBNET协议对应不同的驱动。 3. **网络接口:** 主机操作系统中呈现的虚拟网卡,操作系统通过此接口进行IP配置、路由配置和网络通信。 4. **数据通道:** USB设备与主机之间用于传输网络数据包的逻辑通道,通常通过USB批量传输端点交换数据。 ## 流程概述 USBNET流程是指将设备的移动数据连接通过USB桥接并共享给主机的端到端过程,通常包含以下操作步骤: 1. **设备枚举与识别**:设备连接到主机后,主机查询其USB描述符,识别设备所属的设备类(通信设备类或特定厂商类),并加载对应驱动,完成网络适配器的注册。 2. **接口初始化与连接**:驱动与设备进行初始化握手,配置USB端点和通信参数。设备端USBNET服务激活后,开始从移动数据连接读取数据;主机端虚拟网络接口状态变为"已连接"。 3. **IP配置**:主机通过DHCP向设备请求IP配置。设备内嵌的DHCP服务器为主机分配私有IP地址并下发网关地址,主机完成IP和路由配置。 4. **数据包转发**: **下行**:设备从移动网络接收IP数据包,通过USB通道发送至主机驱动,驱动解包后提交至主机网络协议栈。 **上行**:主机产生的IP数据包经虚拟网络接口和驱动,通过USB发送至设备,再由设备转发至移动网络。 5. **连接断开**:停止USBNET服务时,设备通知主机驱动,驱动将网络接口标记为断开,随后关闭数据通道并释放资源。 **主机接收网络数据:** ```{image} images/image_SMJvbHKvEotuPAxSiPQcVK6PnLc.webp :width: 2960px :height: 4628px :align: center ``` **主机发送数据到网络:** ```{image} images/image_HJp2belklolqlSxBiuKcGOCJnOh.webp :width: 2960px :height: 5492px :align: center ``` ## 主要协议对比 | **协议** | **全称** | **性质与描述** | **优点** | **缺点** | **主要适用系统** | | --- | --- | --- | --- | --- | --- | | RNDIS | Remote Network Driver Interface Specification | 微软制定的私有协议,通过在USB上封装以太网帧实现通信,已成为Windows事实标准。 | Windows兼容性最佳,即插即用,无需额外安装驱动。 | 协议复杂冗余;在Linux/macOS上需额外驱动或兼容层。 | Windows | | ECM | Ethernet Control Model | USB-IF官方标准。直接在USB上传输原始以太网帧,协议简洁。 | 跨平台标准,在Linux、macOS和现代Windows上支持良好、稳定。 | 在旧版本Windows上可能需要手动安装驱动。 | Linux,macOS,现代Windows | | NCM | Network Control Model | CDC ECM的增强版标准。核心改进是支持数据包聚合,将多个IP数据包聚合到一个USB传输中,提升效率。 | 高性能,在大带宽场景下吞吐量和效率显著高于ECM/RNDIS;跨平台兼容性好。 | 协议实现稍复杂,需驱动和设备端同时支持。 | Linux,macOS,现代Windows(尤其适合4G/5G高速场景) | | MBIM | Mobile Broadband Interface Model | 微软与行业联合制定的现代标准。专为移动宽带设计,在USB上传输原始的、未封装的IP数据包,控制与数据分离。 | 架构现代高效,直接处理IP数据包,开销低;支持丰富的移动网络功能管理;是Windows 8+及5G时代的推荐标准。 | 协议相对复杂;在旧系统或非Windows平台上支持可能有限。 | 现代Windows (8+),5G设备 | ## 数据结构 USBNET的实现依赖以下核心数据结构层次: - USB描述符层: 设备通过此层向主机声明身份。关键描述符包括设备描述符、配置描述符、接口描述符和端点描述符,它们共同定义了"通信接口类"和"数据接口",后者关联的批量传输端点用于传输网络数据。 - 协议控制消息层(以RNDIS/MBIM为例): 该层提供连接管理和参数协商功能,通过USB控制传输或中断传输端点交换带外控制消息。 **RNDIS:** 使用 *RNDIS_INITIALIZE_MSG*、*RNDIS_QUERY_MSG* 等控制消息。 **MBIM:** 使用 *MBIM_COMMAND_MSG*、*MBIM_COMMAND_DONE* 等结构化消息管理网络功能。 - 网络数据帧层: 传输实际用户网络数据的带内数据通道,封装格式因协议而异: **RNDIS:** 以太网帧包裹在 *RNDIS_PACKET_MSG* 结构中传输。 **ECM:** 在USB端点上直接传输完整的以太网帧。 **NCM:** 传输NCM传输块,其中聚合了多个IP数据包,效率更高。 **MBIM:** 在USB端点上直接传输原始的IP数据包,无需额外的链路层封装,协议开销较低。 ## 网络激活管理 参照:[DataCall拨号](../../%E8%9C%82%E7%AA%9D%E6%97%A0%E7%BA%BF%E7%BD%91%E5%8D%A1/DataCall%E6%8B%A8%E5%8F%B7/DataCall%E6%8B%A8%E5%8F%B7.md) # USBNET API ## 头文件 *qosa_usbnet.h* ## 函数概览 | **函数** | **说明** | | --- | --- | | *qosa_usbnet_get_type()* | 获取USBNET应用协议类型 | | *qosa_usbnet_set_type()* | 设置USBNET应用协议类型 | | *qosa_usbnet_set_config()* | 设置USBNET连接配置项 | | *qosa_usbnet_get_config()* | 获取USBNET连接配置项 | | *qosa_usbnet_start()* | 启动USBNET连接 | | *qosa_usbnet_stop()* | 停止USBNET连接 | ## 函数详解 ### qosa_usbnet_get_type - **功能描述** 获取USBNET应用协议类型。 - **函数原型** ```c qosa_usbnet_err_e qosa_usbnet_get_type(qosa_uint8_t simid, qosa_usbnet_type_e *type) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *simid* | 输入 | qosa_uint8_t | SIM卡ID;范围:0~1
*0*:卡槽1
*1*:卡槽2 | | *type* | 输出 | *qosa_usbnet_type_e** | 协议类型;详见 [*qosa_usbnet_type_e*](#qosausbnettype_e) | - **返回值说明** *QOSA_USBNET_ERR_OK*:函数执行成功 其他值(详见 [*qosa_usbnet_err_e*](#qosausbneterr_e)):函数执行失败 ### qosa_usbnet_set_type - **功能描述** 设置USBNET应用协议类型。 - **函数原型** ```c qosa_usbnet_err_e qosa_usbnet_set_type(qosa_uint8_t simid, qosa_usbnet_type_e type) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *simid* | 输入 | qosa_uint8_t | SIM卡ID;范围:0~1
*0*:卡槽1
*1*:卡槽2 | | *type* | 输入 | *qosa_usbnet_type_e* | 协议类型;详见 [*qosa_usbnet_type_e*](#qosausbnettype_e) | - **返回值说明** *QOSA_USBNET_ERR_OK*:函数执行成功 其他值(详见 [*qosa_usbnet_err_e*](#qosausbneterr_e)):函数执行失败 ```{note} 设置的USBNET应用协议类型在设备重启后生效。 ``` ### qosa_usbnet_set_config - **功能描述** 设置USBNET连接配置项。 - **函数原型** ```c qosa_usbnet_err_e qosa_usbnet_set_config(qosa_uint8_t simid, qosa_usbnet_config_t *config) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *simid* | 输入 | qosa_uint8_t | SIM卡ID;范围:0~1
*0*:卡槽1
*1*:卡槽2 | | *config* | 输入 | *qosa_usbnet_config_t** | 连接配置项;详见 [*qosa_usbnet_config_t*](#qosausbnetconfig_t) | - **返回值说明** *QOSA_USBNET_ERR_OK*:函数执行成功 其他值(详见 [*qosa_usbnet_err_e*](#qosausbneterr_e)):函数执行失败 ### qosa_usbnet_get_config - **功能描述** 获取USBNET连接配置项。 - **函数原型** ```c qosa_usbnet_err_e qosa_usbnet_get_config(qosa_uint8_t simid, qosa_usbnet_config_t *config) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *simid* | 输入 | qosa_uint8_t | SIM卡ID;范围:0~1
*0*:卡槽1
*1*:卡槽2 | | *config* | 输出 | *qosa_usbnet_config_t** | 连接配置项;详见 [*qosa_usbnet_config_t*](#qosausbnetconfig_t) | - **返回值说明** *QOSA_USBNET_ERR_OK*:函数执行成功 其他值(详见 [*qosa_usbnet_err_e*](#qosausbneterr_e)):函数执行失败 ### qosa_usbnet_start - **功能描述** 启动USBNET连接,进行网络共享。 - **函数原型** ```c qosa_usbnet_err_e qosa_usbnet_start(qosa_uint8_t simid, usbnet_callback_t cb, void *ctx) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *simid* | 输入 | qosa_uint8_t | SIM卡ID;范围:0~1
*0*:卡槽1
*1*:卡槽2 | | *cb* | 输入 | *usbnet_callback_t* | 启动USBNET连接,返回状态的回调函数 | | *ctx* | 输入 | void * | 回调函数上下文 | - **返回值说明** *QOSA_USBNET_ERR_OK*:函数执行成功 其他值(详见 [*qosa_usbnet_err_e*](#qosausbneterr_e)):函数执行失败 ### qosa_usbnet_stop - **功能描述** 停止USBNET连接,断开网络共享。 - **函数原型** ```c qosa_usbnet_err_e qosa_usbnet_stop(qosa_uint8_t simid, usbnet_callback_t cb, void *ctx) ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *simid* | 输入 | qosa_uint8_t | SIM卡ID;范围:0~1
*0*:卡槽1
*1*:卡槽2 | | *cb* | 输入 | *usbnet_callback_t* | 停止USBNET连接,返回状态的回调函数 | | *ctx* | 输入 | void * | 回调函数上下文 | - **返回值说明** *QOSA_USBNET_ERR_OK*:函数执行成功 其他值(详见 [*qosa_usbnet_err_e*](#qosausbneterr_e)):函数执行失败 #### usbnet_callback_t - **函数原型** ```c typedef void (*usbnet_callback_t)(void *ctx, void *argv); ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *ctx* | 输入 | void * | 用户上下文指针 | | *argv* | 输入 | void * | 回调参数指针 | ## 结构体定义 ### qosa_usbnet_config_t 配置USBNET连接参数的结构体定义如下: ```c typedef struct { qosa_uint8_t simid; qosa_uint8_t pdpid; qosa_usbnet_method_e method; } qosa_usbnet_config_t; ``` | **参数** | **类型** | **说明** | | --- | --- | --- | | *simid* | qosa_uint8_t | SIM卡ID;范围:0~1
*0*:卡槽1
*1*:卡槽2 | | *pdpid* | qosa_uint8_t | PDP ID;范围:1~15 | | *method* | *qosa_usbnet_method_e* | 连接方式;详见 [*qosa_usbnet_method_e*](#qosausbnetmethod_e) | ```{note} 仅当连接方式(*method*)为 *0* 时,配置文件ID(*pdpid*)才允许设置为 *0*。 ``` ## 枚举定义 ### qosa_usbnet_type_e 协议类型枚举定义如下: ```c typedef enum { QOSA_USBNET_TYPE_ECM = 1, QOSA_USBNET_TYPE_MBIM = 2, QOSA_USBNET_TYPE_RNDIS = 3, QOSA_USBNET_TYPE_NCM = 5, } qosa_usbnet_type_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_USBNET_TYPE_ECM* | ECM协议 | | *QOSA_USBNET_TYPE_MBIM* | MBIM协议 | | *QOSA_USBNET_TYPE_RNDIS* | RNDIS协议 | | *QOSA_USBNET_TYPE_NCM* | NCM协议 | ### qosa_usbnet_method_e 连接方式枚举定义如下: ```c typedef enum { QOSA_USBNET_METHOD_DISABLE = 0, QOSA_USBNET_METHOD_ONE_SHOT = 1, QOSA_USBNET_METHOD_AUTO_CONNECT = 3, } qosa_usbnet_method_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_USBNET_METHOD_DISABLE* | 禁用 | | *QOSA_USBNET_METHOD_ONE_SHOT* | 单次连接 | | *QOSA_USBNET_METHOD_AUTO_CONNECT* | PDP连接断开或上电等情况下USBNET将自动重新连接,重连间隔逐渐增大 | ### qosa_usbnet_err_e USBNET模块的结果码枚举定义如下: ```c typedef enum usbnet_err { QOSA_USBNET_ERR_OK = 0, QOSA_USBNET_ERR_OPERATION_NOT_ALLOWED = 3 | QOSA_ERRCODE_USBNET_BASE, QOSA_USBNET_ERR_OPERATION_NOT_SUPPORTED = 4 | QOSA_ERRCODE_USBNET_BASE, QOSA_USBNET_ERR_MEMORY_FULL = 20 | QOSA_ERRCODE_USBNET_BASE, QOSA_USBNET_ERR_MEMORY_FAILURE = 23 | QOSA_ERRCODE_USBNET_BASE, QOSA_USBNET_ERR_INVALID_PARAM = 53 | QOSA_ERRCODE_USBNET_BASE, QOSA_USBNET_ERR_EXECUTE = 1 | (QOSA_ERRCODE_USBNET_BASE + QOSA_AT_ERR_OFS), QOSA_USBNET_ERR_BUSY = 2 | (QOSA_ERRCODE_USBNET_BASE + QOSA_AT_ERR_OFS), QOSA_USBNET_ERR_ALREADY_CONNECTED = 3 | (QOSA_ERRCODE_USBNET_BASE + QOSA_AT_ERR_OFS), } qosa_usbnet_err_e; ``` | **成员** | **说明** | | --- | --- | | *QOSA_USBNET_ERR_OK* | 操作成功 | | *QOSA_USBNET_ERR_OPERATION_NOT_ALLOWED* | 操作不被允许 | | *QOSA_USBNET_ERR_OPERATION_NOT_SUPPORTED* | 操作不被支持 | | *QOSA_USBNET_ERR_MEMORY_FULL* | 内存已满 | | *QOSA_USBNET_ERR_MEMORY_FAILURE* | 内存故障 | | *QOSA_USBNET_ERR_INVALID_PARAM* | 无效参数 | | *QOSA_USBNET_ERR_EXECUTE* | 操作执行 | | *QOSA_USBNET_ERR_BUSY* | 模块忙 | | *QOSA_USBNET_ERR_ALREADY_CONNECTED* | 已连接 | # 应用逻辑流程图 ```{image} images/board_QinCw2MxyhuoQobsmRkcRh6Unbb.jpg :width: 789px :height: 1471px :align: center ``` # 示例代码 完整示例代码请查看https://github.com/UniRTOS/UniRTOS-Doc-Examples/blob/main/network/nic/usbnet/usbnet_demo.c