diff --git a/zh-cn/device-dev/driver/Readme-CN.md b/zh-cn/device-dev/driver/Readme-CN.md index 27caa89536b5091ac5a8d7f24a568cc774d93da9..a5b29873e75b372a7de4b8c29761252d7cc9b755 100755 --- a/zh-cn/device-dev/driver/Readme-CN.md +++ b/zh-cn/device-dev/driver/Readme-CN.md @@ -33,4 +33,4 @@ - [TOUCHSCREEN](driver-peripherals-touch-des.md) - [SENSOR](driver-peripherals-sensor-des.md) - [WLAN](driver-peripherals-external-des.md) - + - [USB](driver-peripherals-usb-des.md) diff --git a/zh-cn/device-dev/driver/driver-peripherals-usb-des.md b/zh-cn/device-dev/driver/driver-peripherals-usb-des.md new file mode 100755 index 0000000000000000000000000000000000000000..02882fcc10d4957bcf2951c4725a90a5c8ba5898 --- /dev/null +++ b/zh-cn/device-dev/driver/driver-peripherals-usb-des.md @@ -0,0 +1,1572 @@ +# USB + +- [概述](#section175431838101617) + - [接口说明](#section17667171301711) + +- [开发指导](#section65745222184) + - [Host DDK API驱动开发步骤](#section865734181916) + - [Host RAW API驱动开发步骤](#section865734181916) + - [Device DDK API驱动开发步骤](#section865734181916) + +- [开发实例](#section263714411191) + - [Host DDK API驱动开发](#section18249155619195) + - [Host RAW API驱动开发](#section3571192072014) + - [Device DDK API驱动开发](#section6356758162015) + + +## 概述 + +USB Host部分,主要包括协议封装、设备管理、驱动安装与卸载等。 + +USB Device部分,支持USB功能设备的开发,提供USB设备相关功能,主要包括设备管理、配置管理、IO管理,实现USB功能设备创建、配置、数据通信等。 + +USB Host驱动模型如下图1所示: + +**图 1** USB Host驱动模型图 +![](figure/USB-Host驱动模型图.png "USB Host驱动模型图") + +**图 2** USB Device驱动模型图 +![](figure/USB-Device驱动模型图.png "USB Device驱动模型图") + +USB驱动模型对外开放的API接口能力如下: + +- Usb Host DDK提供给用户态可直接调用的驱动能力接口,按照功能分类三大类:DDK初始化类、对interface对象操作类、对request对象操作类,可以提供DDK初始化、interface绑定和释放,打开和关闭操作,request的申请和释放,同步和异步传输等。 +- Usb Deivce DDK提供设备管理、IO管理、配置管理,主要功能有:创建和删除设备、获取和打开接口、同步和异步传输等。 + +### 接口说明 + +USB驱动模型Host侧开放的API接口功能,参考表1。 + +**表 1** USB驱动模型Host侧开放的API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

头文件

+

接口名称

+

功能描述

+

usb_interface.h

+

+

+

int32_t UsbInitHostSdk(struct UsbSession **session);

+

USB主机端驱动开发工具包初始化

+

int32_t UsbExitHostSdk(const struct UsbSession *session);

+

USB主机端驱动开发工具包退出

+

const struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex);

+

获取USB接口对象

+

int UsbReleaseInterface(const struct UsbInterface *interfaceObj);

+

释放USB接口对象

+

int UsbAddOrRemoveInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex, UsbInterfaceStatus status);

+

增加移除接口

+

UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);

+

打开USB对象接口

+

int32_t UsbCloseInterface(const UsbInterfaceHandle *interfaceHandle);

+

关闭USB接口对象

+

int32_t UsbSelectInterfaceSetting(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, struct UsbInterface **interfaceObj);

+

设置可选配置

+

int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);

+

获取指定可选设置的管道信息

+

int32_t UsbClearInterfaceHalt(const UsbInterfaceHandle *interfaceHandle, uint8_t pipeAddress);

+

清除指定索引的管道状态

+

struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int isoPackets, int length);

+

分配请求对象

+

int UsbFreeRequest(const struct UsbRequest *request);

+

释放请求对象

+

int UsbSubmitRequestAsync(const struct UsbRequest *request);

+

发送异步请求

+

int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params);

+

填充请求

+

sint UsbCancelRequest(const struct UsbRequest *request);

+

取消异步请求

+

int UsbSubmitRequestSync(const struct UsbRequest *request);

+

发送同步请求

+

usb_raw_api.h

+

+

+

+

+

+

int UsbRawInit(struct UsbSession **session);

+

USB驱动开发工具包专家模式初始化

+

int UsbRawExit(const struct UsbSession *session);

+

USB驱动开发工具包专家模式退出

+

UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);

+

打开USB设备对象

+

int UsbRawCloseDevice(const UsbRawHandle *devHandle);

+

关闭USB设备对象

+

int UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData);

+

执行同步控制传输

+

int UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);

+

执行同步批量传输

+

int UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);

+

执行同步中断传输

+

int UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);

+

获取给定设备指定ID的设备配置描述符

+

void UsbRawFreeConfigDescriptor(const struct UsbRawConfigDescriptor *config);

+

释放配置描述符内存空间

+

int UsbRawGetConfiguration(const UsbRawHandle *devHandle, int *config);

+

获取当前激活配置

+

int UsbRawSetConfiguration(const UsbRawHandle *devHandle, int config);

+

设置当前激活配置

+

int UsbRawGetDescriptor(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawDescriptorParam *param, const unsigned char *data);

+

获取描述符信息

+

UsbRawDevice *UsbRawGetDevice(const UsbRawHandle *devHandle);

+

由设备句柄获取设备指针

+

int UsbRawGetDeviceDescriptor(const UsbRawDevice *rawDev, struct UsbDeviceDescriptor *desc);

+

获取给定设备的USB设备描述符

+

int UsbRawClaimInterface(const UsbRawHandle *devHandle, int interfaceNumber);

+

声明给定设备句柄上的接口

+

int UsbRawReleaseInterface(const UsbRawHandle *devHandle, int interfaceNumber);

+

释放之前声明的接口

+

int UsbRawResetDevice(const UsbRawHandle *devHandle);

+

复位设备

+

struct UsbRawRequest *UsbRawAllocRequest(const UsbRawHandle *devHandle, int isoPackets, int length);

+

分配一个带有指定数量的同步包描述符的传输请求

+

int UsbRawFreeRequest(const struct UsbRawRequest *request);

+

释放之前分配的传输请求

+

int UsbRawFillBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

填充批量传输请求所需信息

+

int UsbRawFillControlSetup(const unsigned char *setup, const struct UsbControlRequestData *requestData);

+

填充控制传输设置包所需信息

+

int UsbRawFillControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

填充控制传输请求所需信息

+

int UsbRawFillInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

填充中断传输请求所需信息

+

int UsbRawFillIsoRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

填充同步传输(Isochronous Transfers)请求所需信息

+

int UsbRawSubmitRequest(const struct UsbRawRequest *request);

+

提交一个传输请求

+

int UsbRawCancelRequest(const struct UsbRawRequest *request);

+

取消一个传输请求

+

int UsbRawHandleRequests(const UsbRawHandle *devHandle);

+

传输请求事件完成处理

+
+ +USB驱动模型Device侧开放的API接口功能,参考表2。 + +**表 2** USB驱动模型Device侧开放的API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

头文件

+

接口名称

+

功能描述

+

usbfn_device.h

+

+

+

const struct UsbFnDevice *UsbFnCreateDevice(const char *udcName, const struct UsbFnDescriptorData *descriptor);

+

创建Usb设备

+

int UsbFnRemoveDevice(struct UsbFnDevice *fnDevice);

+

删除Usb设备

+

const struct UsbFnDevice *UsbFnGetDevice(const char *udcName);

+

获取Usb设备

+

usbfn_interface.h

+

+

+

+

+

+

int UsbFnStartRecvInterfaceEvent(struct UsbFnInterface *interface, uint32_t eventMask, UsbFnEventCallback callback, void *context);

+

开始接受Event事件

+

int UsbFnStopRecvInterfaceEvent(struct UsbFnInterface *interface);

+

停止接受Event事件

+

UsbFnInterfaceHandle UsbFnOpenInterface(struct UsbFnInterface *interface);

+

打开一个接口

+

int UsbFnCloseInterface(UsbFnInterfaceHandle handle);

+

关闭一个接口

+

int UsbFnGetInterfacePipeInfo(struct UsbFnInterface *interface, uint8_t pipeId, struct UsbFnPipeInfo *info);

+

获取管道信息

+

int UsbFnSetInterfaceProp(const struct UsbFnInterface *interface, const char *name, const char *value);

+

设置自定义属性

+

usbfn_request.h

+

+

+

+

+

+

+

+

struct UsbFnRequest *UsbFnAllocCtrlRequest(UsbFnInterfaceHandle handle, uint32_t len);

+

申请一个控制请求

+

struct UsbFnRequest *UsbFnAllocRequest(UsbFnInterfaceHandle handle, uint8_t pipe, uint32_t len);

+

申请一个数据请求

+

int UsbFnFreeRequest(struct UsbFnRequest *req);

+

释放一个请求

+

int UsbFnSubmitRequestAsync(struct UsbFnRequest *req);

+

发送异步请求

+

int UsbFnSubmitRequestSync(struct UsbFnRequest *req, uint32_t timeout);

+

发送同步请求

+

int UsbFnCancelRequest(struct UsbFnRequest *req);

+

取消请求

+
+ +## 开发指导 + +USB驱动是基于HDF框架、PLATFORM和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同USB器件提供统一的驱动模型。本篇开发指导以串口为例,分别介绍USB Host和USB Device驱动开发。 + +### 开发步骤 + +### Host DDK API驱动开发步骤 + +1. 驱动匹配表配置。 +2. 初始化Host DDK。 +3. 待步骤2初始化完后获取UsbInterface接口对象。 +4. 打开步骤3获取到的UsbInterface接口对象,获取对应接口的UsbInterfaceHandle对象。 +5. 根据步骤4获取到的UsbInterfaceHandle对象,获取指定索引为pinpeIndex的pipeInfo信息。 +6. 为步骤4获取到的UsbInterfaceHandle预先分配待发送的IO Request对象。 +7. 根据输入参数params填充步骤6预先分配的IO Request。 +8. 提交IO Request对象,可以选择同步或异步两种模式。 + + +### Host RAW API驱动开发步骤 + +1. 驱动匹配表配置。 +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)。 +4. 接收Event事件(UsbFnInterfaceStartRecvEvent)如Enable、Setup等事件,回调函数(UsbFnEventCallback)中对Event事件做出响应。 +5. 收发数据,可以选择同步异步发送模式。 + +## 开发实例 + +本实例提供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]; + } + } + } +} + +#include "usb_serial.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "osal_time.h" +#include "securec.h" +#include "usb_interface.h" +#include "hdf_usb_pnp_manage.h" + +#define HDF_LOG_TAG USB_HOST_ACM +#define STR_LEN 512 + +static struct UsbRequest *g_syncRequest = NULL; +static struct UsbRequest *g_ctrlCmdRequest = NULL; +static bool g_acmReleaseFlag = false; +static uint8_t *g_acmReadBuffer = NULL; +... +static int SerialCtrlMsg(struct AcmDevice *acm, uint8_t request, + uint16_t value, void *buf, uint16_t len) +{ + int ret; + uint16_t index = acm->intPipe->interfaceId; + struct UsbControlParams controlParams = {}; + struct UsbRequestParams parmas = {}; + if (acm == NULL || buf == NULL) { + HDF_LOGE("%{public}s:invalid param", __func__); + return HDF_ERR_IO; + } + if (acm->ctrlReq == NULL) { + acm->ctrlReq = UsbAllocRequest(acm->ctrDevHandle, 0, len); + if (acm->ctrlReq == NULL) { + HDF_LOGE("%{public}s: UsbAllocRequest faild", __func__); + return HDF_ERR_IO; + } + } + + controlParams.request = request; + controlParams.target = USB_REQUEST_TARGET_INTERFACE; + controlParams.reqType = USB_REQUEST_TYPE_CLASS; + controlParams.directon = USB_REQUEST_DIR_TO_DEVICE; + controlParams.value = value; + controlParams.index = index; + controlParams.data = buf; + controlParams.size = len; + + parmas.interfaceId = USB_CTRL_INTERFACE_ID; + parmas.pipeAddress = acm->ctrPipe->pipeAddress; + parmas.pipeId = acm->ctrPipe->pipeId; + parmas.requestType = USB_REQUEST_PARAMS_CTRL_TYPE; + parmas.timeout = USB_CTRL_SET_TIMEOUT; + parmas.ctrlReq = UsbControlSetUp(&controlParams); + ret = UsbFillRequest(acm->ctrlReq, acm->ctrDevHandle, &parmas); + if (HDF_SUCCESS != ret) { + HDF_LOGE("%{public}s: faile, ret=%{public}d ", __func__, ret); + return ret; + } + ret = UsbSubmitRequestSync(acm->ctrlReq); //发送同步IO Request + if (HDF_SUCCESS != ret) { + HDF_LOGE("UsbSubmitRequestSync faile, ret=%{public}d ", ret); + return ret; + } + if (!acm->ctrlReq->compInfo.status) { + HDF_LOGE("%{public}s status=%{public}d ", __func__, acm->ctrlReq->compInfo.status); + } + return HDF_SUCCESS; +} +... +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接口对象 + return tmpIf; +} +... +static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm, + uint8_t interfaceIndex, UsbPipeType pipeType, UsbPipeDirection pipeDirection) +{ + uint8_t i; + int ret; + struct UsbInterfaceInfo *info = NULL; + UsbInterfaceHandle *interfaceHandle = NULL; + if (pipeType == USB_PIPE_TYPE_CONTROL) + { + info = &acm->ctrIface->info; + interfaceHandle = acm->ctrDevHandle; + } + else + { + info = &acm->iface[interfaceIndex]->info; + interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex); + } + + for (i = 0; i <= info->pipeNum; i++) { + struct UsbPipeInfo p; + ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);//获取指定索引为i的pipeInfo信息 + if (ret < 0) { + continue; + } + if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) { + struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi)); + if (pi == NULL) { + HDF_LOGE("%{public}s: Alloc pipe failed", __func__); + return NULL; + } + p.interfaceId = info->interfaceIndex; + *pi = p; + return pi; + } + } + return NULL; +} + +static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm, + UsbPipeType pipeType, UsbPipeDirection pipeDirection) +{ + uint8_t i; + if (acm == NULL) { + HDF_LOGE("%{public}s: invalid parmas", __func__); + return NULL; + } + for (i = 0; i < acm->interfaceCnt; i++) { + struct UsbPipeInfo *p = NULL; + if (!acm->iface[i]) { + continue; + } + p = EnumePipe(acm, i, pipeType, pipeDirection); + if (p == NULL) { + continue; + } + return p; + } + return NULL; +} + +/* HdfDriverEntry implementations */ +static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) +{ + struct UsbPnpNotifyServiceInfo *info = NULL; + 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; + } + if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { + HDF_LOGE("%s:%d OsalMutexInit fail", __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 faile 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: + if (OsalMutexDestroy(&acm->lock)) { + HDF_LOGE("%s:%d OsalMutexDestroy fail", __func__, __LINE__); + } +error: + OsalMemFree(acm); + acm = NULL; + return HDF_FAILURE; +} +... +static int AcmAllocReadRequests(struct AcmDevice *acm) +{ + int ret; + struct UsbRequestParams readParmas = {}; + for (int i = 0; i < ACM_NR; i++) { + acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize); //分配待发送的readReq IO Request对象 + if (!acm->readReq[i]) { + HDF_LOGE("readReq request faild\n"); + goto error; + } + readParmas.userData = (void *)acm; + readParmas.pipeAddress = acm->dataInPipe->pipeAddress; + readParmas.pipeId = acm->dataInPipe->pipeId; + readParmas.interfaceId = acm->dataInPipe->interfaceId; + readParmas.callback = AcmReadBulk; + readParmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE; + readParmas.timeout = USB_CTRL_SET_TIMEOUT; + readParmas.dataReq.numIsoPackets = 0; + readParmas.dataReq.directon = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1; + readParmas.dataReq.length = acm->readSize; + ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParmas); //填充待发送的readReq对象 + if (HDF_SUCCESS != ret) { + HDF_LOGE("%{public}s: UsbFillRequest faile, ret=%{public}d \n", __func__, ret); + goto error; + } + } + return HDF_SUCCESS; + +error: + AcmFreeReadRequests(acm); + return HDF_ERR_MALLOC_FAIL; +} + +static int AcmAllocNotifyRequest(struct AcmDevice *acm) +{ + int ret; + struct UsbRequestParams intParmas = {}; + acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize); //分配待发送的中断IO Request对象 + if (!acm->notifyReq) { + HDF_LOGE("notifyReq request fail\n"); + return HDF_ERR_MALLOC_FAIL; + } + intParmas.userData = (void *)acm; + intParmas.pipeAddress = acm->intPipe->pipeAddress; + intParmas.pipeId = acm->intPipe->pipeId; + intParmas.interfaceId = acm->intPipe->interfaceId; + intParmas.callback = AcmCtrlIrq; + intParmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE; + intParmas.timeout = USB_CTRL_SET_TIMEOUT; + intParmas.dataReq.numIsoPackets = 0; + intParmas.dataReq.directon = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK; + intParmas.dataReq.length = acm->intSize; + ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParmas); //填充预先分配的中断IO Request + if (HDF_SUCCESS != ret) { + HDF_LOGE("%{public}s: UsbFillRequest faile, ret=%{public}d \n", __func__, ret); + goto error; + } + return HDF_SUCCESS; + +error: + AcmFreeNotifyReqeust(acm); + return ret; +} + +static void AcmReleaseInterfaces(struct AcmDevice *acm) +{ + for (int i = 0; i < acm->interfaceCnt; i++) { + if (acm->iface[i]) { + UsbReleaseInterface(acm->iface[i]); + acm->iface[i] = NULL; + } + } + if (acm->ctrIface) { + UsbReleaseInterface(acm->ctrIface); + acm->ctrIface = NULL; + } +} + +static int32_t AcmClaimInterfaces(struct AcmDevice *acm) +{ + for (int i = 0; i < acm->interfaceCnt; i++) { + acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]); //获取UsbInterface接口对象 + if (acm->iface[i] == NULL) { + HDF_LOGE("%{public}s: interface%{public}d is null", __func__, acm->interfaceIndex[i]); + goto error; + } + } + + acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID); //获取控制接口对应的UsbInterface接口对象 + if (acm->ctrIface == NULL) { + HDF_LOGE("%{public}s: GetUsbInterfaceById null", __func__); + goto error; + } + + return HDF_SUCCESS; + + error: + AcmReleaseInterfaces(acm); + return HDF_FAILURE; +} + +static void AcmCloseInterfaces(struct AcmDevice *acm) +{ + for (int i = 0; i < acm->interfaceCnt; i++) { + if (acm->devHandle[i]) { + UsbCloseInterface(acm->devHandle[i]); + acm->devHandle[i] = NULL; + } + } + if (acm->ctrDevHandle) { + UsbCloseInterface(acm->ctrDevHandle); + acm->ctrDevHandle = NULL; + } +} + +static int32_t AcmOpenInterfaces(struct AcmDevice *acm) +{ + for (int i = 0; i < acm->interfaceCnt; i++) { + if (acm->iface[i]) { + acm->devHandle[i] = UsbOpenInterface(acm->iface[i]); //打开获取到的UsbInterface接口对象 + if (acm->devHandle[i] == NULL) { + HDF_LOGE("%{public}s: UsbOpenInterface null", __func__); + goto error; + } + } + } + acm->ctrDevHandle = UsbOpenInterface(acm->ctrIface); + if (acm->ctrDevHandle == NULL) { + HDF_LOGE("%{public}s: ctrDevHandle UsbOpenInterface null", __func__); + goto error; + } + + return HDF_SUCCESS; + +error: + 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信息 + 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信息 + 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信息 + 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信息 + if (acm->intPipe == NULL) { + HDF_LOGE("intPipe is NULL"); + goto error; + } + + acm->readSize = acm->dataInPipe->maxPacketSize; + acm->writeSize = acm->dataOutPipe->maxPacketSize; + acm->ctrlSize = acm->ctrPipe->maxPacketSize; + acm->intSize = acm->intPipe->maxPacketSize; + + return HDF_SUCCESS; + +error: + AcmFreePipes(acm); + return HDF_FAILURE; +} + +static void AcmFreeRequests(struct AcmDevice *acm) +{ + if (g_syncRequest != NULL) { + UsbFreeRequest(g_syncRequest); + g_syncRequest = NULL; + } + AcmFreeReadRequests(acm); + AcmFreeNotifyReqeust(acm); + AcmFreeWriteRequests(acm); + AcmWriteBufFree(acm); +} + +static int32_t AcmAllocRequests(struct AcmDevice *acm) +{ + int32_t ret; + + if (AcmWriteBufAlloc(acm) < 0) { + HDF_LOGE("%{public}s: AcmWriteBufAlloc failed", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + for (int 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对象 + snd->instance = acm; + if (snd->request == NULL) { + HDF_LOGE("%{public}s:%{public}d snd request fail", __func__, __LINE__); + goto error_alloc_write_req; + } + } + + ret = AcmAllocNotifyRequest(acm); //分配并填充中断IO Request对象 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s:%{public}d AcmAllocNotifyRequest fail", __func__, __LINE__); + goto error_alloc_int_req; + } + + ret = AcmAllocReadRequests(acm); //分配并填充readReq IO Request对象 + if (ret) { + HDF_LOGE("%{public}s:%{public}d AcmAllocReadRequests fail", __func__, __LINE__); + goto error_alloc_read_req; + } + + return HDF_SUCCESS; + +error_alloc_read_req: + AcmFreeNotifyReqeust(acm); +error_alloc_int_req: + AcmFreeWriteRequests(acm); +error_alloc_write_req: + AcmWriteBufFree(acm); + return HDF_FAILURE; +} + +static int32_t AcmInit(struct AcmDevice *acm) +{ + int32_t ret; + struct UsbSession *session = NULL; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d: initFlag is true", __func__, __LINE__); + return HDF_SUCCESS; + } + + ret = UsbInitHostSdk(NULL); //初始化Host DDK + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: UsbInitHostSdk faild", __func__); + return HDF_ERR_IO; + } + acm->session = session; + + ret = AcmClaimInterfaces(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmClaimInterfaces faild", __func__); + goto error_claim_interfaces; + } + + ret = AcmOpenInterfaces(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmOpenInterfaces faild", __func__); + goto error_open_interfaces; + } + + ret = AcmGetPipes(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmGetPipes failed", __func__); + goto error_get_pipes; + } + + ret = AcmAllocRequests(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmAllocRequests failed", __func__); + goto error_alloc_reqs; + } + + acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); + acm->lineCoding.bCharFormat = CHARFORMAT; + acm->lineCoding.bParityType = USB_CDC_NO_PARITY; + acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS; + acm->initFlag = true; + + HDF_LOGD("%{public}s:%{public}d========OK", __func__, __LINE__); + return HDF_SUCCESS; + +error_alloc_reqs: + AcmFreePipes(acm); +error_get_pipes: + AcmCloseInterfaces(acm); +error_open_interfaces: + AcmReleaseInterfaces(acm); +error_claim_interfaces: + UsbExitHostSdk(acm->session); + acm->session = NULL; + return ret; +} + +static void AcmRelease(struct AcmDevice *acm) +{ + if (acm->initFlag == false) { + HDF_LOGE("%{public}s:%{public}d: initFlag is false", __func__, __LINE__); + return; + } + + AcmFreeRequests(acm); + AcmFreePipes(acm); + AcmCloseInterfaces(acm); + AcmReleaseInterfaces(acm); + UsbExitHostSdk(acm->session); + acm->session = NULL; + + acm->initFlag = false; +} + +static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct AcmDevice *acm = NULL; + + if (device == NULL) { + HDF_LOGE("%{public}s: device is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + acm = (struct AcmDevice *)device->service; + OsalMutexInit(&acm->readLock); + OsalMutexInit(&acm->writeLock); + HDF_LOGD("%{public}s:%{public}d busNum=%{public}d,devAddr=%{public}d", \ + __func__, __LINE__, acm->busNum, acm->devAddr); + + ret = UsbSerialDeviceAlloc(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: Serial Device alloc faild", __func__); + } + + acm->initFlag = false; + g_acmReleaseFlag = false; + + HDF_LOGD("%{public}s:%{public}d init ok!", __func__, __LINE__); + + return ret; +} + +static void UsbSerialDriverRelease(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + + if (device == NULL) { + HDF_LOGE("%{public}s: device is NULL", __func__); + return; + } + acm = (struct AcmDevice *)device->service; + if (acm == NULL) { + HDF_LOGE("%{public}s: acm is null", __func__); + return; + } + + g_acmReleaseFlag = true; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d AcmRelease", __func__, __LINE__); + AcmRelease(acm); + } + UsbSeriaDevicelFree(acm); + OsalMutexDestroy(&acm->writeLock); + OsalMutexDestroy(&acm->readLock); + OsalMutexDestroy(&acm->lock); + OsalMemFree(acm); + acm = NULL; + HDF_LOGD("%{public}s:%{public}d exit", __func__, __LINE__); +} + +struct HdfDriverEntry g_usbSerialDriverEntry = { + .moduleVersion = 1, + .moduleName = "usbhost_acm", //驱动模块名称,必须与hcs文件中配置的名称一致 + .Bind = UsbSerialDriverBind, + .Init = UsbSerialDriverInit, + .Release = UsbSerialDriverRelease, +}; +HDF_INIT(g_usbSerialDriverEntry); +``` + +### Host RAW API驱动开发 + +``` +root { + module = "usb_pnp_device"; + usb_pnp_config { + match_attr = "usb_pnp_match"; + usb_pnp_device_id = "UsbPnpDeviceId"; + UsbPnpDeviceId { + idTableList = [ + "host_acm_rawapi_table" + ]; + host_acm_rawapi_table { //驱动配置匹配表信息 + //驱动模块名,该字段的值必须和驱动入口结构的moduleName一致 + moduleName = "usbhost_acm_rawapi"; + //驱动对外发布服务的名称,必须唯一 + serviceName = "usbhost_acm_rawapi_service"; + //驱动私有数据匹配关键字 + deviceMatchAttr = "usbhost_acm_rawapi_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]; + } + } + } +} + +#include "usb_serial_rawapi.h" +#include +#include "osal_mem.h" +#include "osal_time.h" +#include "securec.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "hdf_usb_pnp_manage.h" + +#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 +#define USB_RAW_IO_STOP_WAIT_MAX_TIME 3 + +static struct UsbRawRequest *g_syncRequest = NULL; +static UsbRawIoProcessStatusType g_stopIoStatus = USB_RAW_IO_PROCESS_RUNNING; +struct OsalMutex g_stopIoLock; +static bool g_rawAcmReleaseFlag = false; +...... + +static int UsbGetConfigDescriptor(UsbRawHandle *devHandle, struct UsbRawConfigDescriptor **config) +{ + UsbRawDevice *dev = NULL; + int activeConfig; + int ret; + + if (devHandle == NULL) { + HDF_LOGE("%{public}s:%{public}d devHandle is NULL", + __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + + ret = UsbRawGetConfiguration(devHandle, &activeConfig); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbRawGetConfiguration failed, ret=%{public}d", + __func__, __LINE__, ret); + return HDF_FAILURE; + } + HDF_LOGE("%{public}s:%{public}d activeConfig=%{public}d", __func__, __LINE__, activeConfig); + dev = UsbRawGetDevice(devHandle); + if (dev == NULL) { + HDF_LOGE("%{public}s:%{public}d UsbRawGetDevice failed", + __func__, __LINE__); + return HDF_FAILURE; + } + + ret = UsbRawGetConfigDescriptor(dev, activeConfig, config); + if (ret) { + HDF_LOGE("UsbRawGetConfigDescriptor failed, ret=%{public}d\n", ret); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} +... +static int UsbAllocWriteRequests(struct AcmDevice *acm) +{ + int i; + + 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("%{public}s: UsbRawAllocRequest faild", __func__); + return HDF_ERR_MALLOC_FAIL; + } + } + + return HDF_SUCCESS; +} +... +/* HdfDriverEntry implementations */ +static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + struct UsbPnpNotifyServiceInfo *info = NULL; + 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 fail", __func__, __LINE__); + goto error; + } + + info = (struct UsbPnpNotifyServiceInfo *)device->priv; + if (info != NULL) { + 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 faile 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: + if (OsalMutexDestroy(&acm->lock)) { + HDF_LOGE("%s:%d OsalMutexDestroy fail", __func__, __LINE__); + } +error: + OsalMemFree(acm); + acm = NULL; + return HDF_FAILURE; +} +... +static int UsbAllocReadRequests(struct AcmDevice *acm) +{ + struct UsbRawFillRequestData reqData; + int size = acm->dataInEp->maxPacketSize; + int ret; + + for (int i = 0; i < ACM_NR; i++) { + acm->readReq[i] = UsbRawAllocRequest(acm->devHandle, 0, size); + if (!acm->readReq[i]) { + HDF_LOGE("readReq request faild\n"); + return HDF_ERR_MALLOC_FAIL; + } + + reqData.endPoint = acm->dataInEp->addr; + reqData.numIsoPackets = 0; + reqData.callback = AcmReadBulkCallback; + reqData.userData = (void *)acm; + reqData.timeout = USB_CTRL_SET_TIMEOUT; + reqData.length = size; + + ret = UsbRawFillBulkRequest(acm->readReq[i], acm->devHandle, &reqData); + if (ret) { + HDF_LOGE("%{public}s: FillBulkRequest faile, ret=%{public}d \n", + __func__, ret); + return HDF_FAILURE; + } + } + + return HDF_SUCCESS; +} +... +static int UsbAllocNotifyRequest(struct AcmDevice *acm) +{ + struct UsbRawFillRequestData fillRequestData; + int size = acm->notifyEp->maxPacketSize; + int ret; + + acm->notifyReq = UsbRawAllocRequest(acm->devHandle, 0, size); + if (!acm->notifyReq) { + HDF_LOGE("notifyReq request fail\n"); + return HDF_ERR_MALLOC_FAIL; + } + + fillRequestData.endPoint = acm->notifyEp->addr; + fillRequestData.length = size; + fillRequestData.numIsoPackets = 0; + fillRequestData.callback = AcmNotifyReqCallback; + fillRequestData.userData = (void *)acm; + fillRequestData.timeout = USB_CTRL_SET_TIMEOUT; + + ret = UsbRawFillInterruptRequest(acm->notifyReq, acm->devHandle, &fillRequestData); + if (ret) { + HDF_LOGE("%{public}s: FillInterruptRequest faile, ret=%{public}d", __func__, ret); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} +... +static int32_t UsbSerialInit(struct AcmDevice *acm) +{ + struct UsbSession *session = NULL; + UsbRawHandle *devHandle = NULL; + int32_t ret; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d: initFlag is true", __func__, __LINE__); + return HDF_SUCCESS; + } + + ret = UsbRawInit(NULL); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbRawInit faild", __func__, __LINE__); + return HDF_ERR_IO; + } + acm->session = session; + + devHandle = UsbRawOpenDevice(session, acm->busNum, acm->devAddr); + if (devHandle == NULL) { + HDF_LOGE("%{public}s:%{public}d UsbRawOpenDevice faild", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_open_device; + } + acm->devHandle = devHandle; + ret = UsbGetConfigDescriptor(devHandle, &acm->config); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbGetConfigDescriptor faild", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_get_desc; + } + ret = UsbParseConfigDescriptor(acm, acm->config); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s:%{public}d UsbParseConfigDescriptor faild", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_parse_desc; + } + + ret = AcmWriteBufAlloc(acm); + if (ret < 0) { + HDF_LOGE("%{public}s:%{public}d AcmWriteBufAlloc faild", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_alloc_write_buf; + } + ret = UsbAllocWriteRequests(acm); + if (ret < 0) { + HDF_LOGE("%{public}s:%{public}d UsbAllocWriteRequests faild", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_alloc_write_reqs; + } + ret = UsbAllocNotifyRequest(acm); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbAllocNotifyRequests faild", __func__, __LINE__); + goto err_alloc_notify_req; + } + ret = UsbAllocReadRequests(acm); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbAllocReadRequests faild", __func__, __LINE__); + goto err_alloc_read_reqs; + } + ret = UsbStartIo(acm); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbAllocReadRequests faild", __func__, __LINE__); + goto err_start_io; + } + + acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); + acm->lineCoding.bCharFormat = CHARFORMAT; + acm->lineCoding.bParityType = USB_CDC_NO_PARITY; + acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS; + + ret = UsbRawSubmitRequest(acm->notifyReq); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbRawSubmitRequest failed", __func__, __LINE__); + goto err_submit_req; + } + + acm->initFlag = true; + + HDF_LOGD("%{public}s:%{public}d=========================OK", __func__, __LINE__); + + return HDF_SUCCESS; + +err_submit_req: + UsbStopIo(acm); +err_start_io: + UsbFreeReadRequests(acm); +err_alloc_read_reqs: + UsbFreeNotifyReqeust(acm); + err_alloc_notify_req: + UsbFreeWriteRequests(acm); +err_alloc_write_reqs: + AcmWriteBufFree(acm); +err_alloc_write_buf: + UsbReleaseInterfaces(acm); +err_parse_desc: + UsbRawFreeConfigDescriptor(acm->config); + acm->config = NULL; +err_get_desc: + (void)UsbRawCloseDevice(devHandle); +err_open_device: + UsbRawExit(acm->session); + + return ret; +} + +static void UsbSerialRelease(struct AcmDevice *acm) +{ + if (acm->initFlag == false) { + HDF_LOGE("%{public}s:%{public}d: initFlag is false", __func__, __LINE__); + return; + } + + /* stop io thread and release all resources */ + UsbStopIo(acm); + if (g_syncRequest != NULL) { + UsbRawFreeRequest(g_syncRequest); + g_syncRequest = NULL; + } + UsbFreeReadRequests(acm); + UsbFreeNotifyReqeust(acm); + UsbFreeWriteRequests(acm); + AcmWriteBufFree(acm); + (void)UsbRawCloseDevice(acm->devHandle); + UsbReleaseInterfaces(acm); + UsbRawFreeConfigDescriptor(acm->config); + acm->config = NULL; + UsbRawExit(acm->session); + + acm->initFlag = false; +} + +static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + int32_t ret; + + if (device == NULL) { + HDF_LOGE("%{public}s:%{public}d device is null", __func__, __LINE__); + return HDF_ERR_INVALID_OBJECT; + } + acm = (struct AcmDevice *)device->service; + OsalMutexInit(&acm->readLock); + OsalMutexInit(&acm->writeLock); + + ret = UsbSerialDeviceAlloc(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s:%{public}d UsbSerialDeviceAlloc faild", __func__, __LINE__); + } + + acm->initFlag = false; + g_rawAcmReleaseFlag = false; + + HDF_LOGD("%{public}s:%{public}d init ok!", __func__, __LINE__); + + return ret; +} + +static void UsbSerialDriverRelease(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + if (device == NULL) { + HDF_LOGE("%{public}s: device is NULL", __func__); + return; + } + + acm = (struct AcmDevice *)device->service; + if (acm == NULL) { + HDF_LOGE("%{public}s: acm is null", __func__); + return; + } + + g_rawAcmReleaseFlag = true; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d UsbSerialRelease", __func__, __LINE__); + UsbSerialRelease(acm); + } + UsbSeriaDevicelFree(acm); + OsalMutexDestroy(&acm->writeLock); + OsalMutexDestroy(&acm->readLock); + OsalMutexDestroy(&acm->lock); + OsalMemFree(acm); + acm = NULL; + HDF_LOGD("%{public}s:%{public}d exit", __func__, __LINE__); +} + +struct HdfDriverEntry g_usbSerialRawDriverEntry = { + .moduleVersion = 1, + .moduleName = "usbhost_acm_rawapi", //驱动模块名称,必须与hcs文件中配置的名称一致 + .Bind = UsbSerialDriverBind, + .Init = UsbSerialDriverInit, + .Release = UsbSerialDriverRelease, +}; +HDF_INIT(g_usbSerialRawDriverEntry); +``` + +### Device DDK API驱动开发 +USB ACM设备核心代码路径为drivers\peripheral\usb\gadget\function\acm\cdcacm.c,其使用示例如下所示,首先根据描述符创建设备,然后获取接口,打开接口,获取Pipe信息,接收Event事件,接着进行USB通信(读写等),设备卸载时候,关闭接口,停止Event接收,删除设备。 + +``` +1、创建设备 +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("%{public}s: create usb function device failed", __func__); + return HDF_FAILURE; + } + ... +} +2、获取接口,打开接口,获取Pipe信息 +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); + ... + } + 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); + ... + /* 打开接口 */ + handle = UsbFnInterfaceOpen(fnIface); + ... + } + return HDF_SUCCESS; +} +3、接收Event事件 +static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int 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通信(读写等) +static int32_t AcmSendNotifyRequest(struct UsbAcmDevice *acm, uint8_t type, + uint16_t value, void *data, uint32_t length) +{ +... +/* 异步发送 */ + ret = UsbFnRequestSubmitAsync(req); + ... +} +5、关闭接口,停止Event接收,删除设备 +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("%{public}s: remove usb function device failed", __func__); + } + return ret; +} +``` + diff --git "a/zh-cn/device-dev/driver/figure/USB-Device\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" "b/zh-cn/device-dev/driver/figure/USB-Device\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..d10900d14a777bc98d0aa7a74842ecdda98d3320 Binary files /dev/null and "b/zh-cn/device-dev/driver/figure/USB-Device\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figure/USB-Host\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" "b/zh-cn/device-dev/driver/figure/USB-Host\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..a36e8829aec7c6f1c37d92766547c9b8ebb620ba Binary files /dev/null and "b/zh-cn/device-dev/driver/figure/USB-Host\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" differ