未验证 提交 60e83038 编写于 作者: O openharmony_ci 提交者: Gitee

!11017 Improve USB development documentation

Merge pull request !11017 from 王易朋/master
# USB
## 概述
## 概述
### 功能简介
USB Host部分,主要包括协议封装、设备管理、驱动安装与卸载等
USB(Universal Serial Bus)通用串行总线,包含了主机端(Host)和设备端(Device)。主机端负责USB总线中的数据传输及端口管理,设备端则可以连接各种外设,所以USB驱动开发又分为主机端驱动开发和设备端驱动开发
USB Device部分,支持USB功能设备的开发,提供USB设备相关功能,主要包括设备管理、配置管理、IO管理,实现USB功能设备创建、配置、数据通信等。
OpenHarmony系统USB模块支持USB业务的开发,提供USB相关的功能,提供用户态第三方功能驱动的USB设备数据读写接口,以及提供创建和删除USB设备,接口的事件获取、打开和关闭等,管道同步异步读写通信,设置USB自定义属性等。
USB Host和Device驱动模型如下图所示:
USB DDK(USB DriverDevelop Kit)是HDF驱动框架为开发者提供的USB驱动程序开发套件,包括USB Host DDK及USB Device DDK两部分,支持基于用户态开发USB设备驱动的同时,还提供了丰富的USB驱动开发能力,让广大开发者能精准且高效的开发USB驱动程序。
### 基本概念
- 管道
管道(Pipe)是主机端和设备端点之间数据传输的模型。任何USB设备一旦上电就存在一个信息管道,即默认的控制管道,USB主机通过该管道来获取设备的描述、配置、状态,并对设备进行配置;管道和端点关联,两者有相同的属性,如支持的传输类型、最大包长度、传输方向等。
- 端点
端点(Endpoint)是USB设备中的可以进行数据收发的最小单元,支持单向或者双向的数据传输。一个USB设备可以包括若干个端点,不同的端点以端点编号和方向区分。不同端点可以支持不同的传输类型、访问间隔以及最大数据包大小。除端点0外,所有的端点只支持一个方向的数据传输。端点0是一个特殊的端点,它支持双向的控制传输。
- 接口
应用软件通过和设备之间的数据交换来完成设备的控制和数据传输。由于同一管道只支持一种类型的数据传输,因此这个过程中通常需要多个管道来完成数据交换。像这样用在一起来对设备进行控制的若干管道的集合称为接口。
- 描述符
描述符(Descriptor)是用于描述设备属性(Attributes)的数据结构,第一个字节表示描述符的大小(字节数),第二个字节表示描述符的类型(Type)。
### 运作机制
#### USB Host DDK
USB Host DDK为开发者提供了主机端USB驱动开发能力,按照功能分为三大类,分别是DDK初始化类、interface对象操作类及request对象操作类。
**图1** USB Host驱动模型图
![image](figures/USB-Host驱动模型图.png "USB-Host驱动模型图")
- USB Interface Pool负责USB Interface管理。提供USB Interface接口对象的申请和回收,USB Interface接口对象用来记录设备端口信息以及资源。USB Interface Pool按照USB Port对USB Interface进行分类管理。同时,此模块还提供了USB DDK API,方便开发者进行USB数据读写操作。
- USB Protocol Layer提供USB协议封装,根据USB协议对设备IO/控制命令进行翻译和解析”,同时负责设备描述符的管理,根据USB Device上报的枚举信息,匹配对应的描述符;构建对应的USB Interface接口对象,并将其加入到USB Interface Pool中管理。
- Device IO Manager负责USB IO请求管理,提供了同步IO和异步IO管理机制,对于异步IO,IO Manager负责将该请求记录下来,然后通过Raw API Library提供的接口依次处理待发送的IO请求;当收到USB控制器应答的处理结果后,IO接收线程负责解析并上报处理结果给上层调用者。
- Raw API Library抽象了底层OS能力,定义了统一的OS能力接口,对外提供了USB RAW API,方便开发者实现更加复杂的驱动功能。
- OS Adapter用于封装与平台(Linux和LiteOS)相关的操作,根据不同平台配置编译对应平台的封装接口。在Linux平台上,访问USB FS的操作,全部都封装在这个模块中;而在LiteOS平台上,基于FreeBSD USB框架的设备访问操作,也都全部封装在这个模块中。
- PNP Notify用于动态监测USB状态变化,当有新设备添加/移除时,变化设备信息。同时将所有USB设备信息都通过KHDF上报给UHDF侧的PNP Notify Manager模块来完成加载/卸载第三方功能驱动。
#### USB Device DDK
USB Device DDK向开发者提供了设备端USB驱动开发能力。例如,USB端口动态注册和去注册能力,开发者可以基于能力实现USB端口的动态添加和组合;动态实例化能力,支持根据动态下发设备、配置、接口及端点描述符创建设备实例及传输通道;用户态的数据发送及接收能力,支持用户态下发送及接收数据;复合设备能力,支持一个物理设备上多个逻辑设备,实现多个逻辑设备间隔离,并支持不同逻辑设备同时被不同的应用进程访问。
**图2** USB Device驱动模型图
![image](figures/USB-Device驱动模型图.png "USB-Device驱动模型图")
USB驱动模型对外开放的API接口能力如下:
- SDK IF负责将USB设备按照设备、接口、管道进行逻辑划分,对配置管理、设备管理、IO管理进行封装。此模块还向开发者提供了设备创建、获取接口、接收Event事件、收发数据等设备测驱动开发的能力接口。
- Configuration Manager负责解析HCS文件描述的USB描述符信息,得到的USB描述符信息用于设备创建,同时模块还提供了自定义属性的读取、创建、删除、修改等操作。
- Device Manager负责根据配置模块解析USB描述符,并根据USB描述符创建设备。同时还负责获取设备、删除设备、获取设备状态,获取设备上面接口信息。
- IO Manager负责数据的读写,包括Events事件、数据读写完成后事件的接收,支持同步和异步模式数据读写。
- Adapter IF主要是对复合设备配置驱动及通用功能驱动设备节点操作进行封装,为上层提供统一的设备管理接口。
- Adapter该模块由复合设备配置驱动及通用功能驱动提供。
## 开发指导
- USB Host DDK提供给用户态可直接调用的驱动能力接口,按照功能分类三大类:DDK初始化类、对interface对象操作类、对request对象操作类,可以提供DDK初始化、interface绑定和释放,打开和关闭操作,request的申请和释放,同步和异步传输等
由于内核态开发USB驱动较复杂,需要开发者对USB协议要有较深的了解才能很好的使用,对开发者的要求相对较高。USB DDK的引入是为了让开发者能在用户态更方便的开发USB驱动
- USB Device DDK提供设备管理、IO管理、配置管理,主要功能有:创建和删除设备、获取和打开接口、同步和异步传输等。
### 场景介绍
USB Host DDK为开发者提供了普通模式和专家模式,普通模式下,开发者可通过USB DDK API直接完成相关USB数据读写操作,不需要过多关注底层的传输细节。专家模式下,开发者通过USB RAW API直接访问OS平台中USB通道的接口,自定义实现更加复杂的功能。USB Device DDk为开发者提供了管理USB设备、接口定义及USB数据请求等功能。下文将介绍相关API。
### 接口说明
USB驱动模型Host侧开放的API接口功能,参考USB Host驱动模型图
USB主机端驱动程序开发相关接口(普通模式)如下,具体接口定义[见源码](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/host/usb_ddk_interface.h)
**表1** usb_ddk_interface.h
**表1** USB主机端驱动程序开发相关接口(普通模式)
| 接口名称 | 功能描述 |
| -------- | -------- |
| int32_t UsbInitHostSdk(struct UsbSession \*\*session); | USB主机端驱动开发工具包初始化 |
| int32_t&nbsp;UsbExitHostSdk(const&nbsp;struct&nbsp;UsbSession<br/>\*session); | USB主机端驱动开发工具包退出 |
| 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接口对象 |
| int32_t&nbsp;UsbReleaseInterface(const&nbsp;struct&nbsp;UsbInterface<br/>\*interfaceObj); | 释放USB接口对象 |
| int32_t&nbsp;UsbAddOrRemoveInterface(const&nbsp;struct&nbsp;UsbSession<br/>\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t&nbsp;usbAddr,&nbsp;uint8_t<br/>interfaceIndex,&nbsp;UsbInterfaceStatus&nbsp;status); | 增加移除接口 |
| UsbInterfaceHandle&nbsp;\*UsbOpenInterface(const&nbsp;struct<br/>UsbInterface&nbsp;\*interfaceObj); | 打开USB对象接口 |
| int32_t&nbsp;UsbCloseInterface(const&nbsp;UsbInterfaceHandle<br/>\*interfaceHandle); | 关闭USB接口对象 |
| int32_t&nbsp;UsbSelectInterfaceSetting(const<br/>UsbInterfaceHandle&nbsp;\*interfaceHandle,&nbsp;uint8_t<br/>settingIndex,&nbsp;struct&nbsp;UsbInterface&nbsp;\*\*interfaceObj); | 设置可选配置 |
| 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); | 获取指定可选设置的管道信息 |
| int32_t&nbsp;UsbClearInterfaceHalt(const<br/>UsbInterfaceHandle&nbsp;\*interfaceHandle,&nbsp;uint8_t<br/>pipeAddress); | 清除指定索引的管道状态 |
| struct&nbsp;UsbRequest&nbsp;\*UsbAllocRequest(const<br/>UsbInterfaceHandle&nbsp;\*interfaceHandle,&nbsp;int32_t&nbsp;isoPackets<br/>,&nbsp;int32_t&nbsp;length); | 分配请求对象 |
| int32_t&nbsp;UsbFreeRequest(const&nbsp;struct&nbsp;UsbRequest<br/>\*request); | 释放请求对象 |
| int32_t&nbsp;UsbSubmitRequestAsync(const&nbsp;struct&nbsp;UsbRequest<br/>\*request); | 发送异步请求 |
| 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); | 填充请求 |
| int32_t&nbsp;UsbCancelRequest(const&nbsp;struct&nbsp;UsbRequest<br/>\*request); | 取消异步请求 |
| int32_t&nbsp;UsbSubmitRequestSync(const&nbsp;struct&nbsp;UsbRequest<br/>\*request); | 发送同步请求 |
**表2** usb_raw_api.h
USB主机端驱动程序开发相关接口(专家模式)如下,具体接口定义[见源码](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/host/usb_raw_api.h)
**表2** USB主机端驱动程序开发相关接口(专家模式)
| 接口名称 | 功能描述 |
| -------- | -------- |
| int32_t&nbsp;UsbRawInit(struct&nbsp;UsbSession&nbsp;\*\*session); | USB驱动开发工具包专家模式初始化 |
| int32_t&nbsp;UsbRawExit(const&nbsp;struct&nbsp;UsbSession&nbsp;\*session); | USB驱动开发工具包专家模式退出 |
| UsbRawHandle&nbsp;\*UsbRawOpenDevice(const&nbsp;struct<br/>UsbSession&nbsp;\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t<br/>usbAddr); | 打开USB设备对象 |
| int32_t&nbsp;UsbRawCloseDevice(const&nbsp;UsbRawHandle<br/>\*devHandle); | 关闭USB设备对象 |
| 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); | 执行同步控制传输 |
| 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); | 执行同步批量传输 |
| 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); | 执行同步中断传输 |
| int32_t&nbsp;UsbRawGetConfigDescriptor(const&nbsp;UsbRawDevice<br/>\*rawDev,&nbsp;uint8_t&nbsp;configIndex,&nbsp;struct<br/>UsbRawConfigDescriptor&nbsp;\*\*config); | 获取给定设备指定ID的设备配置描述符 |
| void&nbsp;UsbRawFreeConfigDescriptor(const&nbsp;struct<br/>UsbRawConfigDescriptor&nbsp;\*config); | 释放配置描述符内存空间 |
| int32_t&nbsp;UsbRawGetConfiguration(const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;int32_t&nbsp;\*config); | 获取当前激活配置 |
| int32_t&nbsp;UsbRawSetConfiguration(const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;int32_t&nbsp;config); | 设置当前激活配置 |
| int32_t&nbsp;UsbRawGetDescriptor(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br/>UsbRawDescriptorParam&nbsp;\*param,&nbsp;const&nbsp;unsigned&nbsp;char<br/>\*data); | 获取描述符信息 |
| UsbRawDevice&nbsp;\*UsbRawGetDevice(const&nbsp;UsbRawHandle<br/>\*devHandle); | 由设备句柄获取设备指针 |
| int32_t&nbsp;UsbRawGetDeviceDescriptor(const&nbsp;UsbRawDevice<br/>\*rawDev,&nbsp;struct<br/>UsbDeviceDescriptor&nbsp;\*desc); | 获取给定设备的USB设备描述符 |
| int32_t&nbsp;UsbRawClaimInterface(const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;int32_t<br/>interfaceNumber); | 声明给定设备句柄上的接口 |
| int32_t&nbsp;UsbRawReleaseInterface(const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;in<br/>t&nbsp;interfaceNumber); | 释放之前声明的接口 |
| int32_t&nbsp;UsbRawResetDevice(const&nbsp;UsbRawHandle<br/>\*devHandle); | 复位设备 |
| struct&nbsp;UsbRawRequest&nbsp;\*UsbRawAllocRequest(const<br/>UsbRawHandle<br/>\*devHandle,&nbsp;int32_t&nbsp;isoPackets,&nbsp;int32_t&nbsp;length); | 分配一个带有指定数量的同步包描述符的传输请求 |
| int32_t&nbsp;UsbRawFreeRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request); | 释放之前分配的传输请求 |
| int32_t&nbsp;UsbRawFillBulkRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br/>UsbRawFillRequestData&nbsp;\*fillData); | 填充批量传输请求所需信息 |
| int32_t&nbsp;UsbRawFillControlSetup(const&nbsp;unsigned&nbsp;char&nbsp;\*setup,<br/>const&nbsp;struct&nbsp;UsbControlRequestData&nbsp;\*requestData); | 填充控制传输设置包所需信息 |
| int32_t&nbsp;UsbRawFillControlRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br/>UsbRawFillRequestData&nbsp;\*fillData); | 填充控制传输请求所需信息 |
| 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); | 填充中断传输请求所需信息 |
| 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)请求所需信息 |
| int32_t&nbsp;UsbRawSubmitRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request); | 提交一个传输请求 |
| int32_t&nbsp;UsbRawCancelRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request); | 取消一个传输请求 |
| int32_t&nbsp;UsbRawHandleRequests(const&nbsp;UsbRawHandle<br/>\*devHandle); | 传输请求事件完成处理 |
USB驱动模型Device侧开放的API接口功能,参考USB Device驱动模型图
USB设备端用于管理USB设备的相关接口如下,具体接口定义[见源码](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/device/usbfn_device.h)
**表3** usbfn_device.h
**表3** USB设备端用于管理USB设备的相关接口
| 接口名称 | 功能描述 |
| -------- | -------- |
......@@ -92,7 +122,9 @@ USB驱动模型Device侧开放的API接口功能,参考USB Device驱动模型
| int32_t&nbsp;UsbFnRemoveDevice(struct&nbsp;UsbFnDevice<br/>\*fnDevice); | 删除USB设备 |
| const&nbsp;struct&nbsp;UsbFnDevice&nbsp;\*UsbFnGetDevice(const&nbsp;char<br/>\*udcName); | 获取USB设备 |
**表4** usbfn_interface.h
USB设备端用于USB接口定义的相关接口如下,具体接口定义[见源码](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/device/usbfn_interface.h)
**表4** USB设备端用于USB接口定义的相关接口
| 接口名称 | 功能描述 |
| -------- | -------- |
......@@ -103,7 +135,9 @@ USB驱动模型Device侧开放的API接口功能,参考USB Device驱动模型
| int32_t&nbsp;UsbFnGetInterfacePipeInfo(struct&nbsp;UsbFnInterface<br/>\*interface,&nbsp;uint8_t&nbsp;pipeId,&nbsp;struct&nbsp;UsbFnPipeInfo&nbsp;\*info); | 获取管道信息 |
| int32_t&nbsp;UsbFnSetInterfaceProp(const&nbsp;struct&nbsp;UsbFnInterface<br/>\*interface,&nbsp;const&nbsp;char&nbsp;\*name,&nbsp;const&nbsp;char&nbsp;\*value); | 设置自定义属性 |
**表5** usbfn_request.h
USB设备端用于管理USB数据请求的相关接口如下,具体接口定义[见源码](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/device/usbfn_request.h)
**表5** USB设备端用于管理USB数据请求的相关接口
| 接口名称 | 功能描述 |
| -------- | -------- |
......@@ -115,113 +149,304 @@ USB驱动模型Device侧开放的API接口功能,参考USB Device驱动模型
| int32_t&nbsp;UsbFnCancelRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | 取消请求 |
## 开发步骤
USB驱动是基于HDF框架、PLATFORM和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同USB器件提供统一的驱动模型。本篇开发指导以串口为例,分别介绍USB Host和USB Device驱动开发。
### 开发步骤
USB驱动基于HDF框架、Platform和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同USB器件提供统一的驱动模型。此处以串口为例,分别介绍USB Host和USB Device驱动开发的详细过程。
#### Host DDK API驱动开发
1. 在设备私有数据HCS中配置,完成主机端驱动总体信息的配置,具体如下:
```cpp
root {
module = "usb_pnp_device";
usb_pnp_config {
match_attr = "usb_pnp_match";
usb_pnp_device_id = "UsbPnpDeviceId";
UsbPnpDeviceId {
idTableList = [
"host_acm_table"
];
host_acm_table {
// 驱动模块名,该字段的值必须和驱动入口结构的moduleName一致
moduleName = "usbhost_acm";
// 驱动对外发布服务的名称,必须唯一
serviceName = "usbhost_acm_pnp_service";
// 驱动私有数据匹配关键字
deviceMatchAttr = "usbhost_acm_pnp_matchAttr";
// 从该字段开始(包含该字段)之后数据长度,以byte为单位
length = 21;
// USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber
matchFlag = 0x0303;
// 厂商编号
vendorId = 0x12D1;
// 产品编号
productId = 0x5000;
// 设备出厂编号,低16位
bcdDeviceLow = 0x0000;
// 设备出厂编号,高16位
bcdDeviceHigh = 0x0000;
// USB分配的设备类代码
deviceClass = 0;
// USB分配的子类代码
deviceSubClass = 0;
// USB分配的设备协议代码
deviceProtocol = 0;
// 接口类型,根据实际需要可填写多个
interfaceClass = [0];
// 接口子类型,根据实际需要可填写多个
interfaceSubClass = [2, 0];
// 接口所遵循的协议,根据实际需要可填写多个
interfaceProtocol = [1, 2];
// 接口的编号,根据实际需要可填写多个
interfaceNumber = [2, 3];
}
}
}
}
```
### Host DDK API驱动开发步骤
2. USB主机端驱动开发工具包初始化。
1. 驱动匹配表配置。
```cpp
int32_t UsbInitHostSdk(struct UsbSession **session);
```
2. 初始化Host DDK
3. 步骤2初始化完后获取UsbInterface对象
3. 待步骤2初始化完后获取UsbInterface接口对象。
```cpp
const struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex);
```
4. 打开步骤3获取到的UsbInterface接口对象,获取相应接口的UsbInterfaceHandle对象。
```cpp
UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);
```
5. 根据步骤4获取到的UsbInterfaceHandle对象,获取指定索引为pipeIndex的pipeInfo信息。
```cpp
int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);
```
6. 为步骤4获取到的UsbInterfaceHandle预先分配待发送的IO Request对象。
```cpp
struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int32_t isoPackets, int32_t length);
```
7. 根据输入参数params填充步骤6预先分配的IO Request。
```cpp
int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params);
```
8. 提交IO Request对象,可以选择同步或异步两种模式。
```cpp
int32_t UsbSubmitRequestSync(const struct UsbRequest *request); //发送同步IO请求
int32_t UsbSubmitRequestAsync(const struct UsbRequest *request); //发送异步IO请求
```
### Host RAW API驱动开发步骤
#### Host RAW API驱动开发
1. 驱动匹配表配置。
1. 同Host DDK API的步骤1一样,在设备私有数据HCS中配置。
2. 初始化Host RAW,并打开USB设备,然后获取描述符,通过描述符获取接口、端点信息。
3. 分配Request,并根据传输类型使用相应接口对Request进行填充。
4. 提交IO Request对象,可以选择同步或异步两种模式。
### Device DDK API驱动开发步骤
1. 构造描述符。
2. 创建设备,使用步骤1构造的描述符实例化一个USB设备。
3. 根据创建的设备获取接口(UsbFnDeviceGetInterface),获取Pipe信息(UsbFnInterfaceGetPipeInfo),打开接口获取Handle(UsbFnInterfaceOpen),根据Handle和Pipe号获取Request(UsbFnRequestAlloc)。
```cpp
int32_t UsbRawInit(struct UsbSession **session);
```
3. 待步骤2完成后打开USB设备。
```cpp
UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);
```
4. 待步骤3完成后获取描述符,通过描述符获取接口、端点信息。
```cpp
int32_t UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);
```
5. 分配Request,并根据传输类型使用相应接口对Request进行填充。
```cpp
int32_t UsbRawFillBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于批量传输的请求
int32_t UsbRawFillControlSetup(const unsigned char *setup, const struct UsbControlRequestData *requestData);
int32_t UsbRawFillControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于控制传输的请求
int32_t UsbRawFillInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于中断传输的请求
int32_t UsbRawFillIsoRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于同步传输的请求
```
6. 提交IO Request对象,可以选择同步或异步两种模式。
```cpp
int32_t UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData); //发送同步USB控制传输请求
int32_t UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData); //发送同步USB批量传输请求
int32_t UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData); //发送同步执行USB中断传输请求
int32_t UsbRawSubmitRequest(const struct UsbRawRequest *request); //提交异步IO请求
```
#### Device DDK API驱动开发
1. 在设备功能代码中构造描述符。
```cpp
static struct UsbFnFunction g_acmFunction = { // 功能描述符
.enable = true,
.funcName = "f_generic.a",
.strings = g_acmStrings,
.fsDescriptors = g_acmFsFunction,
.hsDescriptors = g_acmHsFunction,
.ssDescriptors = g_acmSsFunction,
.sspDescriptors = NULL,
};
struct UsbFnFunction *g_functions[] = {
#ifdef CDC_ECM
&g_ecmFunction,
#endif
#ifdef CDC_ACM
&g_acmFunction,
#endif
NULL
};
static struct UsbFnConfiguration g_masterConfig = { // 配置描述符
.configurationValue = 1,
.iConfiguration = USB_FUNC_CONFIG_IDX,
.attributes = USB_CFG_BUS_POWERED,
.maxPower = POWER,
.functions = g_functions,
};
static struct UsbFnConfiguration *g_configs[] = {
&g_masterConfig,
NULL,
};
static struct UsbDeviceDescriptor g_cdcMasterDeviceDesc = { // 设备描述符
.bLength = sizeof(g_cdcMasterDeviceDesc),
.bDescriptorType = USB_DDK_DT_DEVICE,
.bcdUSB = CpuToLe16(BCD_USB),
.bDeviceClass = 0,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = USB_MAX_PACKET_SIZE,
.idVendor = CpuToLe16(DEVICE_VENDOR_ID),
.idProduct = CpuToLe16(DEVICE_PRODUCT_ID),
.bcdDevice = CpuToLe16(DEVICE_VERSION),
.iManufacturer = USB_FUNC_MANUFACTURER_IDX,
.iProduct = USB_FUNC_PRODUCT_IDX,
.iSerialNumber = USB_FUNC_SERIAL_IDX,
.bNumConfigurations = 1,
};
static struct UsbFnDeviceDesc g_masterFuncDevice = { // 描述符入口
.deviceDesc = &g_cdcMasterDeviceDesc,
.deviceStrings = g_devStrings,
.configs = g_configs,
};
```
2. 创建设备。描述符构造完成后,使用UsbFnDeviceCreate函数创建一个USB设备,并传入UDC控制器和UsbFnDescriptorData结构体。
```cpp
if (useHcs == 0) { // 使用代码编写的描述符
descData.type = USBFN_DESC_DATA_TYPE_DESC;
descData.descriptor = &g_acmFuncDevice;
} else { // 使用hcs编写的描述符
descData.type = USBFN_DESC_DATA_TYPE_PROP;
descData.property = acm->device->property;
}
// 创建设备
fnDev = (struct UsbFnDevice *) UsbFnCreateDevice(acm->udcName, &descData);
```
3. 设备创建后,使用UsbFnGetInterface函数获取UsbInterface接口对象,并通过UsbFnGetInterfacePipeInfo函数获取USB管道信息。
```cpp
// 获取接口
fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
// 获取Pipe信息
UsbFnGetInterfacePipeInfo(fnIface, i, &pipeInfo);
// 获取Handle
handle = UsbFnOpenInterface(fnIface);
// 获取控制(EP0)Request
req = UsbFnAllocCtrlRequest(acm->ctrlIface.handle,
sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
// 获取Request
req = UsbFnAllocCtrlRequest(acm->ctrlIface.handle,
sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
```
4. 通过UsbFnStartRecvInterfaceEvent函数接收Event事件,并通过UsbFnEventCallback回调函数对Event事件做出响应。
```cpp
// 开始接收Event事件
ret = UsbFnStartRecvInterfaceEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm);
// Event处理回调函数
static void UsbAcmEventCallback(struct UsbFnEvent *event)
{
struct UsbAcmDevice *acm = NULL;
if (event == NULL || event->context == NULL) {
HDF_LOGE("%s: event is null", __func__);
return;
}
4. 接收Event事件(UsbFnInterfaceStartRecvEvent)如Enable、Setup等事件,回调函数(UsbFnEventCallback)中对Event事件做出响应。
acm = (struct UsbAcmDevice *)event->context;
switch (event->type) {
case USBFN_STATE_BIND:
HDF_LOGI("%s: receive bind event", __func__);
break;
case USBFN_STATE_UNBIND:
HDF_LOGI("%s: receive unbind event", __func__);
break;
case USBFN_STATE_ENABLE:
HDF_LOGI("%s: receive enable event", __func__);
AcmEnable(acm);
break;
case USBFN_STATE_DISABLE:
HDF_LOGI("%s: receive disable event", __func__);
AcmDisable(acm);
acm->enableEvtCnt = 0;
break;
case USBFN_STATE_SETUP:
HDF_LOGI("%s: receive setup event", __func__);
if (event->setup != NULL) {
AcmSetup(acm, event->setup);
}
break;
case USBFN_STATE_SUSPEND:
HDF_LOGI("%s: receive suspend event", __func__);
AcmSuspend(acm);
break;
case USBFN_STATE_RESUME:
HDF_LOGI("%s: receive resume event", __func__);
AcmResume(acm);
break;
default:
break;
}
}
```
5. 收发数据,可以选择同步异步发送模式。
```cpp
notify = (struct UsbCdcNotification *)req->buf;
...
if (memcpy_s((void *)(notify + 1), length, data, length) != EOK) {
return HDF_FAILURE;
}
ret = UsbFnSubmitRequestAsync(req); // 异步发送
```
## 开发实例
### 开发实例
本实例提供USB串口驱动开发示例,并简要对具体关键点进行开发说明。
### Host DDK API驱动开发
```
root {
module = "usb_pnp_device";
usb_pnp_config {
match_attr = "usb_pnp_match";
usb_pnp_device_id = "UsbPnpDeviceId";
UsbPnpDeviceId {
idTableList = [
"host_acm_table"
];
host_acm_table {
// 驱动模块名,该字段的值必须和驱动入口结构的moduleName一致
moduleName = "usbhost_acm";
// 驱动对外发布服务的名称,必须唯一
serviceName = "usbhost_acm_pnp_service";
// 驱动私有数据匹配关键字
deviceMatchAttr = "usbhost_acm_pnp_matchAttr";
// 从该字段开始(包含该字段)之后数据长度,以byte为单位
length = 21;
// USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber
matchFlag = 0x0303;
// 厂商编号
vendorId = 0x12D1;
// 产品编号
productId = 0x5000;
// 设备出厂编号,低16位
bcdDeviceLow = 0x0000;
// 设备出厂编号,高16位
bcdDeviceHigh = 0x0000;
// USB分配的设备类代码
deviceClass = 0;
// USB分配的子类代码
deviceSubClass = 0;
// USB分配的设备协议代码
deviceProtocol = 0;
// 接口类型,根据实际需要可填写多个
interfaceClass = [0];
// 接口子类型,根据实际需要可填写多个
interfaceSubClass = [2, 0];
// 接口所遵循的协议,根据实际需要可填写多个
interfaceProtocol = [1, 2];
// 接口的编号,根据实际需要可填写多个
interfaceNumber = [2, 3];
}
}
}
}
```
#### Host DDK API驱动开发
```cpp
#include "usb_serial.h"
#include "hdf_base.h"
#include "hdf_log.h"
......@@ -234,7 +459,7 @@ root {
#define HDF_LOG_TAG USB_HOST_ACM
#define STR_LEN 512
static struct UsbRequest *g_syncRequest = NULL;
static struct UsbRequest *g_syncRequest = NULL; // 定义一个USB请求
static struct UsbRequest *g_ctrlCmdRequest = NULL;
static bool g_acmReleaseFlag = false;
static uint8_t *g_acmReadBuffer = NULL;
......@@ -245,42 +470,41 @@ static int32_t SerialCtrlMsg(struct AcmDevice *acm, uint8_t request,
int32_t ret;
uint16_t index = acm->intPipe->interfaceId;
struct UsbControlParams controlParams;
struct UsbRequestParams params;
struct UsbRequestParams params; // 定义一个USB请求参数对象
if (acm == NULL || buf == NULL) {
HDF_LOGE("%s:invalid param", __func__);
return HDF_ERR_IO;
}
if (acm->ctrlReq == NULL) {
// 为获取到的UsbInterfaceHandle预先分配待发送的IO Request对象
acm->ctrlReq = UsbAllocRequest(acm->ctrDevHandle, 0, len);
if (acm->ctrlReq == NULL) {
HDF_LOGE("%s: UsbAllocRequest failed", __func__);
return HDF_ERR_IO;
}
}
controlParams.request = request;
controlParams.target = USB_REQUEST_TARGET_INTERFACE;
controlParams.reqType = USB_REQUEST_TYPE_CLASS;
controlParams.direction = USB_REQUEST_DIR_TO_DEVICE;
controlParams.target = USB_REQUEST_TARGET_INTERFACE; // 接口对象
controlParams.reqType = USB_REQUEST_TYPE_CLASS; // 请求类型
controlParams.direction = USB_REQUEST_DIR_TO_DEVICE; // 从主机到设备的数据传输
controlParams.value = value;
controlParams.index = index;
controlParams.data = buf;
controlParams.size = len;
params.interfaceId = USB_CTRL_INTERFACE_ID;
params.interfaceId = USB_CTRL_INTERFACE_ID; // 定义USB控制接口的默认ID
params.pipeAddress = acm->ctrPipe->pipeAddress;
params.pipeId = acm->ctrPipe->pipeId;
params.requestType = USB_REQUEST_PARAMS_CTRL_TYPE;
params.timeout = USB_CTRL_SET_TIMEOUT;
params.requestType = USB_REQUEST_PARAMS_CTRL_TYPE; // 控制类型
params.timeout = USB_CTRL_SET_TIMEOUT; // 设置超时时间
params.ctrlReq = UsbControlSetUp(&controlParams);
// 根据params填充预先分配的IO Request
ret = UsbFillRequest(acm->ctrlReq, acm->ctrDevHandle, &params);
if (HDF_SUCCESS != ret) {
HDF_LOGE("%s: failed, ret=%d ", __func__, ret);
if (ret != HDF_SUCCESS) {
return ret;
}
ret = UsbSubmitRequestSync(acm->ctrlReq); //发送同步IO Request
if (HDF_SUCCESS != ret) {
HDF_LOGE("UsbSubmitRequestSync failed, ret=%d ", ret);
// 发送同步IO Request
ret = UsbSubmitRequestSync(acm->ctrlReq);
if (ret != HDF_SUCCESS) {
return ret;
}
if (!acm->ctrlReq->compInfo.status) {
......@@ -293,8 +517,8 @@ static struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm,
uint8_t interfaceIndex)
{
struct UsbInterface *tmpIf = NULL;
tmpIf = (struct UsbInterface *)UsbClaimInterface(acm->session, acm->busNum,
acm->devAddr, interfaceIndex); // 获取UsbInterface接口对象
// 获取UsbInterface接口对象
tmpIf = (struct UsbInterface *)UsbClaimInterface(acm->session, acm->busNum, acm->devAddr, interfaceIndex);
return tmpIf;
}
...
......@@ -303,8 +527,8 @@ static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm,
{
uint8_t i;
int32_t ret;
struct UsbInterfaceInfo *info = NULL;
UsbInterfaceHandle *interfaceHandle = NULL;
struct UsbInterfaceInfo *info = NULL; // 定义一个USB接口信息对象
UsbInterfaceHandle *interfaceHandle = NULL; // 定义一个USB接口操作句柄,就是void *类型
if (pipeType == USB_PIPE_TYPE_CONTROL)
{
info = &acm->ctrIface->info;
......@@ -313,19 +537,20 @@ static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm,
else
{
info = &acm->iface[interfaceIndex]->info;
// 根据interfaceIndex获取设备句柄
interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex);
}
for (i = 0; i <= info->pipeNum; i++) {
struct UsbPipeInfo p;
ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);// 获取指定索引为i的pipeInfo信息
// 获取指定索引为i的pipeInfo信息
ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);
if (ret < 0) {
continue;
}
if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) {
struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi));
struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi)); // 开辟内存并初始化
if (pi == NULL) {
HDF_LOGE("%s: Alloc pipe failed", __func__);
return NULL;
}
p.interfaceId = info->interfaceIndex;
......@@ -341,7 +566,6 @@ static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm,
{
uint8_t i;
if (acm == NULL) {
HDF_LOGE("%s: invalid params", __func__);
return NULL;
}
for (i = 0; i < acm->interfaceCnt; i++) {
......@@ -349,6 +573,7 @@ static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm,
if (!acm->iface[i]) {
continue;
}
// 获取控制pipe的pipeInfo信息
p = EnumePipe(acm, i, pipeType, pipeDirection);
if (p == NULL) {
continue;
......@@ -365,40 +590,32 @@ static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device)
errno_t err;
struct AcmDevice *acm = NULL;
if (device == NULL) {
HDF_LOGE("%s: device is null", __func__);
return HDF_ERR_INVALID_OBJECT;
}
acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm));
if (acm == NULL) {
HDF_LOGE("%s: Alloc usb serial device failed", __func__);
return HDF_FAILURE;
}
// 初始化互斥锁,&acm->lock表示指向互斥量的指针
if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) {
HDF_LOGE("%s:%d OsalMutexInit failed", __func__, __LINE__);
goto error;
}
info = (struct UsbPnpNotifyServiceInfo *)device->priv;
if (info != NULL) {
HDF_LOGD("%s:%d busNum=%d,devAddr=%d,interfaceLength=%d",
__func__, __LINE__, info->busNum, info->devNum, info->interfaceLength);
acm->busNum = info->busNum;
acm->devAddr = info->devNum;
acm->interfaceCnt = info->interfaceLength;
err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES,
(const void*)info->interfaceNumber, info->interfaceLength);
if (err != EOK) {
HDF_LOGE("%s:%d memcpy_s failed err=%d",
__func__, __LINE__, err);
goto lock_error;
}
} else {
HDF_LOGE("%s:%d info is NULL!", __func__, __LINE__);
goto lock_error;
}
acm->device = device;
device->service = &(acm->service);
acm->device->service->Dispatch = UsbSerialDeviceDispatch;
HDF_LOGD("UsbSerialDriverBind=========================OK");
return HDF_SUCCESS;
lock_error:
......@@ -416,9 +633,9 @@ static int32_t AcmAllocReadRequests(struct AcmDevice *acm)
int32_t ret;
struct UsbRequestParams readParams;
for (int32_t i = 0; i < ACM_NR; i++) {
acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize); // 分配待发送的readReq IO Request对象
// 分配待发送的readReq IO Request对象
acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize);
if (!acm->readReq[i]) {
HDF_LOGE("readReq request failed");
goto error;
}
readParams.userData = (void *)acm;
......@@ -426,14 +643,14 @@ static int32_t AcmAllocReadRequests(struct AcmDevice *acm)
readParams.pipeId = acm->dataInPipe->pipeId;
readParams.interfaceId = acm->dataInPipe->interfaceId;
readParams.callback = AcmReadBulk;
readParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE;
readParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE; /* Data type */
readParams.timeout = USB_CTRL_SET_TIMEOUT;
readParams.dataReq.numIsoPackets = 0;
readParams.dataReq.direction = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1;
readParams.dataReq.length = acm->readSize;
ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParams); // 填充待发送的readReq对象
if (HDF_SUCCESS != ret) {
HDF_LOGE("%s: UsbFillRequest failed, ret=%d n", __func__, ret);
// 根据readParams填充预先分配待发送的readReq IO Request对象
ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParams);
if (ret != HDF_SUCCESS) {
goto error;
}
}
......@@ -448,9 +665,9 @@ static int32_t AcmAllocNotifyRequest(struct AcmDevice *acm)
{
int32_t ret;
struct UsbRequestParams intParams = {};
acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize); // 分配待发送的中断IO Request对象
// 分配待发送的中断IO Request对象
acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize);
if (!acm->notifyReq) {
HDF_LOGE("notifyReq request failed");
return HDF_ERR_MALLOC_FAIL;
}
intParams.userData = (void *)acm;
......@@ -463,9 +680,9 @@ static int32_t AcmAllocNotifyRequest(struct AcmDevice *acm)
intParams.dataReq.numIsoPackets = 0;
intParams.dataReq.direction = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK;
intParams.dataReq.length = acm->intSize;
ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParams); // 填充预先分配的中断IO Request
if (HDF_SUCCESS != ret) {
HDF_LOGE("%s: UsbFillRequest failed, ret=%d n", __func__, ret);
// 填充预先分配的中断IO Request
ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParams);
if (ret != HDF_SUCCESS) {
goto error;
}
return HDF_SUCCESS;
......@@ -479,6 +696,7 @@ static void AcmReleaseInterfaces(struct AcmDevice *acm)
{
for (int32_t i = 0; i < acm->interfaceCnt; i++) {
if (acm->iface[i]) {
// 释放一个USB接口对象
UsbReleaseInterface(acm->iface[i]);
acm->iface[i] = NULL;
}
......@@ -492,22 +710,23 @@ static void AcmReleaseInterfaces(struct AcmDevice *acm)
static int32_t AcmClaimInterfaces(struct AcmDevice *acm)
{
for (int32_t i = 0; i < acm->interfaceCnt; i++) {
acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]); // 获取UsbInterface接口对象
// 获取UsbInterface接口对象
acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]);
if (acm->iface[i] == NULL) {
HDF_LOGE("%s: interface%d is null", __func__, acm->interfaceIndex[i]);
goto error;
}
}
acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID); // 获取控制接口对应的UsbInterface接口对象
// 获取控制接口对应的UsbInterface接口对象
acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID);
if (acm->ctrIface == NULL) {
HDF_LOGE("%s: GetUsbInterfaceById null", __func__);
goto error;
}
return HDF_SUCCESS;
error:
// 根据acm->interfaceCnt循环释放接口对象
AcmReleaseInterfaces(acm);
return HDF_FAILURE;
}
......@@ -516,6 +735,7 @@ static void AcmCloseInterfaces(struct AcmDevice *acm)
{
for (int32_t i = 0; i < acm->interfaceCnt; i++) {
if (acm->devHandle[i]) {
// 关闭一个USB设备对象
UsbCloseInterface(acm->devHandle[i]);
acm->devHandle[i] = NULL;
}
......@@ -530,49 +750,49 @@ static int32_t AcmOpenInterfaces(struct AcmDevice *acm)
{
for (int32_t i = 0; i < acm->interfaceCnt; i++) {
if (acm->iface[i]) {
acm->devHandle[i] = UsbOpenInterface(acm->iface[i]); // 打开获取到的UsbInterface接口对象
// 打开获取到的UsbInterface接口对象
acm->devHandle[i] = UsbOpenInterface(acm->iface[i]);
if (acm->devHandle[i] == NULL) {
HDF_LOGE("%s: UsbOpenInterface null", __func__);
goto error;
}
}
}
acm->ctrDevHandle = UsbOpenInterface(acm->ctrIface);
if (acm->ctrDevHandle == NULL) {
HDF_LOGE("%s: ctrDevHandle UsbOpenInterface null", __func__);
goto error;
}
return HDF_SUCCESS;
error:
// 关闭所有UsbInterface接口对象
AcmCloseInterfaces(acm);
return HDF_FAILURE;
}
static int32_t AcmGetPipes(struct AcmDevice *acm)
{
acm->dataInPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN);// 获取dataInPipe的pipeInfo信息
// 获取dataInPipe的pipeInfo信息
acm->dataInPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN);
if (acm->dataInPipe == NULL) {
HDF_LOGE("dataInPipe is NULL");
goto error;
}
acm->dataOutPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT);// 获取dataOutPipe的pipeInfo信息
// 获取dataOutPipe的pipeInfo信息
acm->dataOutPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT);
if (acm->dataOutPipe == NULL) {
HDF_LOGE("dataOutPipe is NULL");
goto error;
}
acm->ctrPipe = EnumePipe(acm, acm->ctrIface->info.interfaceIndex, USB_PIPE_TYPE_CONTROL, USB_PIPE_DIRECTION_OUT); // 获取控制pipe的pipeInfo信息
// 获取控制pipe的pipeInfo信息
acm->ctrPipe = EnumePipe(acm, acm->ctrIface->info.interfaceIndex, USB_PIPE_TYPE_CONTROL, USB_PIPE_DIRECTION_OUT);
if (acm->ctrPipe == NULL) {
HDF_LOGE("ctrPipe is NULL");
goto error;
}
acm->intPipe = GetPipe(acm, USB_PIPE_TYPE_INTERRUPT, USB_PIPE_DIRECTION_IN);// 获取中断pipe的pipeInfo信息
// 获取中断pipe的pipeInfo信息
acm->intPipe = GetPipe(acm, USB_PIPE_TYPE_INTERRUPT, USB_PIPE_DIRECTION_IN);
if (acm->intPipe == NULL) {
HDF_LOGE("intPipe is NULL");
goto error;
}
......@@ -580,10 +800,10 @@ static int32_t AcmGetPipes(struct AcmDevice *acm)
acm->writeSize = acm->dataOutPipe->maxPacketSize;
acm->ctrlSize = acm->ctrPipe->maxPacketSize;
acm->intSize = acm->intPipe->maxPacketSize;
return HDF_SUCCESS;
error:
// 释放设备中所有的管道信息
AcmFreePipes(acm);
return HDF_FAILURE;
}
......@@ -605,29 +825,26 @@ static int32_t AcmAllocRequests(struct AcmDevice *acm)
int32_t ret;
if (AcmWriteBufAlloc(acm) < 0) {
HDF_LOGE("%s: AcmWriteBufAlloc failed", __func__);
return HDF_ERR_MALLOC_FAIL;
}
for (int32_t i = 0; i < ACM_NW; i++) {
struct AcmWb *snd = &(acm->wb[i]);
snd->request = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataOutPipe->interfaceId), 0, acm->writeSize); //分配待发送的IO Request对象
// 分配待发送的IO Request对象
snd->request = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataOutPipe->interfaceId), 0, acm->writeSize);
snd->instance = acm;
if (snd->request == NULL) {
HDF_LOGE("%s:%d snd request failed", __func__, __LINE__);
goto error_alloc_write_req;
}
}
ret = AcmAllocNotifyRequest(acm); // 分配并填充中断IO Request对象
ret = AcmAllocNotifyRequest(acm); // 分配并填充中断IO Request对象
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s:%d AcmAllocNotifyRequest failed", __func__, __LINE__);
goto error_alloc_int_req;
}
ret = AcmAllocReadRequests(acm); // 分配并填充readReq IO Request对象
ret = AcmAllocReadRequests(acm); // 分配并填充readReq IO Request对象
if (ret) {
HDF_LOGE("%s:%d AcmAllocReadRequests failed", __func__, __LINE__);
goto error_alloc_read_req;
}
......@@ -648,57 +865,56 @@ static int32_t AcmInit(struct AcmDevice *acm)
struct UsbSession *session = NULL;
if (acm->initFlag == true) {
HDF_LOGE("%s:%d: initFlag is true", __func__, __LINE__);
return HDF_SUCCESS;
}
ret = UsbInitHostSdk(NULL); // 初始化Host DDK
// 初始化Host DDK
ret = UsbInitHostSdk(NULL);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: UsbInitHostSdk failed", __func__);
return HDF_ERR_IO;
}
acm->session = session;
// 根据acm->interfaceIndex[i]分别获取UsbInterface接口对象
ret = AcmClaimInterfaces(acm);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: AcmClaimInterfaces failed", __func__);
goto error_claim_interfaces;
}
// 根据acm->iface[i]分别打开UsbInterface接口对象
ret = AcmOpenInterfaces(acm);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: AcmOpenInterfaces failed", __func__);
goto error_open_interfaces;
}
// 获取管道信息的指针
ret = AcmGetPipes(acm);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: AcmGetPipes failed", __func__);
goto error_get_pipes;
}
ret = AcmAllocRequests(acm);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: AcmAllocRequests failed", __func__);
goto error_alloc_reqs;
}
acm->lineCoding.dwDTERate = CpuToLe32(DATARATE);
acm->lineCoding.bCharFormat = CHARFORMAT;
acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); // 转换为小端数据
acm->lineCoding.bCharFormat = CHARFORMAT; // 8
acm->lineCoding.bParityType = USB_CDC_NO_PARITY;
acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS;
acm->initFlag = true;
HDF_LOGD("%s:%d========OK", __func__, __LINE__);
return HDF_SUCCESS;
error_alloc_reqs:
AcmFreePipes(acm);
error_get_pipes:
// 关闭所有UsbInterface接口对象
AcmCloseInterfaces(acm);
error_open_interfaces:
// 释放所有UsbInterface接口对象
AcmReleaseInterfaces(acm);
error_claim_interfaces:
// 在主机端退出USB DDK,acm->session代表指向会话上下文的指针
UsbExitHostSdk(acm->session);
acm->session = NULL;
return ret;
......@@ -707,7 +923,6 @@ error_claim_interfaces:
static void AcmRelease(struct AcmDevice *acm)
{
if (acm->initFlag == false) {
HDF_LOGE("%s:%d: initFlag is false", __func__, __LINE__);
return;
}
......@@ -715,9 +930,9 @@ static void AcmRelease(struct AcmDevice *acm)
AcmFreePipes(acm);
AcmCloseInterfaces(acm);
AcmReleaseInterfaces(acm);
// 在主机端退出USB DDK
UsbExitHostSdk(acm->session);
acm->session = NULL;
acm->initFlag = false;
}
......@@ -727,15 +942,15 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
struct AcmDevice *acm = NULL;
if (device == NULL) {
HDF_LOGE("%s: device is null", __func__);
return HDF_ERR_INVALID_OBJECT;
}
acm = (struct AcmDevice *)device->service;
// 初始化互斥锁,&acm->readLock表示指向互斥量的指针
OsalMutexInit(&acm->readLock);
OsalMutexInit(&acm->writeLock);
HDF_LOGD("%s:%d busNum=%d,devAddr=%d",
__func__, __LINE__, acm->busNum, acm->devAddr);
HDF_LOGD("%s:%d busNum=%d,devAddr=%d", __func__, __LINE__, acm->busNum, acm->devAddr);
// 给USB串口设备信息开辟空间并赋值
ret = UsbSerialDeviceAlloc(acm);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: Serial Device alloc failed", __func__);
......@@ -743,9 +958,6 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
acm->initFlag = false;
g_acmReleaseFlag = false;
HDF_LOGD("%s:%d init ok!", __func__, __LINE__);
return ret;
}
......@@ -754,43 +966,40 @@ static void UsbSerialDriverRelease(struct HdfDeviceObject *device)
struct AcmDevice *acm = NULL;
if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return;
}
acm = (struct AcmDevice *)device->service;
if (acm == NULL) {
HDF_LOGE("%s: acm is null", __func__);
return;
}
g_acmReleaseFlag = true;
if (acm->initFlag == true) {
HDF_LOGE("%s:%d AcmRelease", __func__, __LINE__);
AcmRelease(acm);
}
// 释放usb串口设备信息
UsbSeriaDevicelFree(acm);
// 释放互斥锁
OsalMutexDestroy(&acm->writeLock);
OsalMutexDestroy(&acm->readLock);
OsalMutexDestroy(&acm->lock);
OsalMemFree(acm);
acm = NULL;
HDF_LOGD("%s:%d exit", __func__, __LINE__);
}
// 驱动的Bind、Init、及Release操作
struct HdfDriverEntry g_usbSerialDriverEntry = {
.moduleVersion = 1,
.moduleName = "usbhost_acm", // 驱动模块名称,必须与hcs文件中配置的名称一致
.moduleName = "usbhost_acm", // 驱动模块名称,必须与hcs文件中配置的名称一致
.Bind = UsbSerialDriverBind,
.Init = UsbSerialDriverInit,
.Release = UsbSerialDriverRelease,
};
HDF_INIT(g_usbSerialDriverEntry);
HDF_INIT(g_usbSerialDriverEntry); // 驱动入口
```
### Host RAW API驱动开发
#### Host RAW API驱动开发
```cpp
root {
......@@ -851,7 +1060,7 @@ root {
#include "hdf_log.h"
#include "hdf_usb_pnp_manage.h"
#define HDF_LOG_TAG USB_HOST_ACM_RAW_API
#define HDF_LOG_TAG USB_HOST_ACM_RAW_API // 日志中可查寻的标签
#define USB_CTRL_REQ_SIZE 64
#define USB_IO_THREAD_STACK_SIZE 8192
#define USB_RAW_IO_SLEEP_MS_TIME 100
......@@ -870,32 +1079,27 @@ static int32_t UsbGetConfigDescriptor(UsbRawHandle *devHandle, struct UsbRawConf
int32_t ret;
if (devHandle == NULL) {
HDF_LOGE("%s:%d devHandle is NULL",
__func__, __LINE__);
return HDF_ERR_INVALID_PARAM;
}
// 获取主用设备配置
ret = UsbRawGetConfiguration(devHandle, &activeConfig);
if (ret) {
HDF_LOGE("%s:%d UsbRawGetConfiguration failed, ret=%d",
__func__, __LINE__, ret);
if (ret != HDF_SUCCESS) {
return HDF_FAILURE;
}
HDF_LOGE("%s:%d activeConfig=%d", __func__, __LINE__, activeConfig);
// 根据指定的设备句柄获取设备指针
dev = UsbRawGetDevice(devHandle);
if (dev == NULL) {
HDF_LOGE("%s:%d UsbRawGetDevice failed",
__func__, __LINE__);
return HDF_FAILURE;
}
// 根据指定的设备ID获取设备配置描述符
ret = UsbRawGetConfigDescriptor(dev, activeConfig, config);
if (ret) {
HDF_LOGE("UsbRawGetConfigDescriptor failed, ret=%dn", ret);
return HDF_FAILURE;
if (ret != HDF_SUCCESS) {
HDF_LOGE("UsbRawGetConfigDescriptor failed, ret=%d\n", ret);
}
return HDF_SUCCESS;
return ret;
}
...
static int32_t UsbAllocWriteRequests(struct AcmDevice *acm)
......@@ -904,10 +1108,10 @@ static int32_t UsbAllocWriteRequests(struct AcmDevice *acm)
for (i = 0; i < ACM_NW; i++) {
struct AcmWb *snd = &acm->wb[i];
// 分配一个具有指定数目的同步传输分组描述符的传输请求
snd->request = UsbRawAllocRequest(acm->devHandle, 0, acm->dataOutEp->maxPacketSize);
snd->instance = acm;
if (snd->request == NULL) {
HDF_LOGE("%s: UsbRawAllocRequest failed", __func__);
return HDF_ERR_MALLOC_FAIL;
}
}
......@@ -923,17 +1127,14 @@ static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device)
errno_t err;
if (device == NULL) {
HDF_LOGE("%s: device is null", __func__);
return HDF_ERR_INVALID_OBJECT;
}
acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm));
if (acm == NULL) {
HDF_LOGE("%s: Alloc usb serial device failed", __func__);
return HDF_FAILURE;
}
if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) {
HDF_LOGE("%s:%d OsalMutexInit failed", __func__, __LINE__);
goto error;
}
......@@ -945,19 +1146,15 @@ static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device)
err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES,
(const void*)info->interfaceNumber, info->interfaceLength);
if (err != EOK) {
HDF_LOGE("%s:%d memcpy_s failed err=%d",
__func__, __LINE__, err);
goto lock_error;
}
} else {
HDF_LOGE("%s:%d info is NULL!", __func__, __LINE__);
goto lock_error;
}
device->service = &(acm->service);
device->service->Dispatch = UsbSerialDeviceDispatch;
acm->device = device;
HDF_LOGD("UsbSerialDriverBind=========================OK");
return HDF_SUCCESS;
lock_error:
......@@ -977,9 +1174,9 @@ static int32_t UsbAllocReadRequests(struct AcmDevice *acm)
int32_t ret;
for (int32_t i = 0; i < ACM_NR; i++) {
// 分配一个具有指定数目的同步传输分组描述符的传输请求
acm->readReq[i] = UsbRawAllocRequest(acm->devHandle, 0, size);
if (!acm->readReq[i]) {
HDF_LOGE("readReq request failed");
return HDF_ERR_MALLOC_FAIL;
}
......@@ -990,10 +1187,9 @@ static int32_t UsbAllocReadRequests(struct AcmDevice *acm)
reqData.timeout = USB_CTRL_SET_TIMEOUT;
reqData.length = size;
// 在批量传输请求中填写所需信息
ret = UsbRawFillBulkRequest(acm->readReq[i], acm->devHandle, &reqData);
if (ret) {
HDF_LOGE("%s: FillBulkRequest failed, ret=%d n",
__func__, ret);
if (ret != HDF_SUCCESS) {
return HDF_FAILURE;
}
}
......@@ -1007,9 +1203,9 @@ static int32_t UsbAllocNotifyRequest(struct AcmDevice *acm)
int32_t size = acm->notifyEp->maxPacketSize;
int32_t ret;
// 分配一个具有指定数目的同步传输分组描述符的传输请求
acm->notifyReq = UsbRawAllocRequest(acm->devHandle, 0, size);
if (!acm->notifyReq) {
HDF_LOGE("notifyReq request failed");
return HDF_ERR_MALLOC_FAIL;
}
......@@ -1020,9 +1216,9 @@ static int32_t UsbAllocNotifyRequest(struct AcmDevice *acm)
fillRequestData.userData = (void *)acm;
fillRequestData.timeout = USB_CTRL_SET_TIMEOUT;
// 在中断传输请求中填充所需的信息
ret = UsbRawFillInterruptRequest(acm->notifyReq, acm->devHandle, &fillRequestData);
if (ret) {
HDF_LOGE("%s: FillInterruptRequest failed, ret=%d", __func__, ret);
if (ret != HDF_SUCCESS) {
return HDF_FAILURE;
}
......@@ -1036,62 +1232,55 @@ static int32_t UsbSerialInit(struct AcmDevice *acm)
int32_t ret;
if (acm->initFlag == true) {
HDF_LOGE("%s:%d: initFlag is true", __func__, __LINE__);
return HDF_SUCCESS;
}
// 以专家模式初始化USB DDK
ret = UsbRawInit(NULL);
if (ret) {
HDF_LOGE("%s:%d UsbRawInit failed", __func__, __LINE__);
if (ret != HDF_SUCCESS) {
return HDF_ERR_IO;
}
acm->session = session;
// 打开一个USB设备对象
devHandle = UsbRawOpenDevice(session, acm->busNum, acm->devAddr);
if (devHandle == NULL) {
HDF_LOGE("%s:%d UsbRawOpenDevice failed", __func__, __LINE__);
ret = HDF_FAILURE;
goto err_open_device;
}
acm->devHandle = devHandle;
// 获取主用设备配置、设备指针及配置描述符
ret = UsbGetConfigDescriptor(devHandle, &acm->config);
if (ret) {
HDF_LOGE("%s:%d UsbGetConfigDescriptor failed", __func__, __LINE__);
if (ret != HDF_SUCCESS) {
ret = HDF_FAILURE;
goto err_get_desc;
}
ret = UsbParseConfigDescriptor(acm, acm->config);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s:%d UsbParseConfigDescriptor failed", __func__, __LINE__);
ret = HDF_FAILURE;
goto err_parse_desc;
}
ret = AcmWriteBufAlloc(acm);
if (ret < 0) {
HDF_LOGE("%s:%d AcmWriteBufAlloc failed", __func__, __LINE__);
ret = HDF_FAILURE;
goto err_alloc_write_buf;
}
ret = UsbAllocWriteRequests(acm);
if (ret < 0) {
HDF_LOGE("%s:%d UsbAllocWriteRequests failed", __func__, __LINE__);
ret = HDF_FAILURE;
goto err_alloc_write_reqs;
}
ret = UsbAllocNotifyRequest(acm);
if (ret) {
HDF_LOGE("%s:%d UsbAllocNotifyRequests failed", __func__, __LINE__);
goto err_alloc_notify_req;
}
ret = UsbAllocReadRequests(acm);
if (ret) {
HDF_LOGE("%s:%d UsbAllocReadRequests failed", __func__, __LINE__);
goto err_alloc_read_reqs;
}
ret = UsbStartIo(acm);
if (ret) {
HDF_LOGE("%s:%d UsbAllocReadRequests failed", __func__, __LINE__);
goto err_start_io;
}
......@@ -1102,18 +1291,14 @@ static int32_t UsbSerialInit(struct AcmDevice *acm)
ret = UsbRawSubmitRequest(acm->notifyReq);
if (ret) {
HDF_LOGE("%s:%d UsbRawSubmitRequest failed", __func__, __LINE__);
goto err_submit_req;
}
acm->initFlag = true;
HDF_LOGD("%s:%d=========================OK", __func__, __LINE__);
return HDF_SUCCESS;
err_submit_req:
UsbStopIo(acm);
UsbStopIo(acm); // 停止IO线程并释放所有资源
err_start_io:
UsbFreeReadRequests(acm);
err_alloc_read_reqs:
......@@ -1128,9 +1313,9 @@ err_parse_desc:
UsbRawFreeConfigDescriptor(acm->config);
acm->config = NULL;
err_get_desc:
(void)UsbRawCloseDevice(devHandle);
(void)UsbRawCloseDevice(devHandle); // 关闭USB设备对象
err_open_device:
UsbRawExit(acm->session);
UsbRawExit(acm->session); // 退出USB DDK的专家模式
return ret;
}
......@@ -1138,7 +1323,6 @@ err_open_device:
static void UsbSerialRelease(struct AcmDevice *acm)
{
if (acm->initFlag == false) {
HDF_LOGE("%s:%d: initFlag is false", __func__, __LINE__);
return;
}
......@@ -1156,6 +1340,7 @@ static void UsbSerialRelease(struct AcmDevice *acm)
UsbReleaseInterfaces(acm);
UsbRawFreeConfigDescriptor(acm->config);
acm->config = NULL;
// 退出USB DDK的专家模式
UsbRawExit(acm->session);
acm->initFlag = false;
......@@ -1167,7 +1352,6 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
int32_t ret;
if (device == NULL) {
HDF_LOGE("%s:%d device is null", __func__, __LINE__);
return HDF_ERR_INVALID_OBJECT;
}
acm = (struct AcmDevice *)device->service;
......@@ -1181,9 +1365,6 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
acm->initFlag = false;
g_rawAcmReleaseFlag = false;
HDF_LOGD("%s:%d init ok!", __func__, __LINE__);
return ret;
}
......@@ -1191,20 +1372,17 @@ static void UsbSerialDriverRelease(struct HdfDeviceObject *device)
{
struct AcmDevice *acm = NULL;
if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return;
}
acm = (struct AcmDevice *)device->service;
if (acm == NULL) {
HDF_LOGE("%s: acm is null", __func__);
return;
}
g_rawAcmReleaseFlag = true;
if (acm->initFlag == true) {
HDF_LOGE("%s:%d UsbSerialRelease", __func__, __LINE__);
UsbSerialRelease(acm);
}
UsbSeriaDevicelFree(acm);
......@@ -1213,12 +1391,11 @@ static void UsbSerialDriverRelease(struct HdfDeviceObject *device)
OsalMutexDestroy(&acm->lock);
OsalMemFree(acm);
acm = NULL;
HDF_LOGD("%s:%d exit", __func__, __LINE__);
}
struct HdfDriverEntry g_usbSerialRawDriverEntry = {
.moduleVersion = 1,
.moduleName = "usbhost_acm_rawapi", //驱动模块名称,必须与hcs文件中配置的名称一致
.moduleName = "usbhost_acm_rawapi", // 驱动模块名称,必须与hcs文件中配置的名称一致
.Bind = UsbSerialDriverBind,
.Init = UsbSerialDriverInit,
.Release = UsbSerialDriverRelease,
......@@ -1226,108 +1403,134 @@ struct HdfDriverEntry g_usbSerialRawDriverEntry = {
HDF_INIT(g_usbSerialRawDriverEntry);
```
### Device DDK API驱动开发
#### Device DDK API驱动开发
USB ACM设备核心代码路径为drivers\peripheral\usb\gadget\function\acm\cdcacm.c。其使用示例如下所示,首先根据描述符创建设备,然后获取接口,打开接口,获取Pipe信息,接收Event事件,接着进行USB通信(读写等),设备卸载时候,关闭接口,停止Event接收,删除设备。
1、创建设备
```cpp
static int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm,
struct DeviceResourceIface *iface)
{
struct UsbFnDevice *fnDev = NULL;
struct UsbFnDescriptorData descData;
uint8_t useHcs;
...
if (useHcs == 0) {
descData.type = USBFN_DESC_DATA_TYPE_DESC;
descData.descriptor = &g_masterFuncDevice;
} else {
descData.type = USBFN_DESC_DATA_TYPE_PROP;
descData.property = device->property;
}
/* 创建设备 */
fnDev = (struct UsbFnDevice *)UsbFnDeviceCreate(acm->udcName, &descData);
if (fnDev == NULL) {
HDF_LOGE("%s: create usb function device failed", __func__);
return HDF_FAILURE;
}
...
}
```
2、获取接口,打开接口,获取Pipe信息
```cpp
static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface)
{
...
for (i = 0; i < fnIface->info.numPipes; i++) {
struct UsbFnPipeInfo pipeInfo;
/* 获取pipe信息 */
ret = UsbFnInterfaceGetPipeInfo(fnIface, i, &pipeInfo);
1. 创建设备。
```cpp
static int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm, struct DeviceResourceIface *iface)
{
struct UsbFnDevice *fnDev = NULL;
struct UsbFnDescriptorData descData;
uint8_t useHcs;
...
if (useHcs == 0) { // 描述符来自于代码中编码
descData.type = USBFN_DESC_DATA_TYPE_DESC;
descData.descriptor = &g_masterFuncDevice;
} else { // 描述符来自于解析hcs文件
descData.type = USBFN_DESC_DATA_TYPE_PROP;
descData.property = device->property;
}
/* 创建设备 */
fnDev = (struct UsbFnDevice *)UsbFnDeviceCreate(acm->udcName, &descData);
if (fnDev == NULL) {
return HDF_FAILURE;
}
...
}
return HDF_SUCCESS;
}
/* 获取接口,打开接口获取handle */
static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev)
{
...
for (i = 0; i < fnDev->numInterfaces; i++) {
/* 获取接口 */
fnIface = (struct UsbFnInterface *)UsbFnDeviceGetInterface(fnDev, i);
```
2. 获取接口,打开接口,获取Pipe信息
```cpp
static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface)
{
...
/* 打开接口 */
handle = UsbFnInterfaceOpen(fnIface);
for (i = 0; i < fnIface->info.numPipes; i++) {
struct UsbFnPipeInfo pipeInfo;
/* 获取pipe信息 */
ret = UsbFnInterfaceGetPipeInfo(fnIface, i, &pipeInfo);
...
}
return HDF_SUCCESS;
}
/* 获取接口,打开接口获取handle */
static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev)
{
...
for (i = 0; i < fnDev->numInterfaces; i++) {
/* 获取接口 */
fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
...
/* 打开接口 */
handle = UsbFnInterfaceOpen(fnIface);
...
}
return HDF_SUCCESS;
}
return HDF_SUCCESS;
}
```
```
3、接收Event事件
```cpp
static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int32_t num)
{
...
3. 接收Event事件(EP0控制传输)
```cpp
static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int32_t num)
{
...
req = UsbFnCtrlRequestAlloc(acm->ctrlIface.handle,
sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
...
}
static int32_t AcmDriverInit(struct HdfDeviceObject *device)
{
...
/* 开始接收Event */
ret = UsbFnInterfaceStartRecvEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm);
...
}
```
4、进行USB通信(读写等)
```cpp
static int32_t AcmSendNotifyRequest(struct UsbAcmDevice *acm, uint8_t type,
uint16_t value, void *data, uint32_t length)
{
...
/* 异步发送 */
ret = UsbFnRequestSubmitAsync(req);
...
}
```
5、关闭接口,停止Event接收,删除设备
```cpp
static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm)
{
int32_t ret;
/* 关闭接口 */
(void)UsbFnInterfaceClose(acm->ctrlIface.handle);
(void)UsbFnInterfaceClose(acm->dataIface.handle);
/* 停止接收Event */
(void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn);
/* 删除设备 */
ret = UsbFnDeviceRemove(acm->fnDev);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: remove usb function device failed", __func__);
...
}
return ret;
}
```
static int32_t AcmDriverInit(struct HdfDeviceObject *device)
{
...
/* 开始接收Event */
ret = UsbFnInterfaceStartRecvEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm);
...
}
```
4. 进行USB通信(读写等)
```cpp
static int32_t AcmSendNotifyRequest(struct UsbAcmDevice *acm, uint8_t type,
uint16_t value, void *data, uint32_t length)
{
...
/* 异步发送 */
ret = UsbFnRequestSubmitAsync(req);
...
}
```
5. 关闭接口,停止Event接收,删除设备
```cpp
static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm)
{
int32_t ret;
/* 关闭接口 */
(void)UsbFnInterfaceClose(acm->ctrlIface.handle);
(void)UsbFnInterfaceClose(acm->dataIface.handle);
/* 停止接收Event EP0控制传输 */
(void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn);
/* 删除设备 */
ret = UsbFnDeviceRemove(acm->fnDev);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: remove usb function device failed", __func__);
}
return ret;
}
```
## 参考
- 代码仓库如下:
**[drivers\_hdf\_core](https://gitee.com/openharmony/drivers_hdf_core)**
[drivers\_peripheral](https://gitee.com/openharmony/drivers_peripheral)
[drivers\_interface](https://gitee.com/openharmony/drivers_interface)
- 代码路径如下:
USB驱动模型liteos适配://drivers/hdf_core/adapter/khdf/liteos/model/usb
USB DDK驱动加载实现://drivers/hdf_core/framework/model/usb
USB HDI服务端实现://drivers/peripheral/usb/hdi_service
USB HDI对外接口://out/{product_name}/gen/drivers/interface/usb/v1_0
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册