鸿蒙OpenHarmony【外设驱动使用之USB】 子体系

打印 上一主题 下一主题

主题 805|帖子 805|积分 2415

USB

概述

功能简介

USB(Universal Serial Bus)通用串行总线,包含了主机端(Host)和设备端(Device)。主机端负责USB总线中的数据传输及端口管理,设备端则可以毗连各种外设,以是USB驱动开辟又分为主机端驱动开辟和设备端驱动开辟。
OpenHarmony体系USB模块支持USB业务的开辟,提供USB相干的功能,提供用户态第三方功能驱动的USB设备数据读写接口,以及提供创建和删除USB设备,接口的事件获取、打开和关闭等,管道同步异步读写通信,设置USB自界说属性等。
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驱动模型图



  • 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驱动模型图



  • SDK IF负责将USB设备按照设备、接口、管道进行逻辑划分,对配置管理、设备管理、IO管理进行封装。此模块还向开辟者提供了设备创建、获取接口、接收Event事件、收发数据等设备测驱动开辟的本领接口。
  • Configuration Manager负责剖析HCS文件描述的USB描述符信息,得到的USB描述符信息用于设备创建,同时模块还提供了自界说属性的读取、创建、删除、修改等利用。
  • Device Manager负责根据配置模块剖析USB描述符,并根据USB描述符创建立备。同时还负责获取设备、删除设备、获取设备状态,获取设备上面接口信息。
  • IO Manager负责数据的读写,包括Events事件、数据读写完成后事件的接收,支持同步和异步模式数据读写。
  • Adapter IF主要是对复合设备配置驱动及通用功能驱动设备节点利用进行封装,为上层提供同一的设备管理接口。
  • Adapter该模块由复合设备配置驱动及通用功能驱动提供。
开辟指导

由于内核态开辟USB驱动较复杂,需要开辟者对USB协议要有较深的了解才华很好的使用,对开辟者的要求相对较高。USB DDK的引入是为了让开辟者能在用户态更方便的开辟USB驱动。
场景介绍

USB Host DDK为开辟者提供了普通模式和专家模式,普通模式下,开辟者可通过USB DDK API直接完成相干USB数据读写利用,不需要过多关注底层的传输细节。专家模式下,开辟者通过USB RAW API直接访问OS平台中USB通道的接口,自界说实现更加复杂的功能。USB Device DDk为开辟者提供了管理USB设备、接口界说及USB数据哀求等功能。下文将介绍相干API。
接口说明

USB主机端驱动程序开辟相干接口(普通模式)如下
表1 USB主机端驱动程序开辟相干接口(普通模式)
接口名称功能描述int32_t UsbInitHostSdk(struct UsbSession **session);
USB主机端驱动开辟工具包初始化struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex)获取USB接口对象UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);
打开USB对象接口int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);
获取指定可选设置的管道信息struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int32_t isoPackets , int32_t length);分配哀求对象int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params);
添补哀求int32_t UsbSubmitRequestSync(const struct UsbRequest *request);发送同步哀求 USB主机端驱动程序开辟相干接口(专家模式)如下
表2 USB主机端驱动程序开辟相干接口(专家模式)
接口名称功能描述int32_t UsbRawInit(struct UsbSession **session);
USB驱动开辟工具包专家模式初始化UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);
打开USB设备对象int32_t UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData);实行同步控制传输int32_t UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);实行同步批量传输int32_t UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);实行同步停止传输int32_t UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);
获取给定设备指定ID的设备配置描述符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);添补同步传输(Isochronous Transfers)哀求所需信息int32_t UsbRawSubmitRequest(const struct UsbRawRequest *request);提交一个传输哀求int32_t UsbRawCancelRequest(const struct UsbRawRequest *request);取消一个传输哀求int32_t UsbRawHandleRequests(const UsbRawHandle *devHandle);传输哀求事件完成处理 USB设备端用于管理USB设备的相干接口如下
表3 USB设备端用于管理USB设备的相干接口
接口名称功能描述const struct UsbFnDevice *UsbFnCreateDevice(const char *udcName, const struct UsbFnDescriptorData *descriptor);创建USB设备int32_t UsbFnRemoveDevice(struct UsbFnDevice *fnDevice);删除USB设备const struct UsbFnDevice *UsbFnGetDevice(const char *udcName);获取USB设备 USB设备端用于USB接口界说的相干接口如下
表4 USB设备端用于USB接口界说的相干接口
接口名称功能描述int32_t UsbFnStartRecvInterfaceEvent(struct UsbFnInterface *interface, uint32_t eventMask, UsbFnEventCallback callback, void *context);开始接受Event事件int32_t UsbFnStopRecvInterfaceEvent(struct UsbFnInterface *interface);停止接受Event事件UsbFnInterfaceHandle UsbFnOpenInterface(struct UsbFnInterface *interface);打开一个接口int32_t UsbFnCloseInterface(UsbFnInterfaceHandle handle);关闭一个接口int32_t UsbFnGetInterfacePipeInfo(struct UsbFnInterface *interface, uint8_t pipeId, struct UsbFnPipeInfo *info);获取管道信息int32_t UsbFnSetInterfaceProp(const struct UsbFnInterface *interface, const char *name, const char *value);设置自界说属性 USB设备端用于管理USB数据哀求的相干接口如下
表5 USB设备端用于管理USB数据哀求的相干接口
接口名称功能描述struct UsbFnRequest *UsbFnAllocCtrlRequest(UsbFnInterfaceHandle handle, uint32_t len);申请一个控制哀求struct UsbFnRequest *UsbFnAllocRequest(UsbFnInterfaceHandle handle, uint8_t pipe, uint32_t len);申请一个数据哀求int32_t UsbFnFreeRequest(struct UsbFnRequest *req);开释一个哀求int32_t UsbFnSubmitRequestAsync(struct UsbFnRequest *req);发送异步哀求int32_t UsbFnSubmitRequestSync(struct UsbFnRequest *req, uint32_t timeout);发送同步哀求int32_t UsbFnCancelRequest(struct UsbFnRequest *req);取消哀求 开辟步骤

USB驱动基于HDF框架、Platform和OSAL基础接口进行开辟,不区分利用体系和芯片平台,为不同USB器件提供同一的驱动模型。此处以串口为例,分别介绍USB Host和USB Device驱动开辟的详细过程。
Host DDK API驱动开辟


  • 在设备私有数据HCS中配置,完成主机端驱动总体信息的配置,具体如下:
    1. root {
    2.     module = "usb_pnp_device";
    3.     usb_pnp_config {
    4.         match_attr = "usb_pnp_match";
    5.         usb_pnp_device_id = "UsbPnpDeviceId";
    6.         UsbPnpDeviceId {
    7.             idTableList = [
    8.                 "host_acm_table"
    9.             ];
    10.             host_acm_table {
    11.                 // 驱动模块名,该字段的值必须和驱动入口结构的moduleName一致
    12.                 moduleName = "usbhost_acm";
    13.                 // 驱动对外发布服务的名称,必须唯一
    14.                 serviceName = "usbhost_acm_pnp_service";
    15.                 // 驱动私有数据匹配关键字
    16.                 deviceMatchAttr = "usbhost_acm_pnp_matchAttr";
    17.                 // 从该字段开始(包含该字段)之后数据长度,以byte为单位
    18.                 length = 21;
    19.                 // USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber
    20.                 matchFlag = 0x0303;
    21.                 // 厂商编号
    22.                 vendorId = 0x12D1;
    23.                 // 产品编号
    24.                 productId = 0x5000;
    25.                 // 设备出厂编号,低16位
    26.                 bcdDeviceLow = 0x0000;
    27.                 // 设备出厂编号,高16位
    28.                 bcdDeviceHigh = 0x0000;
    29.                 // USB分配的设备类代码
    30.                 deviceClass = 0;
    31.                 // USB分配的子类代码
    32.                 deviceSubClass = 0;
    33.                 // USB分配的设备协议代码
    34.                 deviceProtocol = 0;
    35.                 // 接口类型,根据实际需要可填写多个
    36.                 interfaceClass = [0];
    37.                 // 接口子类型,根据实际需要可填写多个
    38.                 interfaceSubClass = [2, 0];
    39.                 // 接口所遵循的协议,根据实际需要可填写多个   
    40.                 interfaceProtocol = [1, 2];
    41.                 // 接口的编号,根据实际需要可填写多个
    42.                 interfaceNumber = [2, 3];
    43.             }
    44.         }
    45.     }
    46. }
    复制代码
  • USB主机端驱动开辟工具包初始化。
    1. int32_t UsbInitHostSdk(struct UsbSession **session);
    复制代码
  • 步骤2初始化完后获取UsbInterface对象。
    1. const struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex);
    复制代码
  • 打开步骤3获取到的UsbInterface接口对象,获取相应接口的UsbInterfaceHandle对象。
    1. UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);
    复制代码
  • 根据步骤4获取到的UsbInterfaceHandle对象,获取指定索引为pipeIndex的pipeInfo信息。
    1. int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);
    复制代码
  • 为步骤4获取到的UsbInterfaceHandle预先分配待发送的IO Request对象。
    1. struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int32_t isoPackets, int32_t length);
    复制代码
  • 根据输入参数params添补步骤6预先分配的IO Request。
    1. int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params);
    复制代码
  • 提交IO Request对象,可以选择同步或异步两种模式。
    1. int32_t UsbSubmitRequestSync(const struct UsbRequest *request); //发送同步IO请求
    2. int32_t UsbSubmitRequestAsync(const struct UsbRequest *request); //发送异步IO请求
    复制代码
Host RAW API驱动开辟


  • 同Host DDK API的步骤1一样,在设备私有数据HCS中配置。
  • 初始化Host RAW,并打开USB设备,然后获取描述符,通过描述符获取接口、端点信息。
    1. int32_t UsbRawInit(struct UsbSession **session);
    复制代码
  • 待步骤2完成后打开USB设备。
    1. UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);
    复制代码
  • 待步骤3完成后获取描述符,通过描述符获取接口、端点信息。
    1. int32_t UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);
    复制代码
  • 分配Request,并根据传输范例使用相应接口对Request进行添补。
    1. int32_t UsbRawFillBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于批量传输的请求
    2. int32_t UsbRawFillControlSetup(const unsigned char *setup, const struct UsbControlRequestData *requestData);
    3. int32_t UsbRawFillControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于控制传输的请求
    4. int32_t UsbRawFillInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于中断传输的请求
    5. int32_t UsbRawFillIsoRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // 填充用于同步传输的请求
    复制代码
  • 提交IO Request对象,可以选择同步或异步两种模式。
    1. int32_t UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData); //发送同步USB控制传输请求
    2. int32_t UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData); //发送同步USB批量传输请求
    3. int32_t UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData); //发送同步执行USB中断传输请求
    4. int32_t UsbRawSubmitRequest(const struct UsbRawRequest *request); //提交异步IO请求
    复制代码
Device DDK API驱动开辟


  • 在设备功能代码中构造描述符。
    1. static struct UsbFnFunction g_acmFunction = {
    2.     .funcName = "f_generic.a",                     //功能名称
    3.     .strings = g_acmStrings,                       //字符串
    4.     .fsDescriptors = g_acmFsFunction,              //初始化fs描述符
    5.     .hsDescriptors = g_acmHsFunction,              //初始化hs描述符
    6.     .ssDescriptors = g_acmSsFunction,              //初始化ss描述符
    7.     .sspDescriptors = nullptr,                     //ss描述符置空
    8. };
    9. struct UsbFnFunction *g_functions[] = {
    10. #ifdef CDC_ECM
    11.     &g_ecmFunction,
    12. #endif
    13. #ifdef CDC_ACM
    14.     &g_acmFunction,
    15. #endif
    16.     nullptr};
    17. static struct UsbFnConfiguration g_masterConfig = { // 配置描述符
    18.     .configurationValue = 1,
    19.     .iConfiguration     = USB_FUNC_CONFIG_IDX,
    20.     .attributes         = USB_CFG_BUS_POWERED,
    21.     .maxPower           = POWER,
    22.     .functions          = g_functions,
    23. };
    24. static struct UsbFnConfiguration *g_configs[] = {
    25.     &g_masterConfig,
    26.     nullptr,
    27. };
    28. static struct UsbDeviceDescriptor g_cdcUsbFnDeviceDesc = { // 设备描述符
    29.     .bLength            = sizeof(g_cdcUsbFnDeviceDesc),
    30.     .bDescriptorType    = USB_DDK_DT_DEVICE,
    31.     .bcdUSB             = CpuToLe16(BCD_USB),
    32.     .bDeviceClass       = 0,
    33.     .bDeviceSubClass    = 0,
    34.     .bDeviceProtocol    = 0,
    35.     .bMaxPacketSize0    = USB_MAX_PACKET_SIZE,
    36.     .idVendor           = CpuToLe16(DEVICE_VENDOR_ID),
    37.     .idProduct          = CpuToLe16(DEVICE_PRODUCT_ID),
    38.     .bcdDevice          = CpuToLe16(DEVICE_VERSION),
    39.     .iManufacturer      = USB_FUNC_MANUFACTURER_IDX,
    40.     .iProduct           = USB_FUNC_PRODUCT_IDX,
    41.     .iSerialNumber      = USB_FUNC_SERIAL_IDX,
    42.     .bNumConfigurations = 1,
    43. };
    44. struct UsbFnDeviceDesc g_acmFnDevice = { //描述符入口
    45.     .deviceDesc = &g_cdcUsbFnDeviceDesc,
    46.     .deviceStrings = g_devStrings,
    47.     .configs = g_configs,
    48. };
    复制代码
  • 创建立备。描述符构造完成后,使用UsbFnDeviceCreate函数创建一个USB设备,并传入UDC控制器和UsbFnDescriptorData结构体。
    1. if (useHcs == 0) { // 使用代码编写的描述符
    2.     descData.type = USBFN_DESC_DATA_TYPE_DESC;
    3.     descData.descriptor = &g_acmFnDevice;
    4. } else {             // 使用hcs编写的描述符
    5.     devMgr->descData.type = USBFN_DESC_DATA_TYPE_PROP;
    6.     devMgr->descData.property = device->property;
    7. }
    8. // 创建设备
    9. fnDev = (struct UsbFnDevice *)UsbFnCreateDevice(devMgr->udcName, &devMgr->descData);
    复制代码
  • 设备创建后,使用UsbFnGetInterface函数获取UsbInterface接口对象,并通过UsbFnGetInterfacePipeInfo函数获取USB管道信息。
    1. // 获取接口
    2. fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
    3. // 获取Pipe信息
    4. UsbFnGetInterfacePipeInfo(fnIface, i, &pipeInfo);
    5. // 获取Handle
    6. handle = UsbFnOpenInterface(fnIface);
    7. // 获取控制(EP0)Request
    8. req = UsbFnAllocCtrlRequest(acmDevice->ctrlIface.handle, sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
    9. // 获取Request
    10. req = UsbFnAllocCtrlRequest(acmDevice->ctrlIface.handle, sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
    复制代码
  • 通过UsbFnStartRecvInterfaceEvent函数接收Event事件,并通过UsbFnEventCallback回调函数对Event事件做出响应。
    1. // 开始接收Event事件
    2. ret = UsbFnStartRecvInterfaceEvent(acmDevice->ctrlIface.fn, 0xff, AcmEventCallback, acmDevice);
    3. // Event处理回调函数
    4. static void UsbAcmEventCallback(struct UsbFnEvent *event)
    5. {
    6.     struct UsbAcmDevice *acm = NULL;
    7.     if (event == NULL || event->context == NULL) {
    8.         HDF_LOGE("%{public}s: event is null", __func__);
    9.         return;
    10.     }
    11.     acm = (struct UsbAcmDevice *)event->context;
    12.     switch (event->type) {
    13.         case USBFN_STATE_BIND:
    14.             HDF_LOGI("%{public}s: receive bind event", __func__);
    15.             break;
    16.         case USBFN_STATE_UNBIND:
    17.             HDF_LOGI("%{public}s: receive unbind event", __func__);
    18.             break;
    19.         case USBFN_STATE_ENABLE:
    20.             HDF_LOGI("%{public}s: receive enable event", __func__);
    21.             AcmEnable(acm);
    22.             break;
    23.         case USBFN_STATE_DISABLE:
    24.             HDF_LOGI("%{public}s: receive disable event", __func__);
    25.             AcmDisable(acm);
    26.             acm->enableEvtCnt = 0;
    27.             break;
    28.         case USBFN_STATE_SETUP:
    29.             HDF_LOGI("%{public}s: receive setup event", __func__);
    30.             if (event->setup != NULL) {
    31.                 AcmSetup(acm, event->setup);
    32.             }
    33.             break;
    34.         case USBFN_STATE_SUSPEND:
    35.             HDF_LOGI("%{public}s: receive suspend event", __func__);
    36.             AcmSuspend(acm);
    37.             break;
    38.         case USBFN_STATE_RESUME:
    39.             HDF_LOGI("%{public}s: receive resume event", __func__);
    40.             AcmResume(acm);
    41.             break;
    42.         default:
    43.             break;
    44.     }
    45. }
    复制代码
  • 收发数据,可以选择同步异步发送模式。
    1. notify = (struct UsbCdcNotification *)req->buf;
    2. ...
    3. ret = memcpy_s((void *)(notify + 1), length, data, length);
    4. if (ret != EOK) {
    5.     HDF_LOGE("%s: memcpy_s failed", __func__);
    6.     return HDF_FAILURE;
    7. }
    8. ret = UsbFnSubmitRequestAsync(req); // 异步发送
    9. if (ret != HDF_SUCCESS) {
    10.     HDF_LOGE("%s: send notify request failed", __func__);
    11.     acm->notifyReq = req;
    12. }
    复制代码
开辟实例

本实例提供USB串口驱动开辟示例,并简要对具体关键点进行开辟说明。
Host DDK API驱动开辟

  1. #include "usb_serial.h"
  2. #include "hdf_base.h"
  3. #include "hdf_log.h"
  4. #include "hdf_usb_pnp_manage.h"
  5. #include "osal_mem.h"
  6. #include "osal_time.h"
  7. #include "securec.h"
  8. #include "usb_ddk_interface.h"
  9. #define HDF_LOG_TAG USB_HOST_ACM
  10. #define STR_LEN     512
  11. static struct UsbRequest *g_syncRequest = NULL;  // 定义一个USB请求
  12. static struct UsbRequest *g_ctrlCmdRequest = NULL;
  13. static bool g_acmReleaseFlag = false;
  14. static uint8_t *g_acmReadBuffer = NULL;
  15. ...
  16. static int32_t SerialCtrlMsg(struct AcmDevice *acm, uint8_t request, uint16_t value, void *buf, uint16_t len)
  17. {
  18.     int32_t ret;
  19.     if (acm == NULL || buf == NULL || acm->intPipe == NULL) {
  20.         HDF_LOGE("%s:invalid param", __func__);
  21.         return HDF_ERR_IO;
  22.     }
  23.     uint16_t index = acm->intPipe->interfaceId;
  24.     struct UsbControlParams controlParams = {};
  25.     struct UsbRequestParams parmas = {}; // 定义一个USB请求参数对象
  26.     if (acm->ctrlReq == NULL) {
  27.         // 为获取到的UsbInterfaceHandle预先分配待发送的IO Request对象
  28.         acm->ctrlReq = UsbAllocRequest(acm->ctrDevHandle, 0, len);
  29.         if (acm->ctrlReq == NULL) {
  30.             HDF_LOGE("%s: UsbAllocRequest failed", __func__);
  31.             return HDF_ERR_IO;
  32.         }
  33.     }
  34.     controlParams.request = request;
  35.     controlParams.target = USB_REQUEST_TARGET_INTERFACE; // 接口对象
  36.     controlParams.reqType = USB_REQUEST_TYPE_CLASS; // 请求类型
  37.     controlParams.directon = USB_REQUEST_DIR_TO_DEVICE; // 从主机到设备的数据传输
  38.     controlParams.value = value;
  39.     controlParams.index = index;
  40.     controlParams.data = buf;
  41.     controlParams.size = len;
  42.     parmas.interfaceId = USB_CTRL_INTERFACE_ID; // 定义USB控制接口的默认ID
  43.     if (acm->ctrPipe != NULL) {
  44.         parmas.pipeAddress = acm->ctrPipe->pipeAddress;
  45.         parmas.pipeId = acm->ctrPipe->pipeId;
  46.     }
  47.     parmas.requestType = USB_REQUEST_PARAMS_CTRL_TYPE; // 控制类型
  48.     parmas.timeout = USB_CTRL_SET_TIMEOUT; // 设置超时时间
  49.     parmas.ctrlReq = UsbControlSetUp(&controlParams);
  50.     parmas.callback = NULL;
  51.     // 根据params填充预先分配的IO Request
  52.     ret = UsbFillRequest(acm->ctrlReq, acm->ctrDevHandle, &parmas);
  53.     if (ret != HDF_SUCCESS) {
  54.         HDF_LOGE("%s: UsbFillRequest failed, ret = %d ", __func__, ret);
  55.         return ret;
  56.     }
  57.     // 发送同步IO Request
  58.     ret = UsbSubmitRequestSync(acm->ctrlReq);
  59.     if (ret != HDF_SUCCESS) {
  60.         HDF_LOGE("UsbSubmitRequestSync failed, ret = %d ", ret);
  61.         return ret;
  62.     }
  63.     if (!acm->ctrlReq->compInfo.status) {
  64.         HDF_LOGE("%s  status=%d ", __func__, acm->ctrlReq->compInfo.status);
  65.     }
  66.     return HDF_SUCCESS;
  67. }
  68. ...
  69. static struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm, uint8_t interfaceIndex)
  70. {
  71.     // 获取UsbInterface接口对象
  72.     return UsbClaimInterface(acm->session, acm->busNum, acm->devAddr, interfaceIndex);
  73. }
  74. ...
  75. static struct UsbPipeInfo *EnumePipe(
  76.     const struct AcmDevice *acm, uint8_t interfaceIndex, UsbPipeType pipeType, UsbPipeDirection pipeDirection)
  77. {
  78.     struct UsbInterfaceInfo *info = NULL; // 定义一个USB接口信息对象
  79.     UsbInterfaceHandle *interfaceHandle = NULL; // 定义一个USB接口操作句柄,就是void *类型
  80.     if (pipeType == USB_PIPE_TYPE_CONTROL) {
  81.         info = &acm->ctrIface->info;
  82.         interfaceHandle = acm->ctrDevHandle;
  83.     } else {
  84.         // 根据interfaceIndex获取设备句柄
  85.         info = &acm->iface[interfaceIndex]->info;
  86.         interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex);
  87.     }
  88.     for (uint8_t i = 0; i <= info->pipeNum; i++) {
  89.         struct UsbPipeInfo p;
  90.         // 获取指定索引为i的pipeInfo信息
  91.         int32_t ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);
  92.         if (ret < 0) {
  93.             continue;
  94.         }
  95.         if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) {
  96.             struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi)); // 开辟内存并初始化
  97.             if (pi == NULL) {
  98.                 HDF_LOGE("%s: Alloc pipe failed", __func__);
  99.                 return NULL;
  100.             }
  101.             p.interfaceId = info->interfaceIndex;
  102.             *pi = p;
  103.             return pi;
  104.         }
  105.     }
  106.     return NULL;
  107. }
  108. static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm, UsbPipeType pipeType, UsbPipeDirection pipeDirection)
  109. {
  110.     uint8_t i;
  111.     if (acm == NULL) {
  112.         HDF_LOGE("%s: invalid param", __func__);
  113.         return NULL;
  114.     }
  115.     for (i = 0; i < acm->interfaceCnt; i++) {
  116.         struct UsbPipeInfo *p = NULL;
  117.         if (!acm->iface[i]) {
  118.             continue;
  119.         }
  120.         // 获取控制pipe的pipeInfo信息
  121.         p = EnumePipe(acm, i, pipeType, pipeDirection);
  122.         if (p == NULL) {
  123.             continue;
  124.         }
  125.         return p;
  126.     }
  127.     return NULL;
  128. }
  129. /* HdfDriverEntry implementations */
  130. static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device)
  131. {
  132.     struct UsbPnpNotifyServiceInfo *info = NULL;
  133.     errno_t err;
  134.     struct AcmDevice *acm = NULL;
  135.     if (device == NULL) {
  136.         HDF_LOGE("%s: device is null", __func__);
  137.         return HDF_ERR_INVALID_OBJECT;
  138.     }
  139.     //开辟内存空间
  140.     acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm));
  141.     if (acm == NULL) {
  142.         HDF_LOGE("%s: Alloc usb serial device failed", __func__);
  143.         return HDF_FAILURE;
  144.     }
  145.     // 初始化互斥锁,&acm->lock表示指向互斥量的指针
  146.     if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) {
  147.         HDF_LOGE("%s:%d OsalMutexInit failed", __func__, __LINE__);
  148.         goto ERROR;
  149.     }
  150.     info = (struct UsbPnpNotifyServiceInfo *)device->priv;
  151.     if (info != NULL) {
  152.         HDF_LOGD("%s:%d busNum=%d,devAddr=%d,interfaceLength=%d", __func__, __LINE__, info->busNum, info->devNum,
  153.             info->interfaceLength);
  154.         acm->busNum = (uint8_t)info->busNum;
  155.         acm->devAddr = (uint8_t)info->devNum;
  156.         acm->interfaceCnt = info->interfaceLength;
  157.         err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, (const void *)info->interfaceNumber,
  158.             info->interfaceLength);
  159.         if (err != EOK) {
  160.             HDF_LOGE("%s:%d memcpy_s failed err = %d", __func__, __LINE__, err);
  161.             goto LOCK_ERROR;
  162.         }
  163.     } else {
  164.         HDF_LOGE("%s:%d info is null!", __func__, __LINE__);
  165.         goto LOCK_ERROR;
  166.     }
  167.     acm->device = device;
  168.     device->service = &(acm->service);
  169.     acm->device->service->Dispatch = UsbSerialDeviceDispatch;
  170.     HDF_LOGD("UsbSerialDriverBind=========================OK");
  171.     return HDF_SUCCESS;
  172. LOCK_ERROR:
  173.     if (OsalMutexDestroy(&acm->lock)) {
  174.         HDF_LOGE("%s:%d OsalMutexDestroy failed", __func__, __LINE__);
  175.     }
  176. ERROR:
  177.     OsalMemFree(acm);
  178.     acm = NULL;
  179.     return HDF_FAILURE;
  180. }
  181. ...
  182. static int32_t AcmAllocReadRequests(struct AcmDevice *acm)
  183. {
  184.     int32_t ret;
  185.     struct UsbRequestParams readParmas = {};
  186.     for (int32_t i = 0; i < ACM_NR; i++) {
  187.         // 分配待发送的readReq IO Request对象
  188.         acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize);
  189.         if (!acm->readReq[i]) {
  190.             HDF_LOGE("readReq request failed\n");
  191.             goto ERROR;
  192.         }
  193.         readParmas.userData = (void *)acm;
  194.         readParmas.pipeAddress = acm->dataInPipe->pipeAddress;
  195.         readParmas.pipeId = acm->dataInPipe->pipeId;
  196.         readParmas.interfaceId = acm->dataInPipe->interfaceId;
  197.         readParmas.callback = AcmReadBulk;
  198.         readParmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE; /* Data type */
  199.         readParmas.timeout = USB_CTRL_SET_TIMEOUT;
  200.         readParmas.dataReq.numIsoPackets = 0;
  201.         readParmas.dataReq.directon = (((uint8_t)acm->dataInPipe->pipeDirection) >> USB_PIPE_DIR_OFFSET) & 0x1;
  202.         readParmas.dataReq.length = (int)acm->readSize;
  203.         // 根据readParams填充预先分配待发送的readReq IO Request对象
  204.         ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParmas);
  205.         if (ret != HDF_SUCCESS) {
  206.             HDF_LOGE("%s: UsbFillRequest failed, ret=%d \n", __func__, ret);
  207.             goto ERROR;
  208.         }
  209.     }
  210.     return HDF_SUCCESS;
  211. ERROR:
  212.     AcmFreeReadRequests(acm);
  213.     return HDF_ERR_MALLOC_FAIL;
  214. }
  215. static int32_t AcmAllocNotifyRequest(struct AcmDevice *acm)
  216. {
  217.     int32_t ret;
  218.     struct UsbRequestParams intParmas = {};
  219.     // 分配待发送的中断IO Request对象
  220.     acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize);
  221.     if (!acm->notifyReq) {
  222.         HDF_LOGE("notifyReq request failed.\n");
  223.         return HDF_ERR_MALLOC_FAIL;
  224.     }
  225.     intParmas.userData = (void *)acm;
  226.     intParmas.pipeAddress = acm->intPipe->pipeAddress;
  227.     intParmas.pipeId = acm->intPipe->pipeId;
  228.     intParmas.interfaceId = acm->intPipe->interfaceId;
  229.     intParmas.callback = AcmCtrlIrq;
  230.     intParmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE;
  231.     intParmas.timeout = USB_CTRL_SET_TIMEOUT;
  232.     intParmas.dataReq.numIsoPackets = 0;
  233.     intParmas.dataReq.directon = (((uint8_t)acm->intPipe->pipeDirection) >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK;
  234.     intParmas.dataReq.length = (int)acm->intSize;
  235.     // 填充预先分配的中断IO Request
  236.     ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParmas);
  237.     if (ret != HDF_SUCCESS) {
  238.         HDF_LOGE("%s: UsbFillRequest failed, ret = %d", __func__, ret);
  239.         goto ERROR;
  240.     }
  241.     return HDF_SUCCESS;
  242. ERROR:
  243.     AcmFreeNotifyReqeust(acm);
  244.     return ret;
  245. }
  246. static void AcmReleaseInterfaces(struct AcmDevice *acm)
  247. {
  248.     for (uint8_t i = 0; i < acm->interfaceCnt; i++) {
  249.         if (acm->iface[i]) {
  250.             // 释放一个USB接口对象
  251.             UsbReleaseInterface(acm->iface[i]);
  252.             acm->iface[i] = NULL;
  253.         }
  254.     }
  255.     if (acm->ctrIface) {
  256.         UsbReleaseInterface(acm->ctrIface);
  257.         acm->ctrIface = NULL;
  258.     }
  259. }
  260. static int32_t AcmClaimInterfaces(struct AcmDevice *acm)
  261. {
  262.     for (uint8_t i = 0; i < acm->interfaceCnt; i++) {
  263.         // 获取UsbInterface接口对象
  264.         acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]);
  265.         if (acm->iface[i] == NULL) {
  266.             HDF_LOGE("%s: interface%d is null", __func__, acm->interfaceIndex[i]);
  267.             goto ERROR;
  268.         }
  269.     }
  270.         // 获取控制接口对应的UsbInterface接口对象
  271.     acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID);
  272.     if (acm->ctrIface == NULL) {
  273.         HDF_LOGE("%s: GetUsbInterfaceById null", __func__);
  274.         goto ERROR;
  275.     }
  276.     return HDF_SUCCESS;
  277. ERROR:
  278.     // 根据acm->interfaceCnt循环释放接口对象
  279.     AcmReleaseInterfaces(acm);
  280.     return HDF_FAILURE;
  281. }
  282. static void AcmCloseInterfaces(struct AcmDevice *acm)
  283. {
  284.     for (uint8_t i = 0; i < acm->interfaceCnt; i++) {
  285.         if (acm->devHandle[i]) {
  286.             // 关闭一个USB设备对象
  287.             UsbCloseInterface(acm->devHandle[i]);
  288.             acm->devHandle[i] = NULL;
  289.         }
  290.     }
  291.     if (acm->ctrDevHandle) {
  292.         UsbCloseInterface(acm->ctrDevHandle);
  293.         acm->ctrDevHandle = NULL;
  294.     }
  295. }
  296. static int32_t AcmOpenInterfaces(struct AcmDevice *acm)
  297. {
  298.     for (uint8_t i = 0; i < acm->interfaceCnt; i++) {
  299.         if (acm->iface[i]) {
  300.             // 打开获取到的UsbInterface接口对象
  301.             acm->devHandle[i] = UsbOpenInterface(acm->iface[i]);
  302.             if (acm->devHandle[i] == NULL) {
  303.                 HDF_LOGE("%s: UsbOpenInterface null", __func__);
  304.                 goto ERROR;
  305.             }
  306.         }
  307.     }
  308.     acm->ctrDevHandle = UsbOpenInterface(acm->ctrIface);
  309.     if (acm->ctrDevHandle == NULL) {
  310.         HDF_LOGE("%s: ctrDevHandle UsbOpenInterface null", __func__);
  311.         goto ERROR;
  312.     }
  313.     return HDF_SUCCESS;
  314. ERROR:
  315.     // 关闭所有UsbInterface接口对象
  316.     AcmCloseInterfaces(acm);
  317.     return HDF_FAILURE;
  318. }
  319. static int32_t AcmGetPipes(struct AcmDevice *acm)
  320. {
  321.     // 获取dataInPipe的pipeInfo信息
  322.     acm->dataInPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN);
  323.     if (acm->dataInPipe == NULL) {
  324.         HDF_LOGE("dataInPipe is null");
  325.         goto ERROR;
  326.     }
  327.         // 获取dataOutPipe的pipeInfo信息
  328.     acm->dataOutPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT);
  329.     if (acm->dataOutPipe == NULL) {
  330.         HDF_LOGE("dataOutPipe is null");
  331.         goto ERROR;
  332.     }
  333.         // 获取控制pipe的pipeInfo信息
  334.     acm->ctrPipe = EnumePipe(acm, acm->ctrIface->info.interfaceIndex, USB_PIPE_TYPE_CONTROL, USB_PIPE_DIRECTION_OUT);
  335.     if (acm->ctrPipe == NULL) {
  336.         HDF_LOGE("ctrPipe is null");
  337.         goto ERROR;
  338.     }
  339.     // 获取中断pipe的pipeInfo信息
  340.     acm->intPipe = GetPipe(acm, USB_PIPE_TYPE_INTERRUPT, USB_PIPE_DIRECTION_IN);
  341.     if (acm->intPipe == NULL) {
  342.         HDF_LOGE("intPipe is null");
  343.         goto ERROR;
  344.     }
  345.     acm->readSize = acm->dataInPipe->maxPacketSize;
  346.     acm->writeSize = acm->dataOutPipe->maxPacketSize;
  347.     acm->ctrlSize = acm->ctrPipe->maxPacketSize;
  348.     acm->intSize = acm->intPipe->maxPacketSize;
  349.     return HDF_SUCCESS;
  350. ERROR:
  351.     // 释放设备中所有的管道信息
  352.     AcmFreePipes(acm);
  353.     return HDF_FAILURE;
  354. }
  355. static void AcmFreeRequests(struct AcmDevice *acm)
  356. {
  357.     if (g_syncRequest != NULL) {
  358.         UsbFreeRequest(g_syncRequest);
  359.         g_syncRequest = NULL;
  360.     }
  361.     AcmFreeReadRequests(acm);
  362.     AcmFreeNotifyReqeust(acm);
  363.     AcmFreeWriteRequests(acm);
  364.     AcmWriteBufFree(acm);
  365. }
  366. static int32_t AcmAllocRequests(const struct AcmDevice *acm)
  367. {
  368.     int32_t ret;
  369.     if (AcmWriteBufAlloc(acm) < 0) {
  370.         HDF_LOGE("%s: AcmWriteBufAlloc failed", __func__);
  371.         return HDF_ERR_MALLOC_FAIL;
  372.     }
  373.     for (int32_t i = 0; i < ACM_NW; i++) {
  374.         struct AcmWb *snd = (struct AcmWb *)&(acm->wb[i]);
  375.         // 分配待发送的IO Request对象
  376.         snd->request = UsbAllocRequest(
  377.             InterfaceIdToHandle((struct AcmDevice *)acm, acm->dataOutPipe->interfaceId), 0, acm->writeSize);
  378.         snd->instance = (struct AcmDevice *)acm;
  379.         if (snd->request == NULL) {
  380.             HDF_LOGE("%s:%d snd request fail", __func__, __LINE__);
  381.             goto ERROR_ALLOC_WRITE_REQ;
  382.         }
  383.     }
  384.     ret = AcmAllocNotifyRequest((struct AcmDevice *)acm); // 分配并填充中断IO Request对象
  385.     if (ret != HDF_SUCCESS) {
  386.         HDF_LOGE("%s:%d AcmAllocNotifyRequest fail", __func__, __LINE__);
  387.         goto ERROR_ALLOC_INT_REQ;
  388.     }
  389.     ret = AcmAllocReadRequests((struct AcmDevice *)acm); // 分配并填充readReq IO Request对象
  390.     if (ret) {
  391.         HDF_LOGE("%s:%d AcmAllocReadRequests fail", __func__, __LINE__);
  392.         goto ERROR_ALLOC_READ_REQ;
  393.     }
  394.     return HDF_SUCCESS;
  395. ERROR_ALLOC_READ_REQ:
  396.     AcmFreeNotifyReqeust((struct AcmDevice *)acm);
  397. ERROR_ALLOC_INT_REQ:
  398.     AcmFreeWriteRequests((struct AcmDevice *)acm);
  399. ERROR_ALLOC_WRITE_REQ:
  400.     AcmWriteBufFree((struct AcmDevice *)acm);
  401.     return HDF_FAILURE;
  402. }
  403. static int32_t AcmInit(struct AcmDevice *acm)
  404. {
  405.     int32_t ret;
  406.     if (acm->initFlag) {
  407.         HDF_LOGE("%{public}s: initFlag is true", __func__);
  408.         return HDF_SUCCESS;
  409.     }
  410.         // 初始化Host DDK
  411.     ret = UsbInitHostSdk(NULL);
  412.     if (ret != HDF_SUCCESS) {
  413.         HDF_LOGE("%{public}s: UsbInitHostSdk failed", __func__);
  414.         return HDF_ERR_IO;
  415.     }
  416.     acm->session = NULL;
  417.         // 根据acm->interfaceIndex[i]分别获取UsbInterface接口对象
  418.     ret = AcmClaimInterfaces(acm);
  419.     if (ret != HDF_SUCCESS) {
  420.         HDF_LOGE("%{public}s: AcmClaimInterfaces failed", __func__);
  421.         goto ERROR_CLAIM_INTERFACES;
  422.     }
  423.     // 根据acm->iface[i]分别打开UsbInterface接口对象
  424.     ret = AcmOpenInterfaces(acm);
  425.     if (ret != HDF_SUCCESS) {
  426.         HDF_LOGE("%{public}s: AcmOpenInterfaces failed", __func__);
  427.         goto ERROR_OPEN_INTERFACES;
  428.     }
  429.     // 获取管道信息的指针
  430.     ret = AcmGetPipes(acm);
  431.     if (ret != HDF_SUCCESS) {
  432.         HDF_LOGE("%{public}s: AcmGetPipes failed", __func__);
  433.         goto ERROR_GET_PIPES;
  434.     }
  435.     ret = AcmAllocRequests(acm);
  436.     if (ret != HDF_SUCCESS) {
  437.         HDF_LOGE("%{public}s: AcmAllocRequests failed", __func__);
  438.         goto ERROR_ALLOC_REQS;
  439.     }
  440.     acm->lineCoding.dwDTERate = CPU_TO_LE32(DATARATE);
  441.     acm->lineCoding.bCharFormat = USB_CDC_1_STOP_BITS;
  442.     acm->lineCoding.bParityType = USB_CDC_NO_PARITY;
  443.     acm->lineCoding.bDataBits = DATA_BITS_LENGTH;
  444.     acm->initFlag = true;
  445.     return HDF_SUCCESS;
  446. ERROR_ALLOC_REQS:
  447.     AcmFreePipes(acm);
  448. ERROR_GET_PIPES:
  449.     // 关闭所有UsbInterface接口对象
  450.     AcmCloseInterfaces(acm);
  451. ERROR_OPEN_INTERFACES:
  452.     // 释放所有UsbInterface接口对象
  453.     AcmReleaseInterfaces(acm);
  454. ERROR_CLAIM_INTERFACES:
  455.     // 在主机端退出USB DDK,acm->session代表指向会话上下文的指针
  456.     UsbExitHostSdk(acm->session);
  457.     acm->session = NULL;
  458.     return ret;
  459. }
  460. static void AcmRelease(struct AcmDevice *acm)
  461. {
  462.     if (!(acm->initFlag)) {
  463.         HDF_LOGE("%s:%d: initFlag is false", __func__, __LINE__);
  464.         return;
  465.     }
  466.     AcmCloseInterfaces(acm);
  467.     AcmReleaseInterfaces(acm);
  468.     AcmFreeRequests(acm);
  469.     AcmFreePipes(acm);
  470.     // 在主机端退出USB DDK
  471.     UsbExitHostSdk(acm->session);
  472.     acm->session = NULL;
  473.     acm->initFlag = false;
  474. }
  475. static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
  476. {
  477.     int32_t ret;
  478.     struct AcmDevice *acm = NULL;
  479.     if (device == NULL) {
  480.         HDF_LOGE("%s: device is null", __func__);
  481.         return HDF_ERR_INVALID_OBJECT;
  482.     }
  483.     acm = (struct AcmDevice *)device->service;
  484.     // 初始化互斥锁,&acm->readLock表示指向互斥量的指针
  485.     if (acm == NULL) {
  486.         return HDF_ERR_INVALID_OBJECT;
  487.     }
  488.     OsalMutexInit(&acm->readLock);
  489.     OsalMutexInit(&acm->writeLock);
  490.     HDF_LOGD("%s:%d busNum = %d,devAddr = %d", __func__, __LINE__, acm->busNum, acm->devAddr);
  491.     // 给USB串口设备信息开辟空间并赋值
  492.     ret = UsbSerialDeviceAlloc(acm);
  493.     if (ret != HDF_SUCCESS) {
  494.         HDF_LOGE("%s: Serial Device alloc failed", __func__);
  495.     }
  496.     acm->initFlag = false;
  497.     g_acmReleaseFlag = false;
  498.     HDF_LOGD("%s:%d init ok!", __func__, __LINE__);
  499.     return ret;
  500. }
  501. static void UsbSerialDriverRelease(struct HdfDeviceObject *device)
  502. {
  503.     struct AcmDevice *acm = NULL;
  504.     if (device == NULL) {
  505.         HDF_LOGE("%s: device is null", __func__);
  506.         return;
  507.     }
  508.     acm = (struct AcmDevice *)device->service;
  509.     if (acm == NULL) {
  510.         HDF_LOGE("%s: acm is null", __func__);
  511.         return;
  512.     }
  513.     g_acmReleaseFlag = true;
  514.     if (acm->initFlag) {
  515.         HDF_LOGE("%s:%d AcmRelease", __func__, __LINE__);
  516.         AcmRelease(acm);
  517.     }
  518.     // 释放usb串口设备信息
  519.     UsbSeriaDevicelFree(acm);
  520.     // 释放互斥锁
  521.     OsalMutexDestroy(&acm->writeLock);
  522.     OsalMutexDestroy(&acm->readLock);
  523.     OsalMutexDestroy(&acm->lock);
  524.     OsalMemFree(acm);
  525.     acm = NULL;
  526.     HDF_LOGD("%s:%d exit", __func__, __LINE__);
  527. }
  528. // 驱动的Bind、Init、及Release操作
  529. struct HdfDriverEntry g_usbSerialDriverEntry = {
  530.     .moduleVersion = 1,
  531.     .moduleName = "usbhost_acm", // 驱动模块名称,必须与hcs文件中配置的名称一致
  532.     .Bind = UsbSerialDriverBind,
  533.     .Init = UsbSerialDriverInit,
  534.     .Release = UsbSerialDriverRelease,
  535. };
  536. HDF_INIT(g_usbSerialDriverEntry); // 驱动入口
复制代码
Host RAW API驱动开辟

  1. root {
  2.     module = "usb_pnp_device";
  3.     usb_pnp_config {
  4.         match_attr = "usb_pnp_match";
  5.         usb_pnp_device_id = "UsbPnpDeviceId";
  6.         UsbPnpDeviceId {
  7.             idTableList = [
  8.                 "host_acm_rawapi_table"
  9.             ];
  10.             host_acm_rawapi_table {    // 驱动配置匹配表信息
  11.                 // 驱动模块名,该字段的值必须和驱动入口结构的moduleName一致
  12.                 moduleName = "usbhost_acm_rawapi";
  13.                 // 驱动对外发布服务的名称,必须唯一
  14.                 serviceName = "usbhost_acm_rawapi_service";
  15.                 // 驱动私有数据匹配关键字
  16.                 deviceMatchAttr = "usbhost_acm_rawapi_matchAttr";
  17.                 // 从该字段开始(包含该字段)之后数据长度,以byte为单位
  18.                 length = 21;
  19.                 // USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber
  20.                 matchFlag = 0x0303;
  21.                 // 厂商编号
  22.                 vendorId = 0x12D1;
  23.                 // 产品编号
  24.                 productId = 0x5000;
  25.                 // 设备出厂编号,低16位
  26.                 bcdDeviceLow = 0x0000;
  27.                 // 设备出厂编号,高16位
  28.                 bcdDeviceHigh = 0x0000;
  29.                 // USB分配的设备类代码
  30.                 deviceClass = 0;
  31.                 // USB分配的子类代码
  32.                 deviceSubClass = 0;
  33.                 // USB分配的设备协议代码
  34.                 deviceProtocol = 0;
  35.                 // 接口类型,根据实际需要可填写多个
  36.                 interfaceClass = [0];
  37.                 // 接口子类型,根据实际需要可填写多个
  38.                 interfaceSubClass = [2, 0];
  39.                 // 接口所遵循的协议,根据实际需要可填写多个
  40.                 interfaceProtocol = [1, 2];
  41.                 // 接口的编号,根据实际需要可填写多个
  42.                 interfaceNumber = [2, 3];
  43.             }
  44.         }
  45.     }
  46. }
复制代码
  1. #include <unistd.h>
  2. #include "hdf_base.h"
  3. #include "hdf_log.h"
  4. #include "hdf_usb_pnp_manage.h"
  5. #include "osal_mem.h"
  6. #include "osal_time.h"
  7. #include "securec.h"
  8. #include "usb_serial_rawapi.h"
  9. #define HDF_LOG_TAG                   USB_HOST_ACM_RAW_API
  10. #define USB_CTRL_REQ_SIZE             64
  11. #define USB_IO_THREAD_STACK_SIZE      8192
  12. #define USB_RAW_IO_SLEEP_MS_TIME      100
  13. #define USB_RAW_IO_STOP_WAIT_MAX_TIME 3
  14. static struct UsbRawRequest *g_syncRequest = NULL;
  15. static UsbRawIoProcessStatusType g_stopIoStatus = USB_RAW_IO_PROCESS_RUNNING;
  16. struct OsalMutex g_stopIoLock;
  17. static bool g_rawAcmReleaseFlag = false;
  18. ...
  19. static int32_t UsbGetConfigDescriptor(UsbRawHandle *devHandle, struct UsbRawConfigDescriptor **config)
  20. {
  21.     UsbRawDevice *dev = NULL;
  22.     int32_t activeConfig;
  23.     int32_t ret;
  24.     if (devHandle == NULL) {
  25.         HDF_LOGE("%s:%d devHandle is null", __func__, __LINE__);
  26.         return HDF_ERR_INVALID_PARAM;
  27.     }
  28.     // 获取主用设备配置
  29.     ret = UsbRawGetConfiguration(devHandle, &activeConfig);
  30.     if (ret) {
  31.         HDF_LOGE("%s:%d UsbRawGetConfiguration failed, ret = %d", __func__, __LINE__, ret);
  32.         return HDF_FAILURE;
  33.     }
  34.     HDF_LOGE("%s:%d activeConfig = %d", __func__, __LINE__, activeConfig);
  35.     // 根据指定的设备句柄获取设备指针
  36.     dev = UsbRawGetDevice(devHandle);
  37.     if (dev == NULL) {
  38.         HDF_LOGE("%s:%d UsbRawGetDevice failed", __func__, __LINE__);
  39.         return HDF_FAILURE;
  40.     }
  41.     // 根据指定的设备ID获取设备配置描述符
  42.     ret = UsbRawGetConfigDescriptor(dev, activeConfig, config);
  43.     if (ret) {
  44.         HDF_LOGE("UsbRawGetConfigDescriptor failed, ret = %d\n", ret);
  45.         return HDF_FAILURE;
  46.     }
  47.     return HDF_SUCCESS;
  48. }
  49. ...
  50.     static int32_t UsbAllocWriteRequests(struct AcmDevice *acm)
  51. {
  52.     int32_t i;
  53.     for (i = 0; i < ACM_NW; i++) {
  54.         struct AcmWb *snd = &acm->wb[i];
  55.         // 分配一个具有指定数目的同步传输分组描述符的传输请求
  56.         snd->request = UsbRawAllocRequest(acm->devHandle, 0, acm->dataOutEp->maxPacketSize);
  57.         snd->instance = acm;
  58.         if (snd->request == NULL) {
  59.             HDF_LOGE("%s: UsbRawAllocRequest failed", __func__);
  60.             return HDF_ERR_MALLOC_FAIL;
  61.         }
  62.     }
  63.     return HDF_SUCCESS;
  64. }
  65. ...
  66. /* HdfDriverEntry implementations */
  67. static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device)
  68. {
  69.     struct AcmDevice *acm = NULL;
  70.     struct UsbPnpNotifyServiceInfo *info = NULL;
  71.     errno_t err;
  72.     if (device == NULL) {
  73.         HDF_LOGE("%s: device is null", __func__);
  74.         return HDF_ERR_INVALID_OBJECT;
  75.     }
  76.     acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm));
  77.     if (acm == NULL) {
  78.         HDF_LOGE("%s: Alloc usb serial device failed", __func__);
  79.         return HDF_FAILURE;
  80.     }
  81.     if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) {
  82.         HDF_LOGE("%s:%d OsalMutexInit fail", __func__, __LINE__);
  83.         goto ERROR;
  84.     }
  85.     info = (struct UsbPnpNotifyServiceInfo *)device->priv;
  86.     if (info != NULL) {
  87.         acm->busNum = (uint8_t)info->busNum;
  88.         acm->devAddr = (uint8_t)info->devNum;
  89.         acm->interfaceCnt = info->interfaceLength;
  90.         err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, (const void *)info->interfaceNumber,
  91.             info->interfaceLength);
  92.         if (err != EOK) {
  93.             HDF_LOGE("%s:%d memcpy_s failed err=%d", __func__, __LINE__, err);
  94.             goto LOCK_ERROR;
  95.         }
  96.     } else {
  97.         HDF_LOGE("%s:%d info is NULL!", __func__, __LINE__);
  98.         goto LOCK_ERROR;
  99.     }
  100.     device->service = &(acm->service);
  101.     device->service->Dispatch = UsbSerialDeviceDispatch;
  102.     acm->device = device;
  103.     HDF_LOGD("UsbSerialDriverBind=========================OK");
  104.     return HDF_SUCCESS;
  105. LOCK_ERROR:
  106.     if (OsalMutexDestroy(&acm->lock)) {
  107.         HDF_LOGE("%s:%d OsalMutexDestroy fail", __func__, __LINE__);
  108.     }
  109. ERROR:
  110.     OsalMemFree(acm);
  111.     acm = NULL;
  112.     return HDF_FAILURE;
  113. }
  114. ...
  115. static int32_t UsbAllocReadRequests(struct AcmDevice *acm)
  116. {
  117.     struct UsbRawFillRequestData reqData;
  118.     uint32_t size = acm->dataInEp->maxPacketSize;
  119.     for (int32_t i = 0; i < ACM_NR; i++) {
  120.         // 分配一个具有指定数目的同步传输分组描述符的传输请求
  121.         acm->readReq[i] = UsbRawAllocRequest(acm->devHandle, 0, size);
  122.         if (!acm->readReq[i]) {
  123.             HDF_LOGE("readReq request failed\n");
  124.             return HDF_ERR_MALLOC_FAIL;
  125.         }
  126.         reqData.endPoint = acm->dataInEp->addr;
  127.         reqData.numIsoPackets = 0;
  128.         reqData.callback = AcmReadBulkCallback;
  129.         reqData.userData = (void *)acm;
  130.         reqData.timeout = USB_CTRL_SET_TIMEOUT;
  131.         reqData.length = size;
  132.         // 在批量传输请求中填写所需信息
  133.         int32_t ret = UsbRawFillBulkRequest(acm->readReq[i], acm->devHandle, &reqData);
  134.         if (ret != HDF_SUCCESS) {
  135.             HDF_LOGE("%s: FillBulkRequest failed, ret=%d\n", __func__, ret);
  136.             return HDF_FAILURE;
  137.         }
  138.     }
  139.     return HDF_SUCCESS;
  140. }
  141. ...
  142. static int32_t UsbAllocNotifyRequest(struct AcmDevice *acm)
  143. {
  144.     struct UsbRawFillRequestData fillRequestData;
  145.     uint32_t size = acm->notifyEp->maxPacketSize;
  146.     int32_t ret;
  147.     // 分配一个具有指定数目的同步传输分组描述符的传输请求
  148.     acm->notifyReq = UsbRawAllocRequest(acm->devHandle, 0, size);
  149.     if (!acm->notifyReq) {
  150.         HDF_LOGE("notifyReq request fail\n");
  151.         return HDF_ERR_MALLOC_FAIL;
  152.     }
  153.     fillRequestData.endPoint = acm->notifyEp->addr;
  154.     fillRequestData.length = size;
  155.     fillRequestData.numIsoPackets = 0;
  156.     fillRequestData.callback = AcmNotifyReqCallback;
  157.     fillRequestData.userData = (void *)acm;
  158.     fillRequestData.timeout = USB_CTRL_SET_TIMEOUT;
  159.     // 在中断传输请求中填充所需的信息
  160.     ret = UsbRawFillInterruptRequest(acm->notifyReq, acm->devHandle, &fillRequestData);
  161.     if (ret) {
  162.         HDF_LOGE("%s: FillInterruptRequest failed, ret=%d", __func__, ret);
  163.         return HDF_FAILURE;
  164.     }
  165.     return HDF_SUCCESS;
  166. }
  167. ...
  168. static int32_t UsbSerialInit(struct AcmDevice *acm)
  169. {
  170.     struct UsbSession *session = NULL;
  171.     UsbRawHandle *devHandle = NULL;
  172.     int32_t ret;
  173.     if (acm->initFlag) {
  174.         HDF_LOGE("%s:%d: initFlag is true", __func__, __LINE__);
  175.         return HDF_SUCCESS;
  176.     }
  177.     // 以专家模式初始化USB DDK
  178.     ret = UsbRawInit(NULL);
  179.     if (ret) {
  180.         HDF_LOGE("%s:%d UsbRawInit failed", __func__, __LINE__);
  181.         return HDF_ERR_IO;
  182.     }
  183.     acm->session = session;
  184.     // 打开一个USB设备对象
  185.     devHandle = UsbRawOpenDevice(session, acm->busNum, acm->devAddr);
  186.     if (devHandle == NULL) {
  187.         HDF_LOGE("%s:%d UsbRawOpenDevice failed", __func__, __LINE__);
  188.         ret = HDF_FAILURE;
  189.         goto ERR_OPEN_DEVICE;
  190.     }
  191.     acm->devHandle = devHandle;
  192.     // 获取主用设备配置、设备指针及配置描述符
  193.     ret = UsbGetConfigDescriptor(devHandle, &acm->config);
  194.     if (ret) {
  195.         HDF_LOGE("%s:%d UsbGetConfigDescriptor failed", __func__, __LINE__);
  196.         ret = HDF_FAILURE;
  197.         goto ERR_GET_DESC;
  198.     }
  199.     ret = UsbParseConfigDescriptor(acm, acm->config);
  200.     if (ret != HDF_SUCCESS) {
  201.         HDF_LOGE("%s:%d UsbParseConfigDescriptor failed", __func__, __LINE__);
  202.         ret = HDF_FAILURE;
  203.         goto ERR_PARSE_DESC;
  204.     }
  205.     ret = AcmWriteBufAlloc(acm);
  206.     if (ret < 0) {
  207.         HDF_LOGE("%s:%d AcmWriteBufAlloc failed", __func__, __LINE__);
  208.         ret = HDF_FAILURE;
  209.         goto ERR_ALLOC_WRITE_BUF;
  210.     }
  211.     ret = UsbAllocWriteRequests(acm);
  212.     if (ret < 0) {
  213.         HDF_LOGE("%s:%d UsbAllocWriteRequests failed", __func__, __LINE__);
  214.         ret = HDF_FAILURE;
  215.         goto ERR_ALLOC_WRITE_REQS;
  216.     }
  217.     ret = UsbAllocNotifyRequest(acm);
  218.     if (ret) {
  219.         HDF_LOGE("%s:%d UsbAllocNotifyRequests failed", __func__, __LINE__);
  220.         goto ERR_ALLOC_NOTIFY_REQ;
  221.     }
  222.     ret = UsbAllocReadRequests(acm);
  223.     if (ret) {
  224.         HDF_LOGE("%s:%d UsbAllocReadRequests failed", __func__, __LINE__);
  225.         goto ERR_ALLOC_READ_REQS;
  226.     }
  227.     ret = UsbStartIo(acm);
  228.     if (ret) {
  229.         HDF_LOGE("%s:%d UsbAllocReadRequests failed", __func__, __LINE__);
  230.         goto ERR_START_IO;
  231.     }
  232.     acm->lineCoding.dwDTERate = CPU_TO_LE32(DATARATE);
  233.     acm->lineCoding.bCharFormat = USB_CDC_1_STOP_BITS;
  234.     acm->lineCoding.bParityType = USB_CDC_NO_PARITY;
  235.     acm->lineCoding.bDataBits = DATA_BITS_LENGTH;
  236.     ret = UsbRawSubmitRequest(acm->notifyReq);
  237.     if (ret) {
  238.         HDF_LOGE("%s:%d UsbRawSubmitRequest failed", __func__, __LINE__);
  239.         goto ERR_SUBMIT_REQ;
  240.     }
  241.     acm->initFlag = true;
  242.     HDF_LOGD("%s:%d=========================OK", __func__, __LINE__);
  243.     return HDF_SUCCESS;
  244. ERR_SUBMIT_REQ:
  245.     UsbStopIo(acm); // 停止IO线程并释放所有资源
  246. ERR_START_IO:
  247.     UsbFreeReadRequests(acm);
  248. ERR_ALLOC_READ_REQS:
  249.     UsbFreeNotifyReqeust(acm);
  250. ERR_ALLOC_NOTIFY_REQ:
  251.     UsbFreeWriteRequests(acm);
  252. ERR_ALLOC_WRITE_REQS:
  253.     AcmWriteBufFree(acm);
  254. ERR_ALLOC_WRITE_BUF:
  255.     UsbReleaseInterfaces(acm);
  256. ERR_PARSE_DESC:
  257.     UsbRawFreeConfigDescriptor(acm->config);
  258.     acm->config = NULL;
  259. ERR_GET_DESC:
  260.     (void)UsbRawCloseDevice(devHandle); // 关闭USB设备对象
  261. ERR_OPEN_DEVICE:
  262.     UsbRawExit(acm->session); // 退出USB DDK的专家模式
  263.     return ret;
  264. }
  265. ...
  266. static void UsbSerialRelease(struct AcmDevice *acm)
  267. {
  268.     if (!(acm->initFlag)) {
  269.         HDF_LOGE("%s:%d: initFlag is false", __func__, __LINE__);
  270.         return;
  271.     }
  272.     /* stop io thread and release all resources */
  273.     UsbStopIo(acm);
  274.     if (g_syncRequest != NULL) {
  275.         UsbRawFreeRequest(g_syncRequest);
  276.         g_syncRequest = NULL;
  277.     }
  278.     UsbFreeReadRequests(acm);
  279.     UsbFreeNotifyReqeust(acm);
  280.     UsbFreeWriteRequests(acm);
  281.     AcmWriteBufFree(acm);
  282.     UsbReleaseInterfaces(acm);
  283.     (void)UsbRawCloseDevice(acm->devHandle);
  284.     UsbRawFreeConfigDescriptor(acm->config);
  285.     acm->config = NULL;
  286.     // 退出USB DDK的专家模式
  287.     UsbRawExit(acm->session);
  288.     acm->initFlag = false;
  289. }
  290. static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
  291. {
  292.     struct AcmDevice *acm = NULL;
  293.     int32_t ret;
  294.     if (device == NULL) {
  295.         HDF_LOGE("%s:%d device is null", __func__, __LINE__);
  296.         return HDF_ERR_INVALID_OBJECT;
  297.     }
  298.     acm = (struct AcmDevice *)device->service;
  299.     if (acm == NULL) {
  300.         return HDF_ERR_INVALID_OBJECT;
  301.     }
  302.     OsalMutexInit(&acm->readLock);
  303.     OsalMutexInit(&acm->writeLock);
  304.         // 设备申请连续的内存
  305.     ret = UsbSerialDeviceAlloc(acm);
  306.     if (ret != HDF_SUCCESS) {
  307.         HDF_LOGE("%s:%d UsbSerialDeviceAlloc failed", __func__, __LINE__);
  308.     }
  309.     acm->initFlag = false;
  310.     g_rawAcmReleaseFlag = false;
  311.     HDF_LOGD("%s:%d init ok!", __func__, __LINE__);
  312.     return ret;
  313. }
  314. static void UsbSerialDriverRelease(struct HdfDeviceObject *device)
  315. {
  316.     struct AcmDevice *acm = NULL;
  317.     if (device == NULL) {
  318.         HDF_LOGE("%s: device is null", __func__);
  319.         return;
  320.     }
  321.     acm = (struct AcmDevice *)device->service;
  322.     if (acm == NULL) {
  323.         HDF_LOGE("%s: acm is null", __func__);
  324.         return;
  325.     }
  326.     g_rawAcmReleaseFlag = true;
  327.     if (acm->initFlag) {
  328.         HDF_LOGE("%s:%d UsbSerialRelease", __func__, __LINE__);
  329.         UsbSerialRelease(acm);
  330.     }
  331.     UsbSeriaDevicelFree(acm);
  332.     OsalMutexDestroy(&acm->writeLock);
  333.     OsalMutexDestroy(&acm->readLock);
  334.     OsalMutexDestroy(&acm->lock);
  335.     OsalMemFree(acm);
  336.     acm = NULL;
  337.     HDF_LOGD("%s:%d exit", __func__, __LINE__);
  338. }
  339. struct HdfDriverEntry g_usbSerialRawDriverEntry = {
  340.     .moduleVersion = 1,
  341.     .moduleName = "usbhost_acm_rawapi", // 驱动模块名称,必须与hcs文件中配置的名称一致
  342.     .Bind = UsbSerialDriverBind,
  343.     .Init = UsbSerialDriverInit,
  344.     .Release = UsbSerialDriverRelease,
  345. };
  346. 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)
    2. {
    3.     int32_t ret;
    4.     struct UsbFnDevice *fnDev = NULL;
    5. // 读取hcs文件中的udc_name节点的字符串值
    6.     if (iface->GetString(acm->device->property, "udc_name", (const char **)&acm->udcName, UDC_NAME) != HDF_SUCCESS) {
    7.         HDF_LOGE("%s: read udc_name failed, use default", __func__);
    8.         return HDF_FAILURE;
    9.     }
    10.     fnDev = (struct UsbFnDevice *)UsbFnGetDevice(acm->udcName);
    11.     if (fnDev == NULL) {
    12.         HDF_LOGE("%s: create usb function device failed", __func__);
    13.         return HDF_FAILURE;
    14.     }
    15. // 解析acm每一个Iface
    16.     ret = AcmParseEachIface(acm, fnDev);
    17.     if (ret != HDF_SUCCESS) {
    18.         HDF_LOGE("%s: get pipes failed", __func__);
    19.         return HDF_FAILURE;
    20.     }
    21.     acm->fnDev = fnDev;
    22.     return HDF_SUCCESS;
    23. }
    复制代码
  • 获取接口,打开接口,获取Pipe信息
    1. static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface)
    2. {
    3.     struct UsbFnInterface *fnIface = iface->fn;
    4.     for (uint32_t i = 0; i < fnIface->info.numPipes; i++) {
    5.         struct UsbFnPipeInfo pipeInfo;
    6.         // pipeInfo清除缓存区内容
    7.         (void)memset_s(&pipeInfo, sizeof(pipeInfo), 0, sizeof(pipeInfo));
    8.         /* 获取pipe信息 */
    9.         int32_t ret = UsbFnGetInterfacePipeInfo(fnIface, i, &pipeInfo);
    10.         if (ret != HDF_SUCCESS) {
    11.             HDF_LOGE("%s: get pipe info error", __func__);
    12.             return ret;
    13.         }
    14.         // PIPE的中断和管脚
    15.         switch (pipeInfo.type) {
    16.             case USB_PIPE_TYPE_INTERRUPT:
    17.                 acm->notifyPipe.id = pipeInfo.id;
    18.                 acm->notifyPipe.maxPacketSize = pipeInfo.maxPacketSize;
    19.                 acm->ctrlIface = *iface;
    20.                 break;
    21.             case USB_PIPE_TYPE_BULK:
    22.                 if (pipeInfo.dir == USB_PIPE_DIRECTION_IN) {
    23.                     acm->dataInPipe.id = pipeInfo.id;
    24.                     acm->dataInPipe.maxPacketSize = pipeInfo.maxPacketSize;
    25.                     acm->dataIface = *iface;
    26.                 } else {
    27.                     acm->dataOutPipe.id = pipeInfo.id;
    28.                     acm->dataOutPipe.maxPacketSize = pipeInfo.maxPacketSize;
    29.                 }
    30.                 break;
    31.             default:
    32.                 HDF_LOGE("%s: pipe type %d don't support", __func__, pipeInfo.type);
    33.                 break;
    34.         }
    35.     }
    36.     return HDF_SUCCESS;
    37. }
    38. /* 获取接口,打开接口获取handle */
    39. static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev)
    40. {
    41.     struct UsbFnInterface *fnIface = NULL;
    42.     uint32_t i;
    43.     if (fnDev == NULL) {
    44.         return HDF_FAILURE;
    45.     }
    46.     for (i = 0; i < fnDev->numInterfaces; i++) {
    47.         fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
    48.         if (fnIface == NULL) {
    49.             HDF_LOGE("%s: get interface failed", __func__);
    50.             return HDF_FAILURE;
    51.         }
    52.         if (fnIface->info.subclass == USB_DDK_CDC_SUBCLASS_ACM) {
    53.             (void)AcmParseAcmIface(acm, fnIface);
    54.             fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i + 1);
    55.             if (fnIface == NULL) {
    56.                 HDF_LOGE("%s: get interface failed", __func__);
    57.                 return HDF_FAILURE;
    58.             }
    59.             (void)AcmParseAcmIface(acm, fnIface);
    60.             return HDF_SUCCESS;
    61.         }
    62.     }
    63.     return HDF_FAILURE;
    64. }
    复制代码
  • 接收Event事件(EP0控制传输)
    1. static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int32_t num)
    2. {
    3.     struct DListHead *head = &acm->ctrlPool;
    4.     struct UsbFnRequest *req = NULL;
    5.     struct CtrlInfo *ctrlInfo = NULL;
    6.     int32_t i;
    7.     DListHeadInit(&acm->ctrlPool);
    8.     acm->ctrlReqNum = 0;
    9.     for (i = 0; i < num; i++) {
    10.         // 申请内存
    11.         ctrlInfo = (struct CtrlInfo *)OsalMemCalloc(sizeof(*ctrlInfo));
    12.         if (ctrlInfo == NULL) {
    13.             HDF_LOGE("%s: Allocate ctrlInfo failed", __func__);
    14.             goto OUT;
    15.         }
    16.         ctrlInfo->acm = acm;
    17.         req = UsbFnAllocCtrlRequest(
    18.             acm->ctrlIface.handle, sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
    19.         if (req == NULL) {
    20.             goto OUT;
    21.         }
    22.         req->complete = AcmCtrlComplete;
    23.         req->context = ctrlInfo;
    24.         DListInsertTail(&req->list, head);
    25.         acm->ctrlReqNum++;
    26.     }
    27.     return HDF_SUCCESS;
    28. OUT:
    29.     return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS;
    30. }
    复制代码
  • 进行USB通信(读写等)
    1. static int32_t AcmSendNotifyRequest(
    2.     struct UsbAcmDevice *acm, uint8_t type, uint16_t value, const void *data, uint32_t length)
    3. {
    4.     struct UsbFnRequest *req = acm->notifyReq;
    5.     struct UsbCdcNotification *notify = NULL;
    6.     int32_t ret;
    7.     if (req == NULL || req->buf == NULL) {
    8.         HDF_LOGE("%s: req is null", __func__);
    9.         return HDF_FAILURE;
    10.     }
    11.     acm->notifyReq = NULL;
    12.     acm->pending = false;
    13.     req->length = sizeof(*notify) + length;
    14.     notify = (struct UsbCdcNotification *)req->buf;
    15.     notify->bmRequestType = USB_DDK_DIR_IN | USB_DDK_TYPE_CLASS | USB_DDK_RECIP_INTERFACE;
    16.     notify->bNotificationType = type;
    17.     notify->wValue = CPU_TO_LE16(value);
    18.     notify->wIndex = CPU_TO_LE16(acm->ctrlIface.fn->info.index);
    19.     notify->wLength = CPU_TO_LE16(length);
    20.     ret = memcpy_s((void *)(notify + 1), length, data, length);
    21.     if (ret != EOK) {
    22.         HDF_LOGE("%s: memcpy_s failed", __func__);
    23.         return HDF_FAILURE;
    24.     }
    25.     ret = UsbFnSubmitRequestAsync(req);
    26.     if (ret != HDF_SUCCESS) {
    27.         HDF_LOGE("%s: send notify request failed", __func__);
    28.         acm->notifyReq = req;
    29.     }
    30.     return ret;
    31. }
    复制代码
  • 关闭接口,停止Event接收,删除设备
    1. static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm)
    2. {
    3.     int32_t ret;
    4.     /* 关闭接口 */
    5.     (void)UsbFnInterfaceClose(acm->ctrlIface.handle);
    6.     (void)UsbFnInterfaceClose(acm->dataIface.handle);
    7.     /* 停止接收Event EP0控制传输 */
    8.     (void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn);
    9.     /* 删除设备 */
    10.     ret = UsbFnDeviceRemove(acm->fnDev);
    11.     if (ret != HDF_SUCCESS) {
    12.         HDF_LOGE("%s: remove usb function device failed", __func__);
    13.     }
    14.     return ret;
    15. }
    16. static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm)
    17. {
    18.     int32_t ret = HDF_SUCCESS;
    19.     if (acm->fnDev == NULL) {
    20.         HDF_LOGE("%s: fnDev is null", __func__);
    21.         return HDF_FAILURE;
    22.     }
    23.     //释放通知请求
    24.     AcmFreeCtrlRequests(acm);
    25.     AcmFreeNotifyRequest(acm);
    26.      /* 停止接收Event EP0控制传输 */
    27.     (void)UsbFnCloseInterface(acm->ctrlIface.handle);
    28.     (void)UsbFnCloseInterface(acm->dataIface.handle);
    29.     (void)UsbFnStopRecvInterfaceEvent(acm->ctrlIface.fn);
    30.     return ret;
    31. }
    复制代码

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天空闲话

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表