• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# USB
2
3## 概述
4
5### 功能简介
6
7USB(Universal Serial Bus)通用串行总线,包含了主机端(Host)和设备端(Device)。主机端负责USB总线中的数据传输及端口管理,设备端则可以连接各种外设,所以USB驱动开发又分为主机端驱动开发和设备端驱动开发。
8
9OpenHarmony系统USB模块支持USB业务的开发,提供USB相关的功能,提供用户态第三方功能驱动的USB设备数据读写接口,以及提供创建和删除USB设备,接口的事件获取、打开和关闭等,管道同步异步读写通信,设置USB自定义属性等。
10
11USB DDK(USB DriverDevelop Kit)是HDF驱动框架为开发者提供的USB驱动程序开发套件,包括USB Host DDK及USB Device DDK两部分,支持基于用户态开发USB设备驱动的同时,还提供了丰富的USB驱动开发能力,让广大开发者能精准且高效的开发USB驱动程序。
12
13### 基本概念
14
15- 管道
16
17  管道(Pipe)是主机端和设备端点之间数据传输的模型。任何USB设备一旦上电就存在一个信息管道,即默认的控制管道,USB主机通过该管道来获取设备的描述、配置、状态,并对设备进行配置;管道和端点关联,两者有相同的属性,如支持的传输类型、最大包长度、传输方向等。
18
19- 端点
20
21  端点(Endpoint)是USB设备中的可以进行数据收发的最小单元,支持单向或者双向的数据传输。一个USB设备可以包括若干个端点,不同的端点以端点编号和方向区分。不同端点可以支持不同的传输类型、访问间隔以及最大数据包大小。除端点0外,所有的端点只支持一个方向的数据传输。端点0是一个特殊的端点,它支持双向的控制传输。
22
23- 接口
24
25  应用软件通过和设备之间的数据交换来完成设备的控制和数据传输。由于同一管道只支持一种类型的数据传输,因此这个过程中通常需要多个管道来完成数据交换。像这样用在一起来对设备进行控制的若干管道的集合称为接口。
26
27- 描述符
28
29  描述符(Descriptor)是用于描述设备属性(Attributes)的数据结构,第一个字节表示描述符的大小(字节数),第二个字节表示描述符的类型(Type)。
30
31### 运作机制
32
33#### USB Host DDK
34
35USB Host DDK为开发者提供了主机端USB驱动开发能力,按照功能分为三大类,分别是DDK初始化类、interface对象操作类及request对象操作类。
36
37  **图1** USB Host驱动模型图
38
39  ![image](figures/USB-Host驱动模型图.png "USB-Host驱动模型图")
40
41- USB Interface Pool负责USB Interface管理。提供USB Interface接口对象的申请和回收,USB Interface接口对象用来记录设备端口信息以及资源。USB Interface Pool按照USB Port对USB Interface进行分类管理。同时,此模块还提供了USB DDK API,方便开发者进行USB数据读写操作。
42
43- USB Protocol Layer提供USB协议封装,根据USB协议对设备IO/控制命令进行翻译和解析”,同时负责设备描述符的管理,根据USB Device上报的枚举信息,匹配对应的描述符;构建对应的USB Interface接口对象,并将其加入到USB Interface Pool中管理。
44
45- Device IO Manager负责USB IO请求管理,提供了同步IO和异步IO管理机制,对于异步IO,IO Manager负责将该请求记录下来,然后通过Raw API Library提供的接口依次处理待发送的IO请求;当收到USB控制器应答的处理结果后,IO接收线程负责解析并上报处理结果给上层调用者。
46
47- Raw API Library抽象了底层OS能力,定义了统一的OS能力接口,对外提供了USB RAW API,方便开发者实现更加复杂的驱动功能。
48
49- OS Adapter用于封装与平台(Linux和LiteOS)相关的操作,根据不同平台配置编译对应平台的封装接口。在Linux平台上,访问USB FS的操作,全部都封装在这个模块中;而在LiteOS平台上,基于FreeBSD USB框架的设备访问操作,也都全部封装在这个模块中。
50
51- PNP Notify用于动态监测USB状态变化,当有新设备添加/移除时,变化设备信息。同时将所有USB设备信息都通过KHDF上报给UHDF侧的PNP Notify Manager模块来完成加载/卸载第三方功能驱动。
52
53#### USB Device DDK
54
55USB Device DDK向开发者提供了设备端USB驱动开发能力。例如,USB端口动态注册和去注册能力,开发者可以基于能力实现USB端口的动态添加和组合;动态实例化能力,支持根据动态下发设备、配置、接口及端点描述符创建设备实例及传输通道;用户态的数据发送及接收能力,支持用户态下发送及接收数据;复合设备能力,支持一个物理设备上多个逻辑设备,实现多个逻辑设备间隔离,并支持不同逻辑设备同时被不同的应用进程访问。
56
57  **图2** USB Device驱动模型图
58
59  ![image](figures/USB-Device驱动模型图.png "USB-Device驱动模型图")
60
61- SDK IF负责将USB设备按照设备、接口、管道进行逻辑划分,对配置管理、设备管理、IO管理进行封装。此模块还向开发者提供了设备创建、获取接口、接收Event事件、收发数据等设备测驱动开发的能力接口。
62
63- Configuration Manager负责解析HCS文件描述的USB描述符信息,得到的USB描述符信息用于设备创建,同时模块还提供了自定义属性的读取、创建、删除、修改等操作。
64
65- Device Manager负责根据配置模块解析USB描述符,并根据USB描述符创建设备。同时还负责获取设备、删除设备、获取设备状态,获取设备上面接口信息。
66
67- IO Manager负责数据的读写,包括Events事件、数据读写完成后事件的接收,支持同步和异步模式数据读写。
68
69- Adapter IF主要是对复合设备配置驱动及通用功能驱动设备节点操作进行封装,为上层提供统一的设备管理接口。
70
71- Adapter该模块由复合设备配置驱动及通用功能驱动提供。
72
73## 开发指导
74
75由于内核态开发USB驱动较复杂,需要开发者对USB协议要有较深的了解才能很好的使用,对开发者的要求相对较高。USB DDK的引入是为了让开发者能在用户态更方便的开发USB驱动。
76
77### 场景介绍
78
79USB Host DDK为开发者提供了普通模式和专家模式,普通模式下,开发者可通过USB DDK API直接完成相关USB数据读写操作,不需要过多关注底层的传输细节。专家模式下,开发者通过USB RAW API直接访问OS平台中USB通道的接口,自定义实现更加复杂的功能。USB Device DDk为开发者提供了管理USB设备、接口定义及USB数据请求等功能。下文将介绍相关API。
80
81### 接口说明
82
83USB主机端驱动程序开发相关接口(普通模式)如下,具体接口定义[见源码](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/host/usb_ddk_interface.h)84
85  **表1** USB主机端驱动程序开发相关接口(普通模式)
86
87| 接口名称 | 功能描述 |
88| -------- | -------- |
89| int32_t UsbInitHostSdk(struct UsbSession \*\*session); | USB主机端驱动开发工具包初始化 |
90| const&nbsp;struct&nbsp;UsbInterface&nbsp;\*UsbClaimInterface(const<br/>struct&nbsp;UsbSession&nbsp;\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t<br/>usbAddr,&nbsp;uint8_t&nbsp;interfaceIndex); | 获取USB接口对象 |
91| UsbInterfaceHandle&nbsp;\*UsbOpenInterface(const&nbsp;struct<br/>UsbInterface&nbsp;\*interfaceObj); | 打开USB对象接口 |
92| int32_t&nbsp;UsbGetPipeInfo(const&nbsp;UsbInterfaceHandle<br/>\*interfaceHandle,&nbsp;uint8_t&nbsp;settingIndex,&nbsp;uint8_t&nbsp;pipeId,<br/>struct&nbsp;UsbPipeInfo&nbsp;\*pipeInfo); | 获取指定可选设置的管道信息 |
93| struct&nbsp;UsbRequest&nbsp;\*UsbAllocRequest(const<br/>UsbInterfaceHandle&nbsp;\*interfaceHandle,&nbsp;int32_t&nbsp;isoPackets<br/>,&nbsp;int32_t&nbsp;length); | 分配请求对象 |
94| int32_t&nbsp;UsbFillRequest(const&nbsp;struct&nbsp;UsbRequest<br/>\*request,&nbsp;const&nbsp;UsbInterfaceHandle&nbsp;\*interfaceHandle,<br/>const&nbsp;struct&nbsp;UsbRequestParams&nbsp;\*params); | 填充请求 |
95| int32_t&nbsp;UsbSubmitRequestSync(const&nbsp;struct&nbsp;UsbRequest<br/>\*request); | 发送同步请求 |
96
97USB主机端驱动程序开发相关接口(专家模式)如下,具体接口定义[见源码](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/host/usb_raw_api.h)98
99  **表2** USB主机端驱动程序开发相关接口(专家模式)
100
101| 接口名称 | 功能描述 |
102| -------- | -------- |
103| int32_t&nbsp;UsbRawInit(struct&nbsp;UsbSession&nbsp;\*\*session); | USB驱动开发工具包专家模式初始化 |
104| UsbRawHandle&nbsp;\*UsbRawOpenDevice(const&nbsp;struct<br/>UsbSession&nbsp;\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t<br/>usbAddr); | 打开USB设备对象 |
105| int32_t&nbsp;UsbRawSendControlRequest(const&nbsp;struct<br/>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbControlRequestData<br/>\*requestData); | 执行同步控制传输 |
106| int32_t&nbsp;UsbRawSendBulkRequest(const&nbsp;struct<br/>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbRequestData<br/>\*requestData); | 执行同步批量传输 |
107| int32_t&nbsp;UsbRawSendInterruptRequest(const&nbsp;struct<br/>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbRequestData<br/>\*requestData); | 执行同步中断传输 |
108| int32_t&nbsp;UsbRawGetConfigDescriptor(const&nbsp;UsbRawDevice<br/>\*rawDev,&nbsp;uint8_t&nbsp;configIndex,&nbsp;struct<br/>UsbRawConfigDescriptor&nbsp;\*\*config); | 获取给定设备指定ID的设备配置描述符 |
109| int32_t&nbsp;UsbRawFillInterruptRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br/>UsbRawFillRequestData&nbsp;\*fillData); | 填充中断传输请求所需信息 |
110| int32_t&nbsp;UsbRawFillIsoRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br/>UsbRawFillRequestData&nbsp;\*fillData); | 填充同步传输(Isochronous&nbsp;Transfers)请求所需信息 |
111| int32_t&nbsp;UsbRawSubmitRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request); | 提交一个传输请求 |
112| int32_t&nbsp;UsbRawCancelRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request); | 取消一个传输请求 |
113| int32_t&nbsp;UsbRawHandleRequests(const&nbsp;UsbRawHandle<br/>\*devHandle); | 传输请求事件完成处理 |
114
115USB设备端用于管理USB设备的相关接口如下,具体接口定义[见源码](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/device/usbfn_device.h)116
117  **表3** USB设备端用于管理USB设备的相关接口
118
119| 接口名称 | 功能描述 |
120| -------- | -------- |
121| const&nbsp;struct&nbsp;UsbFnDevice&nbsp;\*UsbFnCreateDevice(const<br/>char&nbsp;\*udcName,&nbsp;const&nbsp;struct&nbsp;UsbFnDescriptorData<br/>\*descriptor); | 创建USB设备 |
122| int32_t&nbsp;UsbFnRemoveDevice(struct&nbsp;UsbFnDevice<br/>\*fnDevice); | 删除USB设备 |
123| const&nbsp;struct&nbsp;UsbFnDevice&nbsp;\*UsbFnGetDevice(const&nbsp;char<br/>\*udcName); | 获取USB设备 |
124
125USB设备端用于USB接口定义的相关接口如下,具体接口定义[见源码](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/device/usbfn_interface.h)126
127  **表4** USB设备端用于USB接口定义的相关接口
128
129| 接口名称 | 功能描述 |
130| -------- | -------- |
131| int32_t&nbsp;UsbFnStartRecvInterfaceEvent(struct<br/>UsbFnInterface&nbsp;\*interface,&nbsp;uint32_t&nbsp;eventMask,<br/>UsbFnEventCallback&nbsp;callback,&nbsp;void&nbsp;\*context); | 开始接受Event事件 |
132| int32_t&nbsp;UsbFnStopRecvInterfaceEvent(struct<br/>UsbFnInterface&nbsp;\*interface); | 停止接受Event事件 |
133| UsbFnInterfaceHandle&nbsp;UsbFnOpenInterface(struct&nbsp;UsbFnInterface&nbsp;\*interface); | 打开一个接口 |
134| int32_t&nbsp;UsbFnCloseInterface(UsbFnInterfaceHandle&nbsp;handle); | 关闭一个接口 |
135| int32_t&nbsp;UsbFnGetInterfacePipeInfo(struct&nbsp;UsbFnInterface<br/>\*interface,&nbsp;uint8_t&nbsp;pipeId,&nbsp;struct&nbsp;UsbFnPipeInfo&nbsp;\*info); | 获取管道信息 |
136| int32_t&nbsp;UsbFnSetInterfaceProp(const&nbsp;struct&nbsp;UsbFnInterface<br/>\*interface,&nbsp;const&nbsp;char&nbsp;\*name,&nbsp;const&nbsp;char&nbsp;\*value); | 设置自定义属性 |
137
138USB设备端用于管理USB数据请求的相关接口如下,具体接口定义[见源码](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/device/usbfn_request.h)139
140  **表5** USB设备端用于管理USB数据请求的相关接口
141
142| 接口名称 | 功能描述 |
143| -------- | -------- |
144| struct&nbsp;UsbFnRequest<br/>\*UsbFnAllocCtrlRequest(UsbFnInterfaceHandle&nbsp;handle,<br/>uint32_t&nbsp;len); | 申请一个控制请求 |
145| struct&nbsp;UsbFnRequest&nbsp;\*UsbFnAllocRequest(UsbFnInterfaceHandle&nbsp;handle,<br/>uint8_t&nbsp;pipe,&nbsp;uint32_t&nbsp;len); | 申请一个数据请求 |
146| int32_t&nbsp;UsbFnFreeRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | 释放一个请求 |
147| int32_t&nbsp;UsbFnSubmitRequestAsync(struct&nbsp;UsbFnRequest<br/>\*req); | 发送异步请求 |
148| int32_t&nbsp;UsbFnSubmitRequestSync(struct&nbsp;UsbFnRequest<br/>\*req,&nbsp;uint32_t&nbsp;timeout); | 发送同步请求 |
149| int32_t&nbsp;UsbFnCancelRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | 取消请求 |
150
151
152### 开发步骤
153
154USB驱动基于HDF框架、Platform和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同USB器件提供统一的驱动模型。此处以串口为例,分别介绍USB Host和USB Device驱动开发的详细过程。
155
156#### Host DDK API驱动开发
157
1581. 在设备私有数据HCS中配置,完成主机端驱动总体信息的配置,具体如下:
159
160    ```cpp
161    root {
162        module = "usb_pnp_device";
163        usb_pnp_config {
164            match_attr = "usb_pnp_match";
165            usb_pnp_device_id = "UsbPnpDeviceId";
166            UsbPnpDeviceId {
167                idTableList = [
168                    "host_acm_table"
169                ];
170                host_acm_table {
171                    // 驱动模块名,该字段的值必须和驱动入口结构的moduleName一致
172                    moduleName = "usbhost_acm";
173                    // 驱动对外发布服务的名称,必须唯一
174                    serviceName = "usbhost_acm_pnp_service";
175                    // 驱动私有数据匹配关键字
176                    deviceMatchAttr = "usbhost_acm_pnp_matchAttr";
177                    // 从该字段开始(包含该字段)之后数据长度,以byte为单位
178                    length = 21;
179                    // USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber
180                    matchFlag = 0x0303;
181                    // 厂商编号
182                    vendorId = 0x12D1;
183                    // 产品编号
184                    productId = 0x5000;
185                    // 设备出厂编号,低16位
186                    bcdDeviceLow = 0x0000;
187                    // 设备出厂编号,高16位
188                    bcdDeviceHigh = 0x0000;
189                    // USB分配的设备类代码
190                    deviceClass = 0;
191                    // USB分配的子类代码
192                    deviceSubClass = 0;
193                    // USB分配的设备协议代码
194                    deviceProtocol = 0;
195                    // 接口类型,根据实际需要可填写多个
196                    interfaceClass = [0];
197                    // 接口子类型,根据实际需要可填写多个
198                    interfaceSubClass = [2, 0];
199                    // 接口所遵循的协议,根据实际需要可填写多个
200                    interfaceProtocol = [1, 2];
201                    // 接口的编号,根据实际需要可填写多个
202                    interfaceNumber = [2, 3];
203                }
204            }
205        }
206    }
207    ```
208
2092. USB主机端驱动开发工具包初始化。
210
211    ```cpp
212    int32_t UsbInitHostSdk(struct UsbSession **session);
213    ```
214
2153. 步骤2初始化完后获取UsbInterface对象。
216
217    ```cpp
218    const struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex);
219    ```
220
2214. 打开步骤3获取到的UsbInterface接口对象,获取相应接口的UsbInterfaceHandle对象。
222
223    ```cpp
224    UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);
225    ```
226
2275. 根据步骤4获取到的UsbInterfaceHandle对象,获取指定索引为pipeIndex的pipeInfo信息。
228
229    ```cpp
230    int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);
231    ```
232
2336. 为步骤4获取到的UsbInterfaceHandle预先分配待发送的IO Request对象。
234
235    ```cpp
236    struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int32_t isoPackets, int32_t length);
237    ```
238
2397. 根据输入参数params填充步骤6预先分配的IO Request。
240
241    ```cpp
242    int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params);
243    ```
244
2458. 提交IO Request对象,可以选择同步或异步两种模式。
246
247    ```cpp
248    int32_t UsbSubmitRequestSync(const struct UsbRequest *request); //发送同步IO请求
249    int32_t UsbSubmitRequestAsync(const struct UsbRequest *request); //发送异步IO请求
250    ```
251
252#### Host RAW API驱动开发
253
2541. 同Host DDK API的步骤1一样,在设备私有数据HCS中配置。
255
2562. 初始化Host RAW,并打开USB设备,然后获取描述符,通过描述符获取接口、端点信息。
257
258    ```cpp
259    int32_t UsbRawInit(struct UsbSession **session);
260    ```
261
2623. 待步骤2完成后打开USB设备。
263
264    ```cpp
265    UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);
266    ```
267
2684. 待步骤3完成后获取描述符,通过描述符获取接口、端点信息。
269
270    ```cpp
271    int32_t UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);
272    ```
273
2745. 分配Request,并根据传输类型使用相应接口对Request进行填充。
275
276    ```cpp
277    int32_t UsbRawFillBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于批量传输的请求
278    int32_t UsbRawFillControlSetup(const unsigned char *setup, const struct UsbControlRequestData *requestData);
279    int32_t UsbRawFillControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于控制传输的请求
280    int32_t UsbRawFillInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于中断传输的请求
281    int32_t UsbRawFillIsoRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于同步传输的请求
282    ```
283
2846. 提交IO Request对象,可以选择同步或异步两种模式。
285
286    ```cpp
287    int32_t UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData); //发送同步USB控制传输请求
288    int32_t UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData); //发送同步USB批量传输请求
289    int32_t UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData); //发送同步执行USB中断传输请求
290    int32_t UsbRawSubmitRequest(const struct UsbRawRequest *request); //提交异步IO请求
291    ```
292
293#### Device DDK API驱动开发
294
2951. 在设备功能代码中构造描述符。
296
297    ```cpp
298    static struct UsbFnFunction g_acmFunction = { // 功能描述符
299        .enable         = true,
300        .funcName       = "f_generic.a",
301        .strings        = g_acmStrings,
302        .fsDescriptors  = g_acmFsFunction,
303        .hsDescriptors  = g_acmHsFunction,
304        .ssDescriptors  = g_acmSsFunction,
305        .sspDescriptors = NULL,
306    };
307    struct UsbFnFunction *g_functions[] = {
308    #ifdef CDC_ECM
309        &g_ecmFunction,
310    #endif
311    #ifdef CDC_ACM
312        &g_acmFunction,
313    #endif
314    NULL
315    };
316    static struct UsbFnConfiguration g_masterConfig = { // 配置描述符
317        .configurationValue = 1,
318        .iConfiguration     = USB_FUNC_CONFIG_IDX,
319        .attributes         = USB_CFG_BUS_POWERED,
320        .maxPower           = POWER,
321        .functions          = g_functions,
322    };
323    static struct UsbFnConfiguration *g_configs[] = {
324        &g_masterConfig,
325        NULL,
326    };
327    static struct UsbDeviceDescriptor g_cdcMasterDeviceDesc = { // 设备描述符
328        .bLength            = sizeof(g_cdcMasterDeviceDesc),
329        .bDescriptorType    = USB_DDK_DT_DEVICE,
330        .bcdUSB             = CpuToLe16(BCD_USB),
331        .bDeviceClass       = 0,
332        .bDeviceSubClass    = 0,
333        .bDeviceProtocol    = 0,
334        .bMaxPacketSize0    = USB_MAX_PACKET_SIZE,
335        .idVendor           = CpuToLe16(DEVICE_VENDOR_ID),
336        .idProduct          = CpuToLe16(DEVICE_PRODUCT_ID),
337        .bcdDevice          = CpuToLe16(DEVICE_VERSION),
338        .iManufacturer      = USB_FUNC_MANUFACTURER_IDX,
339        .iProduct           = USB_FUNC_PRODUCT_IDX,
340        .iSerialNumber      = USB_FUNC_SERIAL_IDX,
341        .bNumConfigurations = 1,
342    };
343    static struct UsbFnDeviceDesc g_masterFuncDevice = { // 描述符入口
344        .deviceDesc    = &g_cdcMasterDeviceDesc,
345        .deviceStrings = g_devStrings,
346        .configs       = g_configs,
347    };
348    ```
349
3502. 创建设备。描述符构造完成后,使用UsbFnDeviceCreate函数创建一个USB设备,并传入UDC控制器和UsbFnDescriptorData结构体。
351
352    ```cpp
353    if (useHcs == 0) { // 使用代码编写的描述符
354        descData.type        = USBFN_DESC_DATA_TYPE_DESC;
355        descData.descriptor = &g_acmFuncDevice;
356    } else {             // 使用hcs编写的描述符
357        descData.type         = USBFN_DESC_DATA_TYPE_PROP;
358        descData.property    = acm->device->property;
359    }
360    // 创建设备
361    fnDev = (struct UsbFnDevice *) UsbFnCreateDevice(acm->udcName, &descData);
362    ```
363
3643. 设备创建后,使用UsbFnGetInterface函数获取UsbInterface接口对象,并通过UsbFnGetInterfacePipeInfo函数获取USB管道信息。
365
366    ```cpp
367    // 获取接口
368    fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
369    // 获取Pipe信息
370    UsbFnGetInterfacePipeInfo(fnIface, i, &pipeInfo);
371    // 获取Handle
372    handle = UsbFnOpenInterface(fnIface);
373    // 获取控制(EP0)Request
374    req = UsbFnAllocCtrlRequest(acm->ctrlIface.handle,
375                sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
376    // 获取Request
377    req = UsbFnAllocCtrlRequest(acm->ctrlIface.handle,
378                sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
379    ```
380
3814. 通过UsbFnStartRecvInterfaceEvent函数接收Event事件,并通过UsbFnEventCallback回调函数对Event事件做出响应。
382
383    ```cpp
384    // 开始接收Event事件
385    ret = UsbFnStartRecvInterfaceEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm);
386    // Event处理回调函数
387    static void UsbAcmEventCallback(struct UsbFnEvent *event)
388    {
389        struct UsbAcmDevice *acm = NULL;
390        if (event == NULL || event->context == NULL) {
391            HDF_LOGE("%s: event is null", __func__);
392            return;
393        }
394
395        acm = (struct UsbAcmDevice *)event->context;
396        switch (event->type) {
397            case USBFN_STATE_BIND:
398                HDF_LOGI("%s: receive bind event", __func__);
399                break;
400            case USBFN_STATE_UNBIND:
401                HDF_LOGI("%s: receive unbind event", __func__);
402                break;
403            case USBFN_STATE_ENABLE:
404                HDF_LOGI("%s: receive enable event", __func__);
405                AcmEnable(acm);
406                break;
407            case USBFN_STATE_DISABLE:
408                HDF_LOGI("%s: receive disable event", __func__);
409                AcmDisable(acm);
410                acm->enableEvtCnt = 0;
411                break;
412            case USBFN_STATE_SETUP:
413                HDF_LOGI("%s: receive setup event", __func__);
414                if (event->setup != NULL) {
415                    AcmSetup(acm, event->setup);
416                }
417                break;
418            case USBFN_STATE_SUSPEND:
419                HDF_LOGI("%s: receive suspend event", __func__);
420                AcmSuspend(acm);
421                break;
422            case USBFN_STATE_RESUME:
423                HDF_LOGI("%s: receive resume event", __func__);
424                AcmResume(acm);
425                break;
426            default:
427                break;
428        }
429    }
430    ```
431
4325. 收发数据,可以选择同步异步发送模式。
433
434    ```cpp
435    notify = (struct UsbCdcNotification *)req->buf;
436    ...
437    if (memcpy_s((void *)(notify + 1), length, data, length) != EOK) {
438        return HDF_FAILURE;
439    }
440    ret = UsbFnSubmitRequestAsync(req); // 异步发送
441    ```
442
443### 开发实例
444
445本实例提供USB串口驱动开发示例,并简要对具体关键点进行开发说明。
446
447#### Host DDK API驱动开发
448
449```cpp
450#include "usb_serial.h"
451#include "hdf_base.h"
452#include "hdf_log.h"
453#include "osal_mem.h"
454#include "osal_time.h"
455#include "securec.h"
456#include "usb_ddk_interface.h"
457#include "hdf_usb_pnp_manage.h"
458
459#define HDF_LOG_TAG USB_HOST_ACM
460#define STR_LEN     512
461
462static struct UsbRequest *g_syncRequest = NULL; // 定义一个USB请求
463static struct UsbRequest *g_ctrlCmdRequest = NULL;
464static bool g_acmReleaseFlag = false;
465static uint8_t *g_acmReadBuffer = NULL;
466...
467static int32_t SerialCtrlMsg(struct AcmDevice *acm, uint8_t request,
468    uint16_t value, void *buf, uint16_t len)
469{
470    int32_t ret;
471    uint16_t index = acm->intPipe->interfaceId;
472    struct UsbControlParams controlParams;
473    struct UsbRequestParams params; // 定义一个USB请求参数对象
474    if (acm == NULL || buf == NULL) {
475        return HDF_ERR_IO;
476    }
477    if (acm->ctrlReq == NULL) {
478        // 为获取到的UsbInterfaceHandle预先分配待发送的IO Request对象
479        acm->ctrlReq = UsbAllocRequest(acm->ctrDevHandle, 0, len);
480        if (acm->ctrlReq == NULL) {
481            return HDF_ERR_IO;
482        }
483    }
484
485    controlParams.request = request;
486    controlParams.target = USB_REQUEST_TARGET_INTERFACE; // 接口对象
487    controlParams.reqType = USB_REQUEST_TYPE_CLASS; // 请求类型
488    controlParams.direction = USB_REQUEST_DIR_TO_DEVICE; // 从主机到设备的数据传输
489    controlParams.value = value;
490    controlParams.index = index;
491    controlParams.data = buf;
492    controlParams.size = len;
493
494    params.interfaceId = USB_CTRL_INTERFACE_ID; // 定义USB控制接口的默认ID
495    params.pipeAddress = acm->ctrPipe->pipeAddress;
496    params.pipeId = acm->ctrPipe->pipeId;
497    params.requestType = USB_REQUEST_PARAMS_CTRL_TYPE; // 控制类型
498    params.timeout = USB_CTRL_SET_TIMEOUT; // 设置超时时间
499    params.ctrlReq = UsbControlSetUp(&controlParams);
500    // 根据params填充预先分配的IO Request
501    ret = UsbFillRequest(acm->ctrlReq, acm->ctrDevHandle, &params);
502    if (ret != HDF_SUCCESS) {
503        return ret;
504    }
505    // 发送同步IO Request
506    ret = UsbSubmitRequestSync(acm->ctrlReq);
507    if (ret != HDF_SUCCESS) {
508        return ret;
509    }
510    if (!acm->ctrlReq->compInfo.status) {
511        HDF_LOGE("%s status=%d ", __func__, acm->ctrlReq->compInfo.status);
512    }
513    return HDF_SUCCESS;
514}
515...
516static struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm,
517    uint8_t interfaceIndex)
518{
519    struct UsbInterface *tmpIf = NULL;
520    // 获取UsbInterface接口对象
521    tmpIf = (struct UsbInterface *)UsbClaimInterface(acm->session, acm->busNum, acm->devAddr, interfaceIndex);
522    return tmpIf;
523}
524...
525static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm,
526    uint8_t interfaceIndex, UsbPipeType pipeType, UsbPipeDirection pipeDirection)
527{
528    uint8_t i;
529    int32_t ret;
530    struct UsbInterfaceInfo *info = NULL; // 定义一个USB接口信息对象
531    UsbInterfaceHandle *interfaceHandle = NULL; // 定义一个USB接口操作句柄,就是void *类型
532    if (pipeType == USB_PIPE_TYPE_CONTROL)
533    {
534        info = &acm->ctrIface->info;
535        interfaceHandle = acm->ctrDevHandle;
536    }
537    else
538    {
539        info = &acm->iface[interfaceIndex]->info;
540        // 根据interfaceIndex获取设备句柄
541        interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex);
542    }
543
544    for (i = 0;  i <= info->pipeNum; i++) {
545        struct UsbPipeInfo p;
546        // 获取指定索引为i的pipeInfo信息
547        ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);
548        if (ret < 0) {
549            continue;
550        }
551        if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) {
552            struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi)); // 开辟内存并初始化
553            if (pi == NULL) {
554                return NULL;
555            }
556            p.interfaceId = info->interfaceIndex;
557            *pi = p;
558            return pi;
559        }
560    }
561    return NULL;
562}
563
564static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm,
565    UsbPipeType pipeType, UsbPipeDirection pipeDirection)
566{
567    uint8_t i;
568    if (acm == NULL) {
569        return NULL;
570    }
571    for (i = 0; i < acm->interfaceCnt; i++) {
572        struct UsbPipeInfo *p = NULL;
573        if (!acm->iface[i]) {
574            continue;
575        }
576        // 获取控制pipe的pipeInfo信息
577        p = EnumePipe(acm, i, pipeType, pipeDirection);
578        if (p == NULL) {
579            continue;
580        }
581        return p;
582    }
583    return NULL;
584}
585
586/* HdfDriverEntry implementations */
587static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device)
588{
589    struct UsbPnpNotifyServiceInfo *info = NULL;
590    errno_t err;
591    struct AcmDevice *acm = NULL;
592    if (device == NULL) {
593        return HDF_ERR_INVALID_OBJECT;
594    }
595    acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm));
596    if (acm == NULL) {
597        return HDF_FAILURE;
598    }
599    // 初始化互斥锁,&acm->lock表示指向互斥量的指针
600    if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) {
601        goto error;
602    }
603    info = (struct UsbPnpNotifyServiceInfo *)device->priv;
604    if (info != NULL) {
605        acm->busNum = info->busNum;
606        acm->devAddr = info->devNum;
607        acm->interfaceCnt = info->interfaceLength;
608        err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES,
609              (const void*)info->interfaceNumber, info->interfaceLength);
610        if (err != EOK) {
611            goto lock_error;
612        }
613    } else {
614        goto lock_error;
615    }
616    acm->device  = device;
617    device->service = &(acm->service);
618    acm->device->service->Dispatch = UsbSerialDeviceDispatch;
619    return HDF_SUCCESS;
620
621lock_error:
622    if (OsalMutexDestroy(&acm->lock)) {
623        HDF_LOGE("%s:%d OsalMutexDestroy failed", __func__, __LINE__);
624    }
625error:
626    OsalMemFree(acm);
627    acm = NULL;
628    return HDF_FAILURE;
629}
630...
631static int32_t AcmAllocReadRequests(struct AcmDevice *acm)
632{
633    int32_t ret;
634    struct UsbRequestParams readParams;
635    for (int32_t i = 0; i < ACM_NR; i++) {
636        // 分配待发送的readReq IO Request对象
637        acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize);
638        if (!acm->readReq[i]) {
639            goto error;
640        }
641        readParams.userData = (void *)acm;
642        readParams.pipeAddress = acm->dataInPipe->pipeAddress;
643        readParams.pipeId = acm->dataInPipe->pipeId;
644        readParams.interfaceId = acm->dataInPipe->interfaceId;
645        readParams.callback = AcmReadBulk;
646        readParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE; /* Data type */
647        readParams.timeout = USB_CTRL_SET_TIMEOUT;
648        readParams.dataReq.numIsoPackets = 0;
649        readParams.dataReq.direction = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1;
650        readParams.dataReq.length = acm->readSize;
651        // 根据readParams填充预先分配待发送的readReq IO Request对象
652        ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParams);
653        if (ret != HDF_SUCCESS) {
654            goto error;
655        }
656    }
657    return HDF_SUCCESS;
658
659error:
660    AcmFreeReadRequests(acm);
661    return HDF_ERR_MALLOC_FAIL;
662}
663
664static int32_t AcmAllocNotifyRequest(struct AcmDevice *acm)
665{
666    int32_t ret;
667    struct UsbRequestParams intParams = {};
668    // 分配待发送的中断IO Request对象
669    acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize);
670    if (!acm->notifyReq) {
671        return HDF_ERR_MALLOC_FAIL;
672    }
673    intParams.userData = (void *)acm;
674    intParams.pipeAddress = acm->intPipe->pipeAddress;
675    intParams.pipeId = acm->intPipe->pipeId;
676    intParams.interfaceId = acm->intPipe->interfaceId;
677    intParams.callback = AcmCtrlIrq;
678    intParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE;
679    intParams.timeout = USB_CTRL_SET_TIMEOUT;
680    intParams.dataReq.numIsoPackets = 0;
681    intParams.dataReq.direction = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK;
682    intParams.dataReq.length = acm->intSize;
683    // 填充预先分配的中断IO Request
684    ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParams);
685    if (ret != HDF_SUCCESS) {
686        goto error;
687    }
688    return HDF_SUCCESS;
689
690error:
691    AcmFreeNotifyRequest(acm);
692    return ret;
693}
694
695static void AcmReleaseInterfaces(struct AcmDevice *acm)
696{
697    for (int32_t i = 0; i < acm->interfaceCnt; i++) {
698        if (acm->iface[i]) {
699            // 释放一个USB接口对象
700            UsbReleaseInterface(acm->iface[i]);
701            acm->iface[i] = NULL;
702        }
703    }
704    if (acm->ctrIface) {
705        UsbReleaseInterface(acm->ctrIface);
706        acm->ctrIface = NULL;
707    }
708}
709
710static int32_t AcmClaimInterfaces(struct AcmDevice *acm)
711{
712    for (int32_t i = 0; i < acm->interfaceCnt; i++) {
713        // 获取UsbInterface接口对象
714        acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]);
715        if (acm->iface[i] == NULL) {
716            goto error;
717        }
718    }
719
720    // 获取控制接口对应的UsbInterface接口对象
721    acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID);
722    if (acm->ctrIface == NULL) {
723        goto error;
724    }
725
726    return HDF_SUCCESS;
727
728 error:
729    // 根据acm->interfaceCnt循环释放接口对象
730    AcmReleaseInterfaces(acm);
731    return HDF_FAILURE;
732}
733
734static void AcmCloseInterfaces(struct AcmDevice *acm)
735{
736    for (int32_t i = 0; i < acm->interfaceCnt; i++) {
737        if (acm->devHandle[i]) {
738            // 关闭一个USB设备对象
739            UsbCloseInterface(acm->devHandle[i]);
740            acm->devHandle[i] = NULL;
741        }
742    }
743    if (acm->ctrDevHandle) {
744        UsbCloseInterface(acm->ctrDevHandle);
745        acm->ctrDevHandle = NULL;
746    }
747}
748
749static int32_t AcmOpenInterfaces(struct AcmDevice *acm)
750{
751    for (int32_t i = 0; i < acm->interfaceCnt; i++) {
752        if (acm->iface[i]) {
753            // 打开获取到的UsbInterface接口对象
754            acm->devHandle[i] = UsbOpenInterface(acm->iface[i]);
755            if (acm->devHandle[i] == NULL) {
756                goto error;
757            }
758        }
759    }
760    acm->ctrDevHandle = UsbOpenInterface(acm->ctrIface);
761    if (acm->ctrDevHandle == NULL) {
762        goto error;
763    }
764
765    return HDF_SUCCESS;
766
767error:
768    // 关闭所有UsbInterface接口对象
769    AcmCloseInterfaces(acm);
770    return HDF_FAILURE;
771}
772
773static int32_t AcmGetPipes(struct AcmDevice *acm)
774{
775    // 获取dataInPipe的pipeInfo信息
776    acm->dataInPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN);
777    if (acm->dataInPipe == NULL) {
778        goto error;
779    }
780
781    // 获取dataOutPipe的pipeInfo信息
782    acm->dataOutPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT);
783    if (acm->dataOutPipe == NULL) {
784        goto error;
785    }
786
787    // 获取控制pipe的pipeInfo信息
788    acm->ctrPipe = EnumePipe(acm, acm->ctrIface->info.interfaceIndex, USB_PIPE_TYPE_CONTROL, USB_PIPE_DIRECTION_OUT);
789    if (acm->ctrPipe == NULL) {
790        goto error;
791    }
792
793    // 获取中断pipe的pipeInfo信息
794    acm->intPipe = GetPipe(acm, USB_PIPE_TYPE_INTERRUPT, USB_PIPE_DIRECTION_IN);
795    if (acm->intPipe == NULL) {
796        goto error;
797    }
798
799    acm->readSize  = acm->dataInPipe->maxPacketSize;
800    acm->writeSize = acm->dataOutPipe->maxPacketSize;
801    acm->ctrlSize  = acm->ctrPipe->maxPacketSize;
802    acm->intSize   = acm->intPipe->maxPacketSize;
803    return HDF_SUCCESS;
804
805error:
806    // 释放设备中所有的管道信息
807    AcmFreePipes(acm);
808    return HDF_FAILURE;
809}
810
811static void AcmFreeRequests(struct AcmDevice *acm)
812{
813    if (g_syncRequest != NULL) {
814        UsbFreeRequest(g_syncRequest);
815        g_syncRequest = NULL;
816    }
817    AcmFreeReadRequests(acm);
818    AcmFreeNotifyRequest(acm);
819    AcmFreeWriteRequests(acm);
820    AcmWriteBufFree(acm);
821}
822
823static int32_t AcmAllocRequests(struct AcmDevice *acm)
824{
825    int32_t ret;
826
827    if (AcmWriteBufAlloc(acm) < 0) {
828        return HDF_ERR_MALLOC_FAIL;
829    }
830
831    for (int32_t i = 0; i < ACM_NW; i++) {
832        struct AcmWb *snd = &(acm->wb[i]);
833        // 分配待发送的IO Request对象
834        snd->request = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataOutPipe->interfaceId), 0, acm->writeSize);
835        snd->instance = acm;
836        if (snd->request == NULL) {
837            goto error_alloc_write_req;
838        }
839    }
840
841    ret = AcmAllocNotifyRequest(acm); // 分配并填充中断IO Request对象
842    if (ret != HDF_SUCCESS) {
843        goto error_alloc_int_req;
844    }
845
846    ret = AcmAllocReadRequests(acm); // 分配并填充readReq IO Request对象
847    if (ret) {
848        goto error_alloc_read_req;
849    }
850
851    return HDF_SUCCESS;
852
853error_alloc_read_req:
854    AcmFreeNotifyRequest(acm);
855error_alloc_int_req:
856    AcmFreeWriteRequests(acm);
857error_alloc_write_req:
858    AcmWriteBufFree(acm);
859    return HDF_FAILURE;
860}
861
862static int32_t AcmInit(struct AcmDevice *acm)
863{
864    int32_t ret;
865    struct UsbSession *session = NULL;
866
867    if (acm->initFlag == true) {
868        return HDF_SUCCESS;
869    }
870
871    // 初始化Host DDK
872    ret = UsbInitHostSdk(NULL);
873    if (ret != HDF_SUCCESS) {
874        return HDF_ERR_IO;
875    }
876    acm->session = session;
877
878    // 根据acm->interfaceIndex[i]分别获取UsbInterface接口对象
879    ret = AcmClaimInterfaces(acm);
880    if (ret != HDF_SUCCESS) {
881        goto error_claim_interfaces;
882    }
883
884    // 根据acm->iface[i]分别打开UsbInterface接口对象
885    ret = AcmOpenInterfaces(acm);
886    if (ret != HDF_SUCCESS) {
887        goto error_open_interfaces;
888    }
889
890    // 获取管道信息的指针
891    ret = AcmGetPipes(acm);
892    if (ret != HDF_SUCCESS) {
893        goto error_get_pipes;
894    }
895
896    ret = AcmAllocRequests(acm);
897    if (ret != HDF_SUCCESS) {
898        goto error_alloc_reqs;
899    }
900
901    acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); // 转换为小端数据
902    acm->lineCoding.bCharFormat = CHARFORMAT; // 8
903    acm->lineCoding.bParityType = USB_CDC_NO_PARITY;
904    acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS;
905    acm->initFlag = true;
906    return HDF_SUCCESS;
907
908error_alloc_reqs:
909    AcmFreePipes(acm);
910error_get_pipes:
911    // 关闭所有UsbInterface接口对象
912    AcmCloseInterfaces(acm);
913error_open_interfaces:
914    // 释放所有UsbInterface接口对象
915    AcmReleaseInterfaces(acm);
916error_claim_interfaces:
917    // 在主机端退出USB DDK,acm->session代表指向会话上下文的指针
918    UsbExitHostSdk(acm->session);
919    acm->session = NULL;
920    return ret;
921}
922
923static void AcmRelease(struct AcmDevice *acm)
924{
925    if (acm->initFlag == false) {
926        return;
927    }
928
929    AcmFreeRequests(acm);
930    AcmFreePipes(acm);
931    AcmCloseInterfaces(acm);
932    AcmReleaseInterfaces(acm);
933    // 在主机端退出USB DDK
934    UsbExitHostSdk(acm->session);
935    acm->session = NULL;
936    acm->initFlag = false;
937}
938
939static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
940{
941    int32_t ret;
942    struct AcmDevice *acm = NULL;
943
944    if (device == NULL) {
945        return HDF_ERR_INVALID_OBJECT;
946    }
947    acm = (struct AcmDevice *)device->service;
948    // 初始化互斥锁,&acm->readLock表示指向互斥量的指针
949    OsalMutexInit(&acm->readLock);
950    OsalMutexInit(&acm->writeLock);
951    HDF_LOGD("%s:%d busNum=%d,devAddr=%d", __func__, __LINE__, acm->busNum, acm->devAddr);
952
953    // 给USB串口设备信息开辟空间并赋值
954    ret = UsbSerialDeviceAlloc(acm);
955    if (ret != HDF_SUCCESS) {
956        HDF_LOGE("%s: Serial Device alloc failed", __func__);
957    }
958
959    acm->initFlag = false;
960    g_acmReleaseFlag = false;
961    return ret;
962}
963
964static void UsbSerialDriverRelease(struct HdfDeviceObject *device)
965{
966    struct AcmDevice *acm = NULL;
967
968    if (device == NULL) {
969        return;
970    }
971    acm = (struct AcmDevice *)device->service;
972    if (acm == NULL) {
973        return;
974    }
975
976    g_acmReleaseFlag = true;
977
978    if (acm->initFlag == true) {
979        AcmRelease(acm);
980    }
981    // 释放usb串口设备信息
982    UsbSeriaDevicelFree(acm);
983    // 释放互斥锁
984    OsalMutexDestroy(&acm->writeLock);
985    OsalMutexDestroy(&acm->readLock);
986    OsalMutexDestroy(&acm->lock);
987    OsalMemFree(acm);
988    acm = NULL;
989}
990
991// 驱动的Bind、Init、及Release操作
992struct HdfDriverEntry g_usbSerialDriverEntry = {
993    .moduleVersion = 1,
994    .moduleName    = "usbhost_acm", // 驱动模块名称,必须与hcs文件中配置的名称一致
995    .Bind          = UsbSerialDriverBind,
996    .Init          = UsbSerialDriverInit,
997    .Release       = UsbSerialDriverRelease,
998};
999HDF_INIT(g_usbSerialDriverEntry); // 驱动入口
1000```
1001
1002#### Host RAW API驱动开发
1003
1004```cpp
1005root {
1006    module = "usb_pnp_device";
1007    usb_pnp_config {
1008        match_attr = "usb_pnp_match";
1009        usb_pnp_device_id = "UsbPnpDeviceId";
1010        UsbPnpDeviceId {
1011            idTableList = [
1012                "host_acm_rawapi_table"
1013            ];
1014            host_acm_rawapi_table {    // 驱动配置匹配表信息
1015                // 驱动模块名,该字段的值必须和驱动入口结构的moduleName一致
1016                moduleName = "usbhost_acm_rawapi";
1017                // 驱动对外发布服务的名称,必须唯一
1018                serviceName = "usbhost_acm_rawapi_service";
1019                // 驱动私有数据匹配关键字
1020                deviceMatchAttr = "usbhost_acm_rawapi_matchAttr";
1021                // 从该字段开始(包含该字段)之后数据长度,以byte为单位
1022                length = 21;
1023                // USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber
1024                matchFlag = 0x0303;
1025                // 厂商编号
1026                vendorId = 0x12D1;
1027                // 产品编号
1028                productId = 0x5000;
1029                // 设备出厂编号,低16位
1030                bcdDeviceLow = 0x0000;
1031                // 设备出厂编号,高16位
1032                bcdDeviceHigh = 0x0000;
1033                // USB分配的设备类代码
1034                deviceClass = 0;
1035                // USB分配的子类代码
1036                deviceSubClass = 0;
1037                // USB分配的设备协议代码
1038                deviceProtocol = 0;
1039                // 接口类型,根据实际需要可填写多个
1040                interfaceClass = [0];
1041                // 接口子类型,根据实际需要可填写多个
1042                interfaceSubClass = [2, 0];
1043                // 接口所遵循的协议,根据实际需要可填写多个
1044                interfaceProtocol = [1, 2];
1045                // 接口的编号,根据实际需要可填写多个
1046                interfaceNumber = [2, 3];
1047            }
1048        }
1049    }
1050}
1051```
1052
1053```cpp
1054#include "usb_serial_rawapi.h"
1055#include <unistd.h>
1056#include "osal_mem.h"
1057#include "osal_time.h"
1058#include "securec.h"
1059#include "hdf_base.h"
1060#include "hdf_log.h"
1061#include "hdf_usb_pnp_manage.h"
1062
1063#define HDF_LOG_TAG                     USB_HOST_ACM_RAW_API // 日志中可查寻的标签
1064#define USB_CTRL_REQ_SIZE               64
1065#define USB_IO_THREAD_STACK_SIZE        8192
1066#define USB_RAW_IO_SLEEP_MS_TIME        100
1067#define USB_RAW_IO_STOP_WAIT_MAX_TIME   3
1068
1069static struct UsbRawRequest *g_syncRequest = NULL;
1070static UsbRawIoProcessStatusType g_stopIoStatus = USB_RAW_IO_PROCESS_RUNNING;
1071struct OsalMutex g_stopIoLock;
1072static bool g_rawAcmReleaseFlag = false;
1073......
1074
1075static int32_t UsbGetConfigDescriptor(UsbRawHandle *devHandle, struct UsbRawConfigDescriptor **config)
1076{
1077    UsbRawDevice *dev = NULL;
1078    int32_t activeConfig;
1079    int32_t ret;
1080
1081    if (devHandle == NULL) {
1082        return HDF_ERR_INVALID_PARAM;
1083    }
1084
1085    // 获取主用设备配置
1086    ret = UsbRawGetConfiguration(devHandle, &activeConfig);
1087    if (ret != HDF_SUCCESS) {
1088        return HDF_FAILURE;
1089    }
1090
1091    // 根据指定的设备句柄获取设备指针
1092    dev = UsbRawGetDevice(devHandle);
1093    if (dev == NULL) {
1094        return HDF_FAILURE;
1095    }
1096
1097    // 根据指定的设备ID获取设备配置描述符
1098    ret = UsbRawGetConfigDescriptor(dev, activeConfig, config);
1099    if (ret != HDF_SUCCESS) {
1100        HDF_LOGE("UsbRawGetConfigDescriptor failed, ret=%d\n", ret);
1101    }
1102    return ret;
1103}
1104...
1105static int32_t UsbAllocWriteRequests(struct AcmDevice *acm)
1106{
1107    int32_t i;
1108
1109    for (i = 0; i < ACM_NW; i++) {
1110        struct AcmWb *snd = &acm->wb[i];
1111        // 分配一个具有指定数目的同步传输分组描述符的传输请求
1112        snd->request = UsbRawAllocRequest(acm->devHandle, 0, acm->dataOutEp->maxPacketSize);
1113        snd->instance = acm;
1114        if (snd->request == NULL) {
1115            return HDF_ERR_MALLOC_FAIL;
1116        }
1117    }
1118
1119    return HDF_SUCCESS;
1120}
1121...
1122/* HdfDriverEntry implementations */
1123static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device)
1124{
1125    struct AcmDevice *acm = NULL;
1126    struct UsbPnpNotifyServiceInfo *info = NULL;
1127    errno_t err;
1128
1129    if (device == NULL) {
1130        return HDF_ERR_INVALID_OBJECT;
1131    }
1132
1133    acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm));
1134    if (acm == NULL) {
1135        return HDF_FAILURE;
1136    }
1137    if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) {
1138        goto error;
1139    }
1140
1141    info = (struct UsbPnpNotifyServiceInfo *)device->priv;
1142    if (info != NULL) {
1143        acm->busNum       = info->busNum;
1144        acm->devAddr      = info->devNum;
1145        acm->interfaceCnt = info->interfaceLength;
1146        err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES,
1147                       (const void*)info->interfaceNumber, info->interfaceLength);
1148        if (err != EOK) {
1149            goto lock_error;
1150        }
1151    } else {
1152        goto lock_error;
1153    }
1154
1155    device->service = &(acm->service);
1156    device->service->Dispatch = UsbSerialDeviceDispatch;
1157    acm->device = device;
1158    return HDF_SUCCESS;
1159
1160lock_error:
1161    if (OsalMutexDestroy(&acm->lock)) {
1162        HDF_LOGE("%s:%d OsalMutexDestroy failed", __func__, __LINE__);
1163    }
1164error:
1165    OsalMemFree(acm);
1166    acm = NULL;
1167    return HDF_FAILURE;
1168}
1169...
1170static int32_t UsbAllocReadRequests(struct AcmDevice *acm)
1171{
1172    struct UsbRawFillRequestData reqData;
1173    int32_t size = acm->dataInEp->maxPacketSize;
1174    int32_t ret;
1175
1176    for (int32_t i = 0; i < ACM_NR; i++) {
1177        // 分配一个具有指定数目的同步传输分组描述符的传输请求
1178        acm->readReq[i] = UsbRawAllocRequest(acm->devHandle, 0, size);
1179        if (!acm->readReq[i]) {
1180            return HDF_ERR_MALLOC_FAIL;
1181        }
1182
1183        reqData.endPoint      = acm->dataInEp->addr;
1184        reqData.numIsoPackets = 0;
1185        reqData.callback      = AcmReadBulkCallback;
1186        reqData.userData      = (void *)acm;
1187        reqData.timeout       = USB_CTRL_SET_TIMEOUT;
1188        reqData.length        = size;
1189
1190        // 在批量传输请求中填写所需信息
1191        ret = UsbRawFillBulkRequest(acm->readReq[i], acm->devHandle, &reqData);
1192        if (ret != HDF_SUCCESS) {
1193            return HDF_FAILURE;
1194        }
1195    }
1196
1197    return HDF_SUCCESS;
1198}
1199...
1200static int32_t UsbAllocNotifyRequest(struct AcmDevice *acm)
1201{
1202    struct UsbRawFillRequestData fillRequestData;
1203    int32_t size = acm->notifyEp->maxPacketSize;
1204    int32_t ret;
1205
1206    // 分配一个具有指定数目的同步传输分组描述符的传输请求
1207    acm->notifyReq = UsbRawAllocRequest(acm->devHandle, 0, size);
1208    if (!acm->notifyReq) {
1209        return HDF_ERR_MALLOC_FAIL;
1210    }
1211
1212    fillRequestData.endPoint = acm->notifyEp->addr;
1213    fillRequestData.length = size;
1214    fillRequestData.numIsoPackets = 0;
1215    fillRequestData.callback = AcmNotifyReqCallback;
1216    fillRequestData.userData = (void *)acm;
1217    fillRequestData.timeout = USB_CTRL_SET_TIMEOUT;
1218
1219    // 在中断传输请求中填充所需的信息
1220    ret = UsbRawFillInterruptRequest(acm->notifyReq, acm->devHandle, &fillRequestData);
1221    if (ret != HDF_SUCCESS) {
1222        return HDF_FAILURE;
1223    }
1224
1225    return HDF_SUCCESS;
1226}
1227...
1228static int32_t UsbSerialInit(struct AcmDevice *acm)
1229{
1230    struct UsbSession *session = NULL;
1231    UsbRawHandle *devHandle = NULL;
1232    int32_t ret;
1233
1234    if (acm->initFlag == true) {
1235        return HDF_SUCCESS;
1236    }
1237
1238    // 以专家模式初始化USB DDK
1239    ret = UsbRawInit(NULL);
1240    if (ret != HDF_SUCCESS) {
1241        return HDF_ERR_IO;
1242    }
1243    acm->session = session;
1244
1245    // 打开一个USB设备对象
1246    devHandle = UsbRawOpenDevice(session, acm->busNum, acm->devAddr);
1247    if (devHandle == NULL) {
1248        ret =  HDF_FAILURE;
1249        goto err_open_device;
1250    }
1251    acm->devHandle = devHandle;
1252    // 获取主用设备配置、设备指针及配置描述符
1253    ret = UsbGetConfigDescriptor(devHandle, &acm->config);
1254    if (ret != HDF_SUCCESS) {
1255        ret =  HDF_FAILURE;
1256        goto err_get_desc;
1257    }
1258    ret = UsbParseConfigDescriptor(acm, acm->config);
1259    if (ret != HDF_SUCCESS) {
1260        ret = HDF_FAILURE;
1261        goto err_parse_desc;
1262    }
1263
1264    ret = AcmWriteBufAlloc(acm);
1265    if (ret < 0) {
1266        ret = HDF_FAILURE;
1267        goto err_alloc_write_buf;
1268    }
1269    ret = UsbAllocWriteRequests(acm);
1270    if (ret < 0) {
1271        ret = HDF_FAILURE;
1272        goto err_alloc_write_reqs;
1273    }
1274    ret = UsbAllocNotifyRequest(acm);
1275    if (ret) {
1276        goto err_alloc_notify_req;
1277    }
1278    ret = UsbAllocReadRequests(acm);
1279    if (ret) {
1280        goto err_alloc_read_reqs;
1281    }
1282    ret = UsbStartIo(acm);
1283    if (ret) {
1284        goto err_start_io;
1285    }
1286
1287    acm->lineCoding.dwDTERate   = CpuToLe32(DATARATE);
1288    acm->lineCoding.bCharFormat = CHARFORMAT;
1289    acm->lineCoding.bParityType = USB_CDC_NO_PARITY;
1290    acm->lineCoding.bDataBits   = USB_CDC_1_STOP_BITS;
1291
1292    ret = UsbRawSubmitRequest(acm->notifyReq);
1293    if (ret) {
1294        goto err_submit_req;
1295    }
1296
1297    acm->initFlag = true;
1298    return HDF_SUCCESS;
1299
1300err_submit_req:
1301    UsbStopIo(acm); // 停止IO线程并释放所有资源
1302err_start_io:
1303    UsbFreeReadRequests(acm);
1304err_alloc_read_reqs:
1305    UsbFreeNotifyRequest(acm);
1306 err_alloc_notify_req:
1307    UsbFreeWriteRequests(acm);
1308err_alloc_write_reqs:
1309    AcmWriteBufFree(acm);
1310err_alloc_write_buf:
1311    UsbReleaseInterfaces(acm);
1312err_parse_desc:
1313    UsbRawFreeConfigDescriptor(acm->config);
1314    acm->config = NULL;
1315err_get_desc:
1316    (void)UsbRawCloseDevice(devHandle); // 关闭USB设备对象
1317err_open_device:
1318    UsbRawExit(acm->session); // 退出USB DDK的专家模式
1319
1320    return ret;
1321}
1322
1323static void UsbSerialRelease(struct AcmDevice *acm)
1324{
1325    if (acm->initFlag == false) {
1326        return;
1327    }
1328
1329    /* stop io thread and release all resources */
1330    UsbStopIo(acm);
1331    if (g_syncRequest != NULL) {
1332        UsbRawFreeRequest(g_syncRequest);
1333        g_syncRequest = NULL;
1334    }
1335    UsbFreeReadRequests(acm);
1336    UsbFreeNotifyRequest(acm);
1337    UsbFreeWriteRequests(acm);
1338    AcmWriteBufFree(acm);
1339    (void)UsbRawCloseDevice(acm->devHandle);
1340    UsbReleaseInterfaces(acm);
1341    UsbRawFreeConfigDescriptor(acm->config);
1342    acm->config = NULL;
1343    // 退出USB DDK的专家模式
1344    UsbRawExit(acm->session);
1345
1346    acm->initFlag = false;
1347}
1348
1349static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
1350{
1351    struct AcmDevice *acm = NULL;
1352    int32_t ret;
1353
1354    if (device == NULL) {
1355        return HDF_ERR_INVALID_OBJECT;
1356    }
1357    acm = (struct AcmDevice *)device->service;
1358    OsalMutexInit(&acm->readLock);
1359    OsalMutexInit(&acm->writeLock);
1360
1361    ret = UsbSerialDeviceAlloc(acm);
1362    if (ret != HDF_SUCCESS) {
1363        HDF_LOGE("%s:%d UsbSerialDeviceAlloc failed", __func__, __LINE__);
1364    }
1365
1366    acm->initFlag = false;
1367    g_rawAcmReleaseFlag = false;
1368    return ret;
1369}
1370
1371static void UsbSerialDriverRelease(struct HdfDeviceObject *device)
1372{
1373    struct AcmDevice *acm = NULL;
1374    if (device == NULL) {
1375        return;
1376    }
1377
1378    acm = (struct AcmDevice *)device->service;
1379    if (acm == NULL) {
1380        return;
1381    }
1382
1383    g_rawAcmReleaseFlag = true;
1384
1385    if (acm->initFlag == true) {
1386        UsbSerialRelease(acm);
1387    }
1388    UsbSeriaDevicelFree(acm);
1389    OsalMutexDestroy(&acm->writeLock);
1390    OsalMutexDestroy(&acm->readLock);
1391    OsalMutexDestroy(&acm->lock);
1392    OsalMemFree(acm);
1393    acm = NULL;
1394}
1395
1396struct HdfDriverEntry g_usbSerialRawDriverEntry = {
1397    .moduleVersion = 1,
1398    .moduleName    = "usbhost_acm_rawapi", // 驱动模块名称,必须与hcs文件中配置的名称一致
1399    .Bind          = UsbSerialDriverBind,
1400    .Init          = UsbSerialDriverInit,
1401    .Release       = UsbSerialDriverRelease,
1402};
1403HDF_INIT(g_usbSerialRawDriverEntry);
1404```
1405
1406#### Device DDK API驱动开发
1407
1408USB ACM设备核心代码路径为drivers\peripheral\usb\gadget\function\acm\cdcacm.c。其使用示例如下所示,首先根据描述符创建设备,然后获取接口,打开接口,获取Pipe信息,接收Event事件,接着进行USB通信(读写等),设备卸载时候,关闭接口,停止Event接收,删除设备。
1409
14101. 创建设备。
1411
1412    ```cpp
1413    static int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm, struct DeviceResourceIface *iface)
1414    {
1415        struct UsbFnDevice *fnDev = NULL;
1416        struct UsbFnDescriptorData descData;
1417        uint8_t useHcs;
1418        ...
1419        if (useHcs == 0) { // 描述符来自于代码中编码
1420            descData.type = USBFN_DESC_DATA_TYPE_DESC;
1421            descData.descriptor = &g_masterFuncDevice;
1422        } else { // 描述符来自于解析hcs文件
1423            descData.type = USBFN_DESC_DATA_TYPE_PROP;
1424            descData.property = device->property;
1425        }
1426        /* 创建设备 */
1427        fnDev = (struct UsbFnDevice *)UsbFnDeviceCreate(acm->udcName, &descData);
1428        if (fnDev == NULL) {
1429            return HDF_FAILURE;
1430        }
1431        ...
1432    }
1433    ```
1434
14352. 获取接口,打开接口,获取Pipe信息
1436
1437    ```cpp
1438    static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface)
1439    {
1440        ...
1441        for (i = 0; i < fnIface->info.numPipes; i++) {
1442            struct UsbFnPipeInfo pipeInfo;
1443            /* 获取pipe信息 */
1444            ret = UsbFnInterfaceGetPipeInfo(fnIface, i, &pipeInfo);
1445            ...
1446        }
1447        return HDF_SUCCESS;
1448    }
1449    /* 获取接口,打开接口获取handle */
1450    static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev)
1451    {
1452        ...
1453        for (i = 0; i < fnDev->numInterfaces; i++) {
1454            /* 获取接口 */
1455            fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
1456            ...
1457            /* 打开接口 */
1458            handle = UsbFnInterfaceOpen(fnIface);
1459            ...
1460        }
1461        return HDF_SUCCESS;
1462    }
1463    ```
1464
14653. 接收Event事件(EP0控制传输)
1466
1467    ```cpp
1468    static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int32_t num)
1469    {
1470        ...
1471        req = UsbFnCtrlRequestAlloc(acm->ctrlIface.handle,
1472            sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
1473        ...
1474    }
1475    static int32_t AcmDriverInit(struct HdfDeviceObject *device)
1476    {
1477        ...
1478        /* 开始接收Event */
1479        ret = UsbFnInterfaceStartRecvEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm);
1480        ...
1481    }
1482    ```
1483
14844. 进行USB通信(读写等)
1485
1486    ```cpp
1487    static int32_t AcmSendNotifyRequest(struct UsbAcmDevice *acm, uint8_t type,
1488        uint16_t value, void *data, uint32_t length)
1489    {
1490        ...
1491        /* 异步发送 */
1492        ret = UsbFnRequestSubmitAsync(req);
1493        ...
1494    }
1495    ```
1496
14975. 关闭接口,停止Event接收,删除设备
1498
1499    ```cpp
1500    static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm)
1501    {
1502        int32_t ret;
1503        /* 关闭接口 */
1504        (void)UsbFnInterfaceClose(acm->ctrlIface.handle);
1505        (void)UsbFnInterfaceClose(acm->dataIface.handle);
1506        /* 停止接收Event EP0控制传输 */
1507        (void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn);
1508        /* 删除设备 */
1509        ret = UsbFnDeviceRemove(acm->fnDev);
1510        if (ret != HDF_SUCCESS) {
1511            HDF_LOGE("%s: remove usb function device failed", __func__);
1512        }
1513        return ret;
1514    }
1515    ```
1516
1517## 参考
1518
1519- 代码仓库如下:
1520
1521  **[drivers\_hdf\_core](https://gitee.com/openharmony/drivers_hdf_core)**
1522
1523  [drivers\_peripheral](https://gitee.com/openharmony/drivers_peripheral)
1524
1525  [drivers\_interface](https://gitee.com/openharmony/drivers_interface)
1526
1527- 代码路径如下:
1528
1529  USB驱动模型liteos适配://drivers/hdf_core/adapter/khdf/liteos/model/usb
1530
1531  USB DDK驱动加载实现://drivers/hdf_core/framework/model/usb
1532
1533  USB HDI服务端实现://drivers/peripheral/usb/hdi_service
1534
1535  USB HDI对外接口://out/{product_name}/gen/drivers/interface/usb/v1_0
1536
1537