1e41f4b71Sopenharmony_ci# USB 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Introduction 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci### Function Overview 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciThe universal serial bus (USB) consists of a USB host and multiple USB devices. The USB host implement data transfer and port management in the USB bus, and the USB device can connect to various peripherals. Therefore, USB driver development is divided into USB host driver development and USB device driver development. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciThe USB module of OpenHarmony supports the development of USB services, provides USB-related functions, provides interfaces to read and write USB device data of third-party function drivers in user mode, creates and deletes USB devices, obtains notification events, enables or disables event listening, implements non-isochronous and isochronous data transfer over USB pipes, and sets custom USB attributes. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ciThe USB DriverDevelop Kit (DDK) is the USB driver development kit provided by the Framework of the OpenHarmony Driver Foundation (HDF). This kit consists of the USB Host DDK and USB Device DDK. It supports the development of USB device drivers based on the user mode and provides rich USB driver development capabilities that help you to efficiently develop USB drivers. 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci### Basic Concepts 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci- Pipe 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci A pipe is a model for data transfer between the USB host and a device endpoint. Once a USB device is powered on, a pipe, that is, the default control pipe, is established. The USB host obtains the description, configuration, and status of the USB device through the pipe, and configures the device as requested. Pipes and endpoints are associated and share the same attributes, such as the supported transfer type, maximum packet length, and data transfer direction. 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci- Endpoint 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci The minimum unit that transfers and receives data in a USB device. It supports unidirectional or bidirectional data transfer. One USB device may include several endpoints, and different endpoints are distinguished by endpoint numbers and directions. Different endpoints can support different data transfer types, access intervals, and maximum packet sizes. All endpoints except endpoint 0 support data transfer in only one direction. Endpoint 0 is a special endpoint that supports bidirectional control transfer. 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci- Interface 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ci The application implements device control and data transfer through exchanging data with the device. Because a pipe supports only one data transfer type, multiple pipes are usually required to complete data exchange in this process. A collection of pipes that are used together to control a device is called an interface. 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci- Descriptor 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci A data structure used to describe device attributes. The first byte indicates the descriptor size (number of bytes), and the second byte indicates the descriptor type. 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ci### Working Principles 32e41f4b71Sopenharmony_ci 33e41f4b71Sopenharmony_ci#### USB Host DDK 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ciThe USB Host DDK provides the capability of developing USB drivers on the host. Based on functions, APIs of the USB Host DDK are classified into three types: DDK initialization, **interface** object operation, and **request** object operation. 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ci **Figure 1** USB host driver model 38e41f4b71Sopenharmony_ci 39e41f4b71Sopenharmony_ci  40e41f4b71Sopenharmony_ci 41e41f4b71Sopenharmony_ci- The USB Interface Pool module manages USB interfaces. It applies for and reclaims USB interface objects, which are used to record device port information and resources. The module manages USB interfaces by USB port. In addition, it provides USB DDK APIs to read and write USB data. 42e41f4b71Sopenharmony_ci 43e41f4b71Sopenharmony_ci- The USB Protocol Layer module provides USB protocol encapsulation, translates and parses device I/O and control commands based on the USB protocol, manages device descriptors, and matches descriptors based on the enum information reported by the USB device. This module creates the corresponding USB interface objects and adds them to the USB Interface Pool module for management. 44e41f4b71Sopenharmony_ci 45e41f4b71Sopenharmony_ci- The Device I/O Manager module manages USB I/O requests and provides synchronous and asynchronous I/O management mechanisms. For the asynchronous I/O management mechanism, the module records the asynchronous I/O requests and processes the requests to be sent through the APIs provided by the Raw API Library module. After receiving the processing result from the USB controller, the I/O request receiving thread parses the processing result and reports it to the upper-layer caller. 46e41f4b71Sopenharmony_ci 47e41f4b71Sopenharmony_ci- The Raw API Library module abstracts underlying OS capabilities, defines unified OS capability APIs, and provides the USB RAW APIs needed to implement more complex driver functions. 48e41f4b71Sopenharmony_ci 49e41f4b71Sopenharmony_ci- The OS Adapter module encapsulates operations related to platforms (Linux and LiteOS). It compiles encapsulation APIs depending on the configuration of the specific platform. On the Linux platform, all USB FS access operations are encapsulated in this module. On the LiteOS platform, all device access operations based on the FreeBSD USB framework are encapsulated in this module. 50e41f4b71Sopenharmony_ci 51e41f4b71Sopenharmony_ci- The PNP Notify module dynamically monitors USB status changes. This module updates the device information when a device is added or removed. Meanwhile, it reports all USB device information to the PNP Notify Manager module on the UHDF side through the KHDF to load or uninstall third-party function drivers. 52e41f4b71Sopenharmony_ci 53e41f4b71Sopenharmony_ci#### USB Device DDK 54e41f4b71Sopenharmony_ci 55e41f4b71Sopenharmony_ciThe USB Device DDK provides the capability of developing USB drivers on the device side. For example, with the dynamic registration and deregistration capabilities, you can dynamically add and combine USB ports based on the actual requirement; with the dynamic instantiation capability, you can create device instances and transmission channels based on dynamically delivered device, configuration, interface, and endpoint descriptors. In addition, the following functions are supported: sending and receiving data in user mode, isolating multiple logical devices from each other on a physical device, and accessing different logical devices from different application processes at the same time. 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ci **Figure 2** USB device driver model 58e41f4b71Sopenharmony_ci 59e41f4b71Sopenharmony_ci  60e41f4b71Sopenharmony_ci 61e41f4b71Sopenharmony_ci- The SDK IF module divides USB devices logically by device, interface, and pipe, and encapsulates functions including configuration management, device management, and I/O management. This module also provides APIs for device driver development, such as creating and obtaining devices, receiving events, and sending and receiving data. 62e41f4b71Sopenharmony_ci 63e41f4b71Sopenharmony_ci- The Configuration Manager module parses the .hcs file for the USB descriptor information, which will be used for creating USB devices. In addition, the module provides operations such as reading, creating, deleting, and modifying custom USB attributes. 64e41f4b71Sopenharmony_ci 65e41f4b71Sopenharmony_ci- The Device Manager module parses USB descriptor information and creates USB devices accordingly. It also provides functions such as adding or deleting USB devices, obtaining USB device status, and obtaining USB device interface information. 66e41f4b71Sopenharmony_ci 67e41f4b71Sopenharmony_ci- The IO Manager module reads and writes data, including common events and data read and write events. It supports data read and write in synchronous and asynchronous modes. 68e41f4b71Sopenharmony_ci 69e41f4b71Sopenharmony_ci- The Adapter IF module encapsulates device node operations of composite device configuration drivers and common function drivers to provide unified device management APIs for the upper layer. 70e41f4b71Sopenharmony_ci 71e41f4b71Sopenharmony_ci- The Adapter module is provided by the composite device configuration driver and common function driver. 72e41f4b71Sopenharmony_ci 73e41f4b71Sopenharmony_ci## Development Guidelines 74e41f4b71Sopenharmony_ci 75e41f4b71Sopenharmony_ciThe USB driver development in kernel mode is complex. Therefore, you need to have a deep understanding of the USB protocol. The USB DDK is introduced to help you to develop USB drivers in user mode more conveniently. 76e41f4b71Sopenharmony_ci 77e41f4b71Sopenharmony_ci### When to Use 78e41f4b71Sopenharmony_ci 79e41f4b71Sopenharmony_ciThe USB Host DDK comes with two modes, namely, common mode and expert mode. In common mode, you can directly read and write USB data by using USB DDK APIs without knowing details about data transfer at the bottom layer. In expert mode, you can use USB RAW APIs to directly access the USB channel interfaces provided by the OS platform to implement more complex functions. The USB Device DDk provides functions such as USB device management, interface definition, and USB data request. 80e41f4b71Sopenharmony_ci 81e41f4b71Sopenharmony_ci### Available APIs 82e41f4b71Sopenharmony_ci 83e41f4b71Sopenharmony_ciThe following table lists the APIs related to USB host driver development (common mode). For details about the API definitions, see the [source code](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/host/usb_ddk_interface.h). 84e41f4b71Sopenharmony_ci 85e41f4b71Sopenharmony_ci **Table 1** APIs for USB host driver development (common mode) 86e41f4b71Sopenharmony_ci 87e41f4b71Sopenharmony_ci| API| Description| 88e41f4b71Sopenharmony_ci| -------- | -------- | 89e41f4b71Sopenharmony_ci| int32_t UsbInitHostSdk(struct UsbSession \*\*session); | Initializes the USB host driver DDK.| 90e41f4b71Sopenharmony_ci| const struct UsbInterface \*UsbClaimInterface(const<br>struct UsbSession \*session, uint8_t busNum, uint8_t<br>usbAddr, uint8_t interfaceIndex); | Obtains a USB interface.| 91e41f4b71Sopenharmony_ci| UsbInterfaceHandle \*UsbOpenInterface(const struct<br>UsbInterface \*interfaceObj); | Opens a USB interface.| 92e41f4b71Sopenharmony_ci| int32_t UsbGetPipeInfo(const UsbInterfaceHandle<br>\*interfaceHandle, uint8_t settingIndex, uint8_t pipeId,<br>struct UsbPipeInfo \*pipeInfo); | Obtains USB pipe information.| 93e41f4b71Sopenharmony_ci| struct UsbRequest \*UsbAllocRequest(const<br>UsbInterfaceHandle \*interfaceHandle, int32_t isoPackets<br>, int32_t length); | Allocates a request object.| 94e41f4b71Sopenharmony_ci| int32_t UsbFillRequest(const struct UsbRequest<br>\*request, const UsbInterfaceHandle \*interfaceHandle,<br>const struct UsbRequestParams \*params); | Fills in a request.| 95e41f4b71Sopenharmony_ci| int32_t UsbSubmitRequestSync(const struct UsbRequest<br>\*request); | Sends a synchronous request.| 96e41f4b71Sopenharmony_ci 97e41f4b71Sopenharmony_ciThe following table lists the APIs related to USB host driver development (expert mode). For details about the API definitions, see the [source code](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/host/usb_raw_api.h). 98e41f4b71Sopenharmony_ci 99e41f4b71Sopenharmony_ci **Table 2** APIs for USB host driver development (expert mode) 100e41f4b71Sopenharmony_ci 101e41f4b71Sopenharmony_ci| API| Description| 102e41f4b71Sopenharmony_ci| -------- | -------- | 103e41f4b71Sopenharmony_ci| int32_t UsbRawInit(struct UsbSession \*\*session); | Initializes the USB raw APIs.| 104e41f4b71Sopenharmony_ci| UsbRawHandle \*UsbRawOpenDevice(const struct<br>UsbSession \*session, uint8_t busNum, uint8_t<br>usbAddr); | Opens a USB device.| 105e41f4b71Sopenharmony_ci| int32_t UsbRawSendControlRequest(const struct<br>UsbRawRequest \*request, const UsbRawHandle<br>\*devHandle, const struct UsbControlRequestData<br>\*requestData); | Performs a control transfer synchronously.| 106e41f4b71Sopenharmony_ci| int32_t UsbRawSendBulkRequest(const struct<br>UsbRawRequest \*request, const UsbRawHandle<br>\*devHandle, const struct UsbRequestData<br>\*requestData); | Performs a bulk transfer synchronously.| 107e41f4b71Sopenharmony_ci| int32_t UsbRawSendInterruptRequest(const struct<br>UsbRawRequest \*request, const UsbRawHandle<br>\*devHandle, const struct UsbRequestData<br>\*requestData); | Performs an interrupt transfer synchronously.| 108e41f4b71Sopenharmony_ci| int32_t UsbRawGetConfigDescriptor(const UsbRawDevice<br>\*rawDev, uint8_t configIndex, struct<br>UsbRawConfigDescriptor \*\*config); | Obtains the configuration descriptor of a device.| 109e41f4b71Sopenharmony_ci| int32_t UsbRawFillInterruptRequest(const struct UsbRawRequest<br>\*request, const UsbRawHandle \*devHandle, const struct<br>UsbRawFillRequestData \*fillData); | Fills in an interrupt transfer request.| 110e41f4b71Sopenharmony_ci| int32_t UsbRawFillIsoRequest(const struct UsbRawRequest<br>\*request, const UsbRawHandle \*devHandle, const struct<br>UsbRawFillRequestData \*fillData); | Fills in an isochronous transfer request.| 111e41f4b71Sopenharmony_ci| int32_t UsbRawSubmitRequest(const struct UsbRawRequest<br>\*request); | Submits a transfer request.| 112e41f4b71Sopenharmony_ci| int32_t UsbRawCancelRequest(const struct UsbRawRequest<br>\*request); | Cancels a transfer request.| 113e41f4b71Sopenharmony_ci| int32_t UsbRawHandleRequests(const UsbRawHandle<br>\*devHandle); | Handles a transfer request event.| 114e41f4b71Sopenharmony_ci 115e41f4b71Sopenharmony_ciThe following table lists the APIs for USB device management on the device side. For details about the API definitions, see the [source code](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/device/usbfn_device.h). 116e41f4b71Sopenharmony_ci 117e41f4b71Sopenharmony_ci **Table 3** APIs for USB device management on the device side 118e41f4b71Sopenharmony_ci 119e41f4b71Sopenharmony_ci| API| Description| 120e41f4b71Sopenharmony_ci| -------- | -------- | 121e41f4b71Sopenharmony_ci| const struct UsbFnDevice \*UsbFnCreateDevice(const<br>char \*udcName, const struct UsbFnDescriptorData<br>\*descriptor); | Creates a USB device.| 122e41f4b71Sopenharmony_ci| int32_t UsbFnRemoveDevice(struct UsbFnDevice<br>\*fnDevice); | Deletes a USB device.| 123e41f4b71Sopenharmony_ci| const struct UsbFnDevice \*UsbFnGetDevice(const char<br>\*udcName); | Obtains a USB device.| 124e41f4b71Sopenharmony_ci 125e41f4b71Sopenharmony_ciThe following table lists the APIs for USB interface definition on the device side. For details about the API definitions, see the [source code](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/device/usbfn_interface.h). 126e41f4b71Sopenharmony_ci 127e41f4b71Sopenharmony_ci **Table 4** APIs for USB interface definition on the device side 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci| API| Description| 130e41f4b71Sopenharmony_ci| -------- | -------- | 131e41f4b71Sopenharmony_ci| int32_t UsbFnStartRecvInterfaceEvent(struct<br>UsbFnInterface \*interface, uint32_t eventMask,<br>UsbFnEventCallback callback, void \*context); | Starts receiving events.| 132e41f4b71Sopenharmony_ci| int32_t UsbFnStopRecvInterfaceEvent(struct<br>UsbFnInterface \*interface); | Stops receiving events.| 133e41f4b71Sopenharmony_ci| UsbFnInterfaceHandle UsbFnOpenInterface(struct UsbFnInterface \*interface); | Opens an interface.| 134e41f4b71Sopenharmony_ci| int32_t UsbFnCloseInterface(UsbFnInterfaceHandle handle); | Closes an interface.| 135e41f4b71Sopenharmony_ci| int32_t UsbFnGetInterfacePipeInfo(struct UsbFnInterface<br>\*interface, uint8_t pipeId, struct UsbFnPipeInfo \*info); | Obtains pipe information.| 136e41f4b71Sopenharmony_ci| int32_t UsbFnSetInterfaceProp(const struct UsbFnInterface<br>\*interface, const char \*name, const char \*value); | Sets custom properties.| 137e41f4b71Sopenharmony_ci 138e41f4b71Sopenharmony_ciThe following table lists the APIs for USB data request on the device side. For details about the API definitions, see the [source code](https://gitee.com/openharmony/drivers_peripheral/blob/master/usb/interfaces/ddk/device/usbfn_request.h). 139e41f4b71Sopenharmony_ci 140e41f4b71Sopenharmony_ci **Table 5** APIs for USB data request on the device side 141e41f4b71Sopenharmony_ci 142e41f4b71Sopenharmony_ci| API| Description| 143e41f4b71Sopenharmony_ci| -------- | -------- | 144e41f4b71Sopenharmony_ci| struct UsbFnRequest<br>\*UsbFnAllocCtrlRequest(UsbFnInterfaceHandle handle,<br>uint32_t len); | Allocates a control transfer request.| 145e41f4b71Sopenharmony_ci| struct UsbFnRequest \*UsbFnAllocRequest(UsbFnInterfaceHandle handle,<br>uint8_t pipe, uint32_t len); | Allocates a data request.| 146e41f4b71Sopenharmony_ci| int32_t UsbFnFreeRequest(struct UsbFnRequest \*req); | Releases a request.| 147e41f4b71Sopenharmony_ci| int32_t UsbFnSubmitRequestAsync(struct UsbFnRequest<br>\*req); | Sends an asynchronous request.| 148e41f4b71Sopenharmony_ci| int32_t UsbFnSubmitRequestSync(struct UsbFnRequest<br>\*req, uint32_t timeout); | Sends a synchronous request.| 149e41f4b71Sopenharmony_ci| int32_t UsbFnCancelRequest(struct UsbFnRequest \*req); | Cancels a request.| 150e41f4b71Sopenharmony_ci 151e41f4b71Sopenharmony_ci 152e41f4b71Sopenharmony_ci### How to Develop 153e41f4b71Sopenharmony_ci 154e41f4b71Sopenharmony_ciUSB drivers are developed based on the Hardware Driver Foundation (HDF), platform, and Operating System Abstraction Layer (OSAL) APIs. A unified driver model is provided for USB devices, irrespective of the operating system and chip architecture. This section uses the serial port as an example to describe how to develop USB host and USB device drivers. 155e41f4b71Sopenharmony_ci 156e41f4b71Sopenharmony_ci#### Developing Driver Using Host DDK APIs 157e41f4b71Sopenharmony_ci 158e41f4b71Sopenharmony_ci1. Configure USB host driver information in the .hcs file of private device data. 159e41f4b71Sopenharmony_ci 160e41f4b71Sopenharmony_ci ```cpp 161e41f4b71Sopenharmony_ci root { 162e41f4b71Sopenharmony_ci module = "usb_pnp_device"; 163e41f4b71Sopenharmony_ci usb_pnp_config { 164e41f4b71Sopenharmony_ci match_attr = "usb_pnp_match"; 165e41f4b71Sopenharmony_ci usb_pnp_device_id = "UsbPnpDeviceId"; 166e41f4b71Sopenharmony_ci UsbPnpDeviceId { 167e41f4b71Sopenharmony_ci idTableList = [ 168e41f4b71Sopenharmony_ci "host_acm_table" 169e41f4b71Sopenharmony_ci ]; 170e41f4b71Sopenharmony_ci host_acm_table { 171e41f4b71Sopenharmony_ci // Driver module name, which must be the same as the value of moduleName in the driver entry structure. 172e41f4b71Sopenharmony_ci moduleName = "usbhost_acm"; 173e41f4b71Sopenharmony_ci // Service name of the driver, which must be unique. 174e41f4b71Sopenharmony_ci serviceName = "usbhost_acm_pnp_service"; 175e41f4b71Sopenharmony_ci // Keyword for matching private driver data. 176e41f4b71Sopenharmony_ci deviceMatchAttr = "usbhost_acm_pnp_matchAttr"; 177e41f4b71Sopenharmony_ci // Data length starting from this field, in bytes. 178e41f4b71Sopenharmony_ci length = 21; 179e41f4b71Sopenharmony_ci // USB driver matching rule: vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber. 180e41f4b71Sopenharmony_ci matchFlag = 0x0303; 181e41f4b71Sopenharmony_ci // Vendor ID. 182e41f4b71Sopenharmony_ci vendorId = 0x12D1; 183e41f4b71Sopenharmony_ci // Product ID. 184e41f4b71Sopenharmony_ci productId = 0x5000; 185e41f4b71Sopenharmony_ci // The least significant 16 bits of the device sequence number. 186e41f4b71Sopenharmony_ci bcdDeviceLow = 0x0000; 187e41f4b71Sopenharmony_ci // The most significant 16 bits of the device sequence number. 188e41f4b71Sopenharmony_ci bcdDeviceHigh = 0x0000; 189e41f4b71Sopenharmony_ci // Device class code allocated by the USB. 190e41f4b71Sopenharmony_ci deviceClass = 0; 191e41f4b71Sopenharmony_ci // Child class code allocated by the USB. 192e41f4b71Sopenharmony_ci deviceSubClass = 0; 193e41f4b71Sopenharmony_ci // Device protocol code allocated by the USB. 194e41f4b71Sopenharmony_ci deviceProtocol = 0; 195e41f4b71Sopenharmony_ci // Interface type. You can enter multiple types as needed. 196e41f4b71Sopenharmony_ci interfaceClass = [0]; 197e41f4b71Sopenharmony_ci // Interface subtype. You can enter multiple subtypes as needed. 198e41f4b71Sopenharmony_ci interfaceSubClass = [2, 0]; 199e41f4b71Sopenharmony_ci // Protocol that the interface complies with. You can enter multiple protocols as needed. 200e41f4b71Sopenharmony_ci interfaceProtocol = [1, 2]; 201e41f4b71Sopenharmony_ci // Interface number. You can enter multiple interface numbers as needed. 202e41f4b71Sopenharmony_ci interfaceNumber = [2, 3]; 203e41f4b71Sopenharmony_ci } 204e41f4b71Sopenharmony_ci } 205e41f4b71Sopenharmony_ci } 206e41f4b71Sopenharmony_ci } 207e41f4b71Sopenharmony_ci ``` 208e41f4b71Sopenharmony_ci 209e41f4b71Sopenharmony_ci2. Initialize the USB host driver DDK. 210e41f4b71Sopenharmony_ci 211e41f4b71Sopenharmony_ci ```cpp 212e41f4b71Sopenharmony_ci int32_t UsbInitHostSdk(struct UsbSession **session); 213e41f4b71Sopenharmony_ci ``` 214e41f4b71Sopenharmony_ci 215e41f4b71Sopenharmony_ci3. Obtain the **UsbInterface** object after initialization. 216e41f4b71Sopenharmony_ci 217e41f4b71Sopenharmony_ci ```cpp 218e41f4b71Sopenharmony_ci const struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex); 219e41f4b71Sopenharmony_ci ``` 220e41f4b71Sopenharmony_ci 221e41f4b71Sopenharmony_ci4. Open the **UsbInterface** object to obtain the **UsbInterfaceHandle** object. 222e41f4b71Sopenharmony_ci 223e41f4b71Sopenharmony_ci ```cpp 224e41f4b71Sopenharmony_ci UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj); 225e41f4b71Sopenharmony_ci ``` 226e41f4b71Sopenharmony_ci 227e41f4b71Sopenharmony_ci5. Obtain pipe information of the specified **pipeIndex** based on the **UsbInterfaceHandle** object. 228e41f4b71Sopenharmony_ci 229e41f4b71Sopenharmony_ci ```cpp 230e41f4b71Sopenharmony_ci int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo); 231e41f4b71Sopenharmony_ci ``` 232e41f4b71Sopenharmony_ci 233e41f4b71Sopenharmony_ci6. Pre-allocate an I/O request for the **UsbInterfaceHandle** object. 234e41f4b71Sopenharmony_ci 235e41f4b71Sopenharmony_ci ```cpp 236e41f4b71Sopenharmony_ci struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int32_t isoPackets, int32_t length); 237e41f4b71Sopenharmony_ci ``` 238e41f4b71Sopenharmony_ci 239e41f4b71Sopenharmony_ci7. Fill in the I/O request based on the input parameters. 240e41f4b71Sopenharmony_ci 241e41f4b71Sopenharmony_ci ```cpp 242e41f4b71Sopenharmony_ci int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params); 243e41f4b71Sopenharmony_ci ``` 244e41f4b71Sopenharmony_ci 245e41f4b71Sopenharmony_ci8. Submit the I/O request in synchronous or asynchronous mode. 246e41f4b71Sopenharmony_ci 247e41f4b71Sopenharmony_ci ```cpp 248e41f4b71Sopenharmony_ci int32_t UsbSubmitRequestSync(const struct UsbRequest *request); // Send a synchronous I/O request. 249e41f4b71Sopenharmony_ci int32_t UsbSubmitRequestAsync(const struct UsbRequest *request); // Send an asynchronous I/O request. 250e41f4b71Sopenharmony_ci ``` 251e41f4b71Sopenharmony_ci 252e41f4b71Sopenharmony_ci#### Developing Driver Using Host Raw APIs 253e41f4b71Sopenharmony_ci 254e41f4b71Sopenharmony_ci1. Configure USB host driver information in the .hcs file of private device data. For details, see step 1 in the previous section. 255e41f4b71Sopenharmony_ci 256e41f4b71Sopenharmony_ci2. Initialize the host raw data, open the USB device, obtain the descriptor, and then obtain interface and endpoint information based on the descriptor. 257e41f4b71Sopenharmony_ci 258e41f4b71Sopenharmony_ci ```cpp 259e41f4b71Sopenharmony_ci int32_t UsbRawInit(struct UsbSession **session); 260e41f4b71Sopenharmony_ci ``` 261e41f4b71Sopenharmony_ci 262e41f4b71Sopenharmony_ci3. Open the USB device. 263e41f4b71Sopenharmony_ci 264e41f4b71Sopenharmony_ci ```cpp 265e41f4b71Sopenharmony_ci UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr); 266e41f4b71Sopenharmony_ci ``` 267e41f4b71Sopenharmony_ci 268e41f4b71Sopenharmony_ci4. Obtain the device descriptor, and obtain the interface and endpoint information based on the descriptor. 269e41f4b71Sopenharmony_ci 270e41f4b71Sopenharmony_ci ```cpp 271e41f4b71Sopenharmony_ci int32_t UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config); 272e41f4b71Sopenharmony_ci ``` 273e41f4b71Sopenharmony_ci 274e41f4b71Sopenharmony_ci5. Allocate a request and fill in the request based on the transfer type. 275e41f4b71Sopenharmony_ci 276e41f4b71Sopenharmony_ci ```cpp 277e41f4b71Sopenharmony_ci int32_t UsbRawFillBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // Populate the request for bulk transfer. 278e41f4b71Sopenharmony_ci int32_t UsbRawFillControlSetup(const unsigned char *setup, const struct UsbControlRequestData *requestData); 279e41f4b71Sopenharmony_ci int32_t UsbRawFillControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // Populate the request for control transfer. 280e41f4b71Sopenharmony_ci int32_t UsbRawFillInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // Populate the request for interrupt transfer. 281e41f4b71Sopenharmony_ci int32_t UsbRawFillIsoRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // Populate the request for isochronous transfer. 282e41f4b71Sopenharmony_ci ``` 283e41f4b71Sopenharmony_ci 284e41f4b71Sopenharmony_ci6. Submit the I/O request in synchronous or asynchronous mode. 285e41f4b71Sopenharmony_ci 286e41f4b71Sopenharmony_ci ```cpp 287e41f4b71Sopenharmony_ci int32_t UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData); // Send a synchronous request for control transfer. 288e41f4b71Sopenharmony_ci int32_t UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData); // Send a synchronous request for bulk transfer. 289e41f4b71Sopenharmony_ci int32_t UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData); // Send a synchronous request for interrupt transfer. 290e41f4b71Sopenharmony_ci int32_t UsbRawSubmitRequest(const struct UsbRawRequest *request); // Send an asynchronous I/O request. 291e41f4b71Sopenharmony_ci ``` 292e41f4b71Sopenharmony_ci 293e41f4b71Sopenharmony_ci#### Developing Driver Using Device DDK APIs 294e41f4b71Sopenharmony_ci 295e41f4b71Sopenharmony_ci1. Construct a descriptor in the device function code. 296e41f4b71Sopenharmony_ci 297e41f4b71Sopenharmony_ci ```cpp 298e41f4b71Sopenharmony_ci static struct UsbFnFunction g_acmFunction = { // Function descriptor 299e41f4b71Sopenharmony_ci .enable = true, 300e41f4b71Sopenharmony_ci .funcName = "f_generic.a", 301e41f4b71Sopenharmony_ci .strings = g_acmStrings, 302e41f4b71Sopenharmony_ci .fsDescriptors = g_acmFsFunction, 303e41f4b71Sopenharmony_ci .hsDescriptors = g_acmHsFunction, 304e41f4b71Sopenharmony_ci .ssDescriptors = g_acmSsFunction, 305e41f4b71Sopenharmony_ci .sspDescriptors = NULL, 306e41f4b71Sopenharmony_ci }; 307e41f4b71Sopenharmony_ci struct UsbFnFunction *g_functions[] = { 308e41f4b71Sopenharmony_ci #ifdef CDC_ECM 309e41f4b71Sopenharmony_ci &g_ecmFunction, 310e41f4b71Sopenharmony_ci #endif 311e41f4b71Sopenharmony_ci #ifdef CDC_ACM 312e41f4b71Sopenharmony_ci &g_acmFunction, 313e41f4b71Sopenharmony_ci #endif 314e41f4b71Sopenharmony_ci NULL 315e41f4b71Sopenharmony_ci }; 316e41f4b71Sopenharmony_ci static struct UsbFnConfiguration g_masterConfig = { // Configuration descriptor 317e41f4b71Sopenharmony_ci .configurationValue = 1, 318e41f4b71Sopenharmony_ci .iConfiguration = USB_FUNC_CONFIG_IDX, 319e41f4b71Sopenharmony_ci .attributes = USB_CFG_BUS_POWERED, 320e41f4b71Sopenharmony_ci .maxPower = POWER, 321e41f4b71Sopenharmony_ci .functions = g_functions, 322e41f4b71Sopenharmony_ci }; 323e41f4b71Sopenharmony_ci static struct UsbFnConfiguration *g_configs[] = { 324e41f4b71Sopenharmony_ci &g_masterConfig, 325e41f4b71Sopenharmony_ci NULL, 326e41f4b71Sopenharmony_ci }; 327e41f4b71Sopenharmony_ci static struct UsbDeviceDescriptor g_cdcMasterDeviceDesc = { // Device descriptor 328e41f4b71Sopenharmony_ci .bLength = sizeof(g_cdcMasterDeviceDesc), 329e41f4b71Sopenharmony_ci .bDescriptorType = USB_DDK_DT_DEVICE, 330e41f4b71Sopenharmony_ci .bcdUSB = CpuToLe16(BCD_USB), 331e41f4b71Sopenharmony_ci .bDeviceClass = 0, 332e41f4b71Sopenharmony_ci .bDeviceSubClass = 0, 333e41f4b71Sopenharmony_ci .bDeviceProtocol = 0, 334e41f4b71Sopenharmony_ci .bMaxPacketSize0 = USB_MAX_PACKET_SIZE, 335e41f4b71Sopenharmony_ci .idVendor = CpuToLe16(DEVICE_VENDOR_ID), 336e41f4b71Sopenharmony_ci .idProduct = CpuToLe16(DEVICE_PRODUCT_ID), 337e41f4b71Sopenharmony_ci .bcdDevice = CpuToLe16(DEVICE_VERSION), 338e41f4b71Sopenharmony_ci .iManufacturer = USB_FUNC_MANUFACTURER_IDX, 339e41f4b71Sopenharmony_ci .iProduct = USB_FUNC_PRODUCT_IDX, 340e41f4b71Sopenharmony_ci .iSerialNumber = USB_FUNC_SERIAL_IDX, 341e41f4b71Sopenharmony_ci .bNumConfigurations = 1, 342e41f4b71Sopenharmony_ci }; 343e41f4b71Sopenharmony_ci static struct UsbFnDeviceDesc g_masterFuncDevice = { // Descriptor entry 344e41f4b71Sopenharmony_ci .deviceDesc = &g_cdcMasterDeviceDesc, 345e41f4b71Sopenharmony_ci .deviceStrings = g_devStrings, 346e41f4b71Sopenharmony_ci .configs = g_configs, 347e41f4b71Sopenharmony_ci }; 348e41f4b71Sopenharmony_ci ``` 349e41f4b71Sopenharmony_ci 350e41f4b71Sopenharmony_ci2. Create a USB device. Call **UsbFnDeviceCreate** and pass in the UDC controller and **UsbFnDescriptorData** structure to create a USB device. 351e41f4b71Sopenharmony_ci 352e41f4b71Sopenharmony_ci ```cpp 353e41f4b71Sopenharmony_ci if (useHcs == 0) { // Descriptor written in the code. 354e41f4b71Sopenharmony_ci descData.type = USBFN_DESC_DATA_TYPE_DESC; 355e41f4b71Sopenharmony_ci descData.descriptor = &g_acmFuncDevice; 356e41f4b71Sopenharmony_ci } else { // Descriptor compiled by using the .hcs file. 357e41f4b71Sopenharmony_ci descData.type = USBFN_DESC_DATA_TYPE_PROP; 358e41f4b71Sopenharmony_ci descData.property = acm->device->property; 359e41f4b71Sopenharmony_ci } 360e41f4b71Sopenharmony_ci // Create a USB device. 361e41f4b71Sopenharmony_ci fnDev = (struct UsbFnDevice *) UsbFnCreateDevice(acm->udcName, &descData); 362e41f4b71Sopenharmony_ci ``` 363e41f4b71Sopenharmony_ci 364e41f4b71Sopenharmony_ci3. Call **UsbFnGetInterface** to obtain a **UsbInterface** object, and call **UsbFnGetInterfacePipeInfo** to obtain the USB pipe information. 365e41f4b71Sopenharmony_ci 366e41f4b71Sopenharmony_ci ```cpp 367e41f4b71Sopenharmony_ci // Obtain an interface. 368e41f4b71Sopenharmony_ci fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i); 369e41f4b71Sopenharmony_ci // Obtain the pipe information. 370e41f4b71Sopenharmony_ci UsbFnGetInterfacePipeInfo(fnIface, i, &pipeInfo); 371e41f4b71Sopenharmony_ci // Obtain a handle. 372e41f4b71Sopenharmony_ci handle = UsbFnOpenInterface(fnIface); 373e41f4b71Sopenharmony_ci // Obtain a control (EP0) request. 374e41f4b71Sopenharmony_ci req = UsbFnAllocCtrlRequest(acm->ctrlIface.handle, 375e41f4b71Sopenharmony_ci sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding)); 376e41f4b71Sopenharmony_ci // Obtain the request. 377e41f4b71Sopenharmony_ci req = UsbFnAllocCtrlRequest(acm->ctrlIface.handle, 378e41f4b71Sopenharmony_ci sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding)); 379e41f4b71Sopenharmony_ci ``` 380e41f4b71Sopenharmony_ci 381e41f4b71Sopenharmony_ci4. Call **UsbFnStartRecvInterfaceEvent** to receive events, and call **UsbFnEventCallback** to respond to the events. 382e41f4b71Sopenharmony_ci 383e41f4b71Sopenharmony_ci ```cpp 384e41f4b71Sopenharmony_ci // Start receiving events. 385e41f4b71Sopenharmony_ci ret = UsbFnStartRecvInterfaceEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm); 386e41f4b71Sopenharmony_ci // Process the event in the callback. 387e41f4b71Sopenharmony_ci static void UsbAcmEventCallback(struct UsbFnEvent *event) 388e41f4b71Sopenharmony_ci { 389e41f4b71Sopenharmony_ci struct UsbAcmDevice *acm = NULL; 390e41f4b71Sopenharmony_ci if (event == NULL || event->context == NULL) { 391e41f4b71Sopenharmony_ci HDF_LOGE("%s: event is null", __func__); 392e41f4b71Sopenharmony_ci return; 393e41f4b71Sopenharmony_ci } 394e41f4b71Sopenharmony_ci 395e41f4b71Sopenharmony_ci acm = (struct UsbAcmDevice *)event->context; 396e41f4b71Sopenharmony_ci switch (event->type) { 397e41f4b71Sopenharmony_ci case USBFN_STATE_BIND: 398e41f4b71Sopenharmony_ci HDF_LOGI("%s: receive bind event", __func__); 399e41f4b71Sopenharmony_ci break; 400e41f4b71Sopenharmony_ci case USBFN_STATE_UNBIND: 401e41f4b71Sopenharmony_ci HDF_LOGI("%s: receive unbind event", __func__); 402e41f4b71Sopenharmony_ci break; 403e41f4b71Sopenharmony_ci case USBFN_STATE_ENABLE: 404e41f4b71Sopenharmony_ci HDF_LOGI("%s: receive enable event", __func__); 405e41f4b71Sopenharmony_ci AcmEnable(acm); 406e41f4b71Sopenharmony_ci break; 407e41f4b71Sopenharmony_ci case USBFN_STATE_DISABLE: 408e41f4b71Sopenharmony_ci HDF_LOGI("%s: receive disable event", __func__); 409e41f4b71Sopenharmony_ci AcmDisable(acm); 410e41f4b71Sopenharmony_ci acm->enableEvtCnt = 0; 411e41f4b71Sopenharmony_ci break; 412e41f4b71Sopenharmony_ci case USBFN_STATE_SETUP: 413e41f4b71Sopenharmony_ci HDF_LOGI("%s: receive setup event", __func__); 414e41f4b71Sopenharmony_ci if (event->setup != NULL) { 415e41f4b71Sopenharmony_ci AcmSetup(acm, event->setup); 416e41f4b71Sopenharmony_ci } 417e41f4b71Sopenharmony_ci break; 418e41f4b71Sopenharmony_ci case USBFN_STATE_SUSPEND: 419e41f4b71Sopenharmony_ci HDF_LOGI("%s: receive suspend event", __func__); 420e41f4b71Sopenharmony_ci AcmSuspend(acm); 421e41f4b71Sopenharmony_ci break; 422e41f4b71Sopenharmony_ci case USBFN_STATE_RESUME: 423e41f4b71Sopenharmony_ci HDF_LOGI("%s: receive resume event", __func__); 424e41f4b71Sopenharmony_ci AcmResume(acm); 425e41f4b71Sopenharmony_ci break; 426e41f4b71Sopenharmony_ci default: 427e41f4b71Sopenharmony_ci break; 428e41f4b71Sopenharmony_ci } 429e41f4b71Sopenharmony_ci } 430e41f4b71Sopenharmony_ci ``` 431e41f4b71Sopenharmony_ci 432e41f4b71Sopenharmony_ci5. Send and receive data in synchronously or asynchronously. 433e41f4b71Sopenharmony_ci 434e41f4b71Sopenharmony_ci ```cpp 435e41f4b71Sopenharmony_ci notify = (struct UsbCdcNotification *)req->buf; 436e41f4b71Sopenharmony_ci ... 437e41f4b71Sopenharmony_ci if (memcpy_s((void *)(notify + 1), length, data, length) != EOK) { 438e41f4b71Sopenharmony_ci return HDF_FAILURE; 439e41f4b71Sopenharmony_ci } 440e41f4b71Sopenharmony_ci ret = UsbFnSubmitRequestAsync(req); // Send data asynchronously. 441e41f4b71Sopenharmony_ci ``` 442e41f4b71Sopenharmony_ci 443e41f4b71Sopenharmony_ci### Development Example 444e41f4b71Sopenharmony_ci 445e41f4b71Sopenharmony_ciThe following example helps you better understand the development of the USB serial port driver. 446e41f4b71Sopenharmony_ci 447e41f4b71Sopenharmony_ci#### Developing Driver Using Host DDK APIs 448e41f4b71Sopenharmony_ci 449e41f4b71Sopenharmony_ci```cpp 450e41f4b71Sopenharmony_ci#include "usb_serial.h" 451e41f4b71Sopenharmony_ci#include "hdf_base.h" 452e41f4b71Sopenharmony_ci#include "hdf_log.h" 453e41f4b71Sopenharmony_ci#include "osal_mem.h" 454e41f4b71Sopenharmony_ci#include "osal_time.h" 455e41f4b71Sopenharmony_ci#include "securec.h" 456e41f4b71Sopenharmony_ci#include "usb_ddk_interface.h" 457e41f4b71Sopenharmony_ci#include "hdf_usb_pnp_manage.h" 458e41f4b71Sopenharmony_ci 459e41f4b71Sopenharmony_ci#define HDF_LOG_TAG USB_HOST_ACM 460e41f4b71Sopenharmony_ci#define STR_LEN 512 461e41f4b71Sopenharmony_ci 462e41f4b71Sopenharmony_cistatic struct UsbRequest *g_syncRequest = NULL; // Define a USB request. 463e41f4b71Sopenharmony_cistatic struct UsbRequest *g_ctrlCmdRequest = NULL; 464e41f4b71Sopenharmony_cistatic bool g_acmReleaseFlag = false; 465e41f4b71Sopenharmony_cistatic uint8_t *g_acmReadBuffer = NULL; 466e41f4b71Sopenharmony_ci... 467e41f4b71Sopenharmony_cistatic int32_t SerialCtrlMsg(struct AcmDevice *acm, uint8_t request, 468e41f4b71Sopenharmony_ci uint16_t value, void *buf, uint16_t len) 469e41f4b71Sopenharmony_ci{ 470e41f4b71Sopenharmony_ci int32_t ret; 471e41f4b71Sopenharmony_ci uint16_t index = acm->intPipe->interfaceId; 472e41f4b71Sopenharmony_ci struct UsbControlParams controlParams; 473e41f4b71Sopenharmony_ci struct UsbRequestParams params; // Define a UsbRequestParams object. 474e41f4b71Sopenharmony_ci if (acm == NULL || buf == NULL) { 475e41f4b71Sopenharmony_ci return HDF_ERR_IO; 476e41f4b71Sopenharmony_ci } 477e41f4b71Sopenharmony_ci if (acm->ctrlReq == NULL) { 478e41f4b71Sopenharmony_ci // Pre-allocate the IO Request object to be sent to UsbInterfaceHandle. 479e41f4b71Sopenharmony_ci acm->ctrlReq = UsbAllocRequest(acm->ctrDevHandle, 0, len); 480e41f4b71Sopenharmony_ci if (acm->ctrlReq == NULL) { 481e41f4b71Sopenharmony_ci return HDF_ERR_IO; 482e41f4b71Sopenharmony_ci } 483e41f4b71Sopenharmony_ci } 484e41f4b71Sopenharmony_ci 485e41f4b71Sopenharmony_ci controlParams.request = request; 486e41f4b71Sopenharmony_ci controlParams.target = USB_REQUEST_TARGET_INTERFACE; // Interface object 487e41f4b71Sopenharmony_ci controlParams.reqType = USB_REQUEST_TYPE_CLASS; // Request type 488e41f4b71Sopenharmony_ci controlParams.direction = USB_REQUEST_DIR_TO_DEVICE; // Data transfer from the host to the device 489e41f4b71Sopenharmony_ci controlParams.value = value; 490e41f4b71Sopenharmony_ci controlParams.index = index; 491e41f4b71Sopenharmony_ci controlParams.data = buf; 492e41f4b71Sopenharmony_ci controlParams.size = len; 493e41f4b71Sopenharmony_ci 494e41f4b71Sopenharmony_ci params.interfaceId = USB_CTRL_INTERFACE_ID; // Define the default ID of the USB control interface. 495e41f4b71Sopenharmony_ci params.pipeAddress = acm->ctrPipe->pipeAddress; 496e41f4b71Sopenharmony_ci params.pipeId = acm->ctrPipe->pipeId; 497e41f4b71Sopenharmony_ci params.requestType = USB_REQUEST_PARAMS_CTRL_TYPE; // Control type. 498e41f4b71Sopenharmony_ci params.timeout = USB_CTRL_SET_TIMEOUT; // Set the timeout interval. 499e41f4b71Sopenharmony_ci params.ctrlReq = UsbControlSetUp(&controlParams); 500e41f4b71Sopenharmony_ci // Fill in the pre-allocated I/O request based on UsbRequestParams. 501e41f4b71Sopenharmony_ci ret = UsbFillRequest(acm->ctrlReq, acm->ctrDevHandle, ¶ms); 502e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 503e41f4b71Sopenharmony_ci return ret; 504e41f4b71Sopenharmony_ci } 505e41f4b71Sopenharmony_ci // Send an I/O request synchronously. 506e41f4b71Sopenharmony_ci ret = UsbSubmitRequestSync(acm->ctrlReq); 507e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 508e41f4b71Sopenharmony_ci return ret; 509e41f4b71Sopenharmony_ci } 510e41f4b71Sopenharmony_ci if (!acm->ctrlReq->compInfo.status) { 511e41f4b71Sopenharmony_ci HDF_LOGE("%s status=%d ", __func__, acm->ctrlReq->compInfo.status); 512e41f4b71Sopenharmony_ci } 513e41f4b71Sopenharmony_ci return HDF_SUCCESS; 514e41f4b71Sopenharmony_ci} 515e41f4b71Sopenharmony_ci... 516e41f4b71Sopenharmony_cistatic struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm, 517e41f4b71Sopenharmony_ci uint8_t interfaceIndex) 518e41f4b71Sopenharmony_ci{ 519e41f4b71Sopenharmony_ci struct UsbInterface *tmpIf = NULL; 520e41f4b71Sopenharmony_ci // Obtain a UsbInterface object. 521e41f4b71Sopenharmony_ci tmpIf = (struct UsbInterface *)UsbClaimInterface(acm->session, acm->busNum, acm->devAddr, interfaceIndex); 522e41f4b71Sopenharmony_ci return tmpIf; 523e41f4b71Sopenharmony_ci} 524e41f4b71Sopenharmony_ci... 525e41f4b71Sopenharmony_cistatic struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm, 526e41f4b71Sopenharmony_ci uint8_t interfaceIndex, UsbPipeType pipeType, UsbPipeDirection pipeDirection) 527e41f4b71Sopenharmony_ci{ 528e41f4b71Sopenharmony_ci uint8_t i; 529e41f4b71Sopenharmony_ci int32_t ret; 530e41f4b71Sopenharmony_ci struct UsbInterfaceInfo *info = NULL; // Define a UsbInterfaceInfo object. 531e41f4b71Sopenharmony_ci UsbInterfaceHandle *interfaceHandle = NULL; // Define a USB interface operation handle (that is, the void * type). 532e41f4b71Sopenharmony_ci if (pipeType == USB_PIPE_TYPE_CONTROL) 533e41f4b71Sopenharmony_ci { 534e41f4b71Sopenharmony_ci info = &acm->ctrIface->info; 535e41f4b71Sopenharmony_ci interfaceHandle = acm->ctrDevHandle; 536e41f4b71Sopenharmony_ci } 537e41f4b71Sopenharmony_ci else 538e41f4b71Sopenharmony_ci { 539e41f4b71Sopenharmony_ci info = &acm->iface[interfaceIndex]->info; 540e41f4b71Sopenharmony_ci // Obtain the device handle based on interfaceIndex. 541e41f4b71Sopenharmony_ci interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex); 542e41f4b71Sopenharmony_ci } 543e41f4b71Sopenharmony_ci 544e41f4b71Sopenharmony_ci for (i = 0; i <= info->pipeNum; i++) { 545e41f4b71Sopenharmony_ci struct UsbPipeInfo p; 546e41f4b71Sopenharmony_ci // Obtain the pipeInfo object whose index is i. 547e41f4b71Sopenharmony_ci ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p); 548e41f4b71Sopenharmony_ci if (ret < 0) { 549e41f4b71Sopenharmony_ci continue; 550e41f4b71Sopenharmony_ci } 551e41f4b71Sopenharmony_ci if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) { 552e41f4b71Sopenharmony_ci struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi)); // Allocate and initialize the memory. 553e41f4b71Sopenharmony_ci if (pi == NULL) { 554e41f4b71Sopenharmony_ci return NULL; 555e41f4b71Sopenharmony_ci } 556e41f4b71Sopenharmony_ci p.interfaceId = info->interfaceIndex; 557e41f4b71Sopenharmony_ci *pi = p; 558e41f4b71Sopenharmony_ci return pi; 559e41f4b71Sopenharmony_ci } 560e41f4b71Sopenharmony_ci } 561e41f4b71Sopenharmony_ci return NULL; 562e41f4b71Sopenharmony_ci} 563e41f4b71Sopenharmony_ci 564e41f4b71Sopenharmony_cistatic struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm, 565e41f4b71Sopenharmony_ci UsbPipeType pipeType, UsbPipeDirection pipeDirection) 566e41f4b71Sopenharmony_ci{ 567e41f4b71Sopenharmony_ci uint8_t i; 568e41f4b71Sopenharmony_ci if (acm == NULL) { 569e41f4b71Sopenharmony_ci return NULL; 570e41f4b71Sopenharmony_ci } 571e41f4b71Sopenharmony_ci for (i = 0; i < acm->interfaceCnt; i++) { 572e41f4b71Sopenharmony_ci struct UsbPipeInfo *p = NULL; 573e41f4b71Sopenharmony_ci if (!acm->iface[i]) { 574e41f4b71Sopenharmony_ci continue; 575e41f4b71Sopenharmony_ci } 576e41f4b71Sopenharmony_ci // Obtain pipe information of the control pipe. 577e41f4b71Sopenharmony_ci p = EnumePipe(acm, i, pipeType, pipeDirection); 578e41f4b71Sopenharmony_ci if (p == NULL) { 579e41f4b71Sopenharmony_ci continue; 580e41f4b71Sopenharmony_ci } 581e41f4b71Sopenharmony_ci return p; 582e41f4b71Sopenharmony_ci } 583e41f4b71Sopenharmony_ci return NULL; 584e41f4b71Sopenharmony_ci} 585e41f4b71Sopenharmony_ci 586e41f4b71Sopenharmony_ci/* HdfDriverEntry implementations */ 587e41f4b71Sopenharmony_cistatic int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) 588e41f4b71Sopenharmony_ci{ 589e41f4b71Sopenharmony_ci struct UsbPnpNotifyServiceInfo *info = NULL; 590e41f4b71Sopenharmony_ci errno_t err; 591e41f4b71Sopenharmony_ci struct AcmDevice *acm = NULL; 592e41f4b71Sopenharmony_ci if (device == NULL) { 593e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 594e41f4b71Sopenharmony_ci } 595e41f4b71Sopenharmony_ci acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm)); 596e41f4b71Sopenharmony_ci if (acm == NULL) { 597e41f4b71Sopenharmony_ci return HDF_FAILURE; 598e41f4b71Sopenharmony_ci } 599e41f4b71Sopenharmony_ci // Initialize the mutex. &acm->lock indicates the pointer pointing to the mutex. 600e41f4b71Sopenharmony_ci if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { 601e41f4b71Sopenharmony_ci goto error; 602e41f4b71Sopenharmony_ci } 603e41f4b71Sopenharmony_ci info = (struct UsbPnpNotifyServiceInfo *)device->priv; 604e41f4b71Sopenharmony_ci if (info != NULL) { 605e41f4b71Sopenharmony_ci acm->busNum = info->busNum; 606e41f4b71Sopenharmony_ci acm->devAddr = info->devNum; 607e41f4b71Sopenharmony_ci acm->interfaceCnt = info->interfaceLength; 608e41f4b71Sopenharmony_ci err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, 609e41f4b71Sopenharmony_ci (const void*)info->interfaceNumber, info->interfaceLength); 610e41f4b71Sopenharmony_ci if (err != EOK) { 611e41f4b71Sopenharmony_ci goto lock_error; 612e41f4b71Sopenharmony_ci } 613e41f4b71Sopenharmony_ci } else { 614e41f4b71Sopenharmony_ci goto lock_error; 615e41f4b71Sopenharmony_ci } 616e41f4b71Sopenharmony_ci acm->device = device; 617e41f4b71Sopenharmony_ci device->service = &(acm->service); 618e41f4b71Sopenharmony_ci acm->device->service->Dispatch = UsbSerialDeviceDispatch; 619e41f4b71Sopenharmony_ci return HDF_SUCCESS; 620e41f4b71Sopenharmony_ci 621e41f4b71Sopenharmony_cilock_error: 622e41f4b71Sopenharmony_ci if (OsalMutexDestroy(&acm->lock)) { 623e41f4b71Sopenharmony_ci HDF_LOGE("%s:%d OsalMutexDestroy failed", __func__, __LINE__); 624e41f4b71Sopenharmony_ci } 625e41f4b71Sopenharmony_cierror: 626e41f4b71Sopenharmony_ci OsalMemFree(acm); 627e41f4b71Sopenharmony_ci acm = NULL; 628e41f4b71Sopenharmony_ci return HDF_FAILURE; 629e41f4b71Sopenharmony_ci} 630e41f4b71Sopenharmony_ci... 631e41f4b71Sopenharmony_cistatic int32_t AcmAllocReadRequests(struct AcmDevice *acm) 632e41f4b71Sopenharmony_ci{ 633e41f4b71Sopenharmony_ci int32_t ret; 634e41f4b71Sopenharmony_ci struct UsbRequestParams readParams; 635e41f4b71Sopenharmony_ci for (int32_t i = 0; i < ACM_NR; i++) { 636e41f4b71Sopenharmony_ci // Allocate the readReq I/O request to be sent. 637e41f4b71Sopenharmony_ci acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize); 638e41f4b71Sopenharmony_ci if (!acm->readReq[i]) { 639e41f4b71Sopenharmony_ci goto error; 640e41f4b71Sopenharmony_ci } 641e41f4b71Sopenharmony_ci readParams.userData = (void *)acm; 642e41f4b71Sopenharmony_ci readParams.pipeAddress = acm->dataInPipe->pipeAddress; 643e41f4b71Sopenharmony_ci readParams.pipeId = acm->dataInPipe->pipeId; 644e41f4b71Sopenharmony_ci readParams.interfaceId = acm->dataInPipe->interfaceId; 645e41f4b71Sopenharmony_ci readParams.callback = AcmReadBulk; 646e41f4b71Sopenharmony_ci readParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE; /* Data type */ 647e41f4b71Sopenharmony_ci readParams.timeout = USB_CTRL_SET_TIMEOUT; 648e41f4b71Sopenharmony_ci readParams.dataReq.numIsoPackets = 0; 649e41f4b71Sopenharmony_ci readParams.dataReq.direction = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1; 650e41f4b71Sopenharmony_ci readParams.dataReq.length = acm->readSize; 651e41f4b71Sopenharmony_ci // Fill in the readReq IO Request object to be sent based on readParams. 652e41f4b71Sopenharmony_ci ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParams); 653e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 654e41f4b71Sopenharmony_ci goto error; 655e41f4b71Sopenharmony_ci } 656e41f4b71Sopenharmony_ci } 657e41f4b71Sopenharmony_ci return HDF_SUCCESS; 658e41f4b71Sopenharmony_ci 659e41f4b71Sopenharmony_cierror: 660e41f4b71Sopenharmony_ci AcmFreeReadRequests(acm); 661e41f4b71Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 662e41f4b71Sopenharmony_ci} 663e41f4b71Sopenharmony_ci 664e41f4b71Sopenharmony_cistatic int32_t AcmAllocNotifyRequest(struct AcmDevice *acm) 665e41f4b71Sopenharmony_ci{ 666e41f4b71Sopenharmony_ci int32_t ret; 667e41f4b71Sopenharmony_ci struct UsbRequestParams intParams = {}; 668e41f4b71Sopenharmony_ci // Allocate the interrupt I/O request to be sent. 669e41f4b71Sopenharmony_ci acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize); 670e41f4b71Sopenharmony_ci if (!acm->notifyReq) { 671e41f4b71Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 672e41f4b71Sopenharmony_ci } 673e41f4b71Sopenharmony_ci intParams.userData = (void *)acm; 674e41f4b71Sopenharmony_ci intParams.pipeAddress = acm->intPipe->pipeAddress; 675e41f4b71Sopenharmony_ci intParams.pipeId = acm->intPipe->pipeId; 676e41f4b71Sopenharmony_ci intParams.interfaceId = acm->intPipe->interfaceId; 677e41f4b71Sopenharmony_ci intParams.callback = AcmCtrlIrq; 678e41f4b71Sopenharmony_ci intParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE; 679e41f4b71Sopenharmony_ci intParams.timeout = USB_CTRL_SET_TIMEOUT; 680e41f4b71Sopenharmony_ci intParams.dataReq.numIsoPackets = 0; 681e41f4b71Sopenharmony_ci intParams.dataReq.direction = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK; 682e41f4b71Sopenharmony_ci intParams.dataReq.length = acm->intSize; 683e41f4b71Sopenharmony_ci // Fill in the interrupt I/O request. 684e41f4b71Sopenharmony_ci ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParams); 685e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 686e41f4b71Sopenharmony_ci goto error; 687e41f4b71Sopenharmony_ci } 688e41f4b71Sopenharmony_ci return HDF_SUCCESS; 689e41f4b71Sopenharmony_ci 690e41f4b71Sopenharmony_cierror: 691e41f4b71Sopenharmony_ci AcmFreeNotifyRequest(acm); 692e41f4b71Sopenharmony_ci return ret; 693e41f4b71Sopenharmony_ci} 694e41f4b71Sopenharmony_ci 695e41f4b71Sopenharmony_cistatic void AcmReleaseInterfaces(struct AcmDevice *acm) 696e41f4b71Sopenharmony_ci{ 697e41f4b71Sopenharmony_ci for (int32_t i = 0; i < acm->interfaceCnt; i++) { 698e41f4b71Sopenharmony_ci if (acm->iface[i]) { 699e41f4b71Sopenharmony_ci // Release a USB interface object. 700e41f4b71Sopenharmony_ci UsbReleaseInterface(acm->iface[i]); 701e41f4b71Sopenharmony_ci acm->iface[i] = NULL; 702e41f4b71Sopenharmony_ci } 703e41f4b71Sopenharmony_ci } 704e41f4b71Sopenharmony_ci if (acm->ctrIface) { 705e41f4b71Sopenharmony_ci UsbReleaseInterface(acm->ctrIface); 706e41f4b71Sopenharmony_ci acm->ctrIface = NULL; 707e41f4b71Sopenharmony_ci } 708e41f4b71Sopenharmony_ci} 709e41f4b71Sopenharmony_ci 710e41f4b71Sopenharmony_cistatic int32_t AcmClaimInterfaces(struct AcmDevice *acm) 711e41f4b71Sopenharmony_ci{ 712e41f4b71Sopenharmony_ci for (int32_t i = 0; i < acm->interfaceCnt; i++) { 713e41f4b71Sopenharmony_ci // Obtain a UsbInterface object. 714e41f4b71Sopenharmony_ci acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]); 715e41f4b71Sopenharmony_ci if (acm->iface[i] == NULL) { 716e41f4b71Sopenharmony_ci goto error; 717e41f4b71Sopenharmony_ci } 718e41f4b71Sopenharmony_ci } 719e41f4b71Sopenharmony_ci 720e41f4b71Sopenharmony_ci // Obtain the UsbInterface object corresponding to the control interface. 721e41f4b71Sopenharmony_ci acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID); 722e41f4b71Sopenharmony_ci if (acm->ctrIface == NULL) { 723e41f4b71Sopenharmony_ci goto error; 724e41f4b71Sopenharmony_ci } 725e41f4b71Sopenharmony_ci 726e41f4b71Sopenharmony_ci return HDF_SUCCESS; 727e41f4b71Sopenharmony_ci 728e41f4b71Sopenharmony_ci error: 729e41f4b71Sopenharmony_ci // Release the UsbInterface object cyclically based on acm->interfaceCnt. 730e41f4b71Sopenharmony_ci AcmReleaseInterfaces(acm); 731e41f4b71Sopenharmony_ci return HDF_FAILURE; 732e41f4b71Sopenharmony_ci} 733e41f4b71Sopenharmony_ci 734e41f4b71Sopenharmony_cistatic void AcmCloseInterfaces(struct AcmDevice *acm) 735e41f4b71Sopenharmony_ci{ 736e41f4b71Sopenharmony_ci for (int32_t i = 0; i < acm->interfaceCnt; i++) { 737e41f4b71Sopenharmony_ci if (acm->devHandle[i]) { 738e41f4b71Sopenharmony_ci // Close a USB device object. 739e41f4b71Sopenharmony_ci UsbCloseInterface(acm->devHandle[i]); 740e41f4b71Sopenharmony_ci acm->devHandle[i] = NULL; 741e41f4b71Sopenharmony_ci } 742e41f4b71Sopenharmony_ci } 743e41f4b71Sopenharmony_ci if (acm->ctrDevHandle) { 744e41f4b71Sopenharmony_ci UsbCloseInterface(acm->ctrDevHandle); 745e41f4b71Sopenharmony_ci acm->ctrDevHandle = NULL; 746e41f4b71Sopenharmony_ci } 747e41f4b71Sopenharmony_ci} 748e41f4b71Sopenharmony_ci 749e41f4b71Sopenharmony_cistatic int32_t AcmOpenInterfaces(struct AcmDevice *acm) 750e41f4b71Sopenharmony_ci{ 751e41f4b71Sopenharmony_ci for (int32_t i = 0; i < acm->interfaceCnt; i++) { 752e41f4b71Sopenharmony_ci if (acm->iface[i]) { 753e41f4b71Sopenharmony_ci // Open the UsbInterface object obtained. 754e41f4b71Sopenharmony_ci acm->devHandle[i] = UsbOpenInterface(acm->iface[i]); 755e41f4b71Sopenharmony_ci if (acm->devHandle[i] == NULL) { 756e41f4b71Sopenharmony_ci goto error; 757e41f4b71Sopenharmony_ci } 758e41f4b71Sopenharmony_ci } 759e41f4b71Sopenharmony_ci } 760e41f4b71Sopenharmony_ci acm->ctrDevHandle = UsbOpenInterface(acm->ctrIface); 761e41f4b71Sopenharmony_ci if (acm->ctrDevHandle == NULL) { 762e41f4b71Sopenharmony_ci goto error; 763e41f4b71Sopenharmony_ci } 764e41f4b71Sopenharmony_ci 765e41f4b71Sopenharmony_ci return HDF_SUCCESS; 766e41f4b71Sopenharmony_ci 767e41f4b71Sopenharmony_cierror: 768e41f4b71Sopenharmony_ci // Disable all UsbInterface objects. 769e41f4b71Sopenharmony_ci AcmCloseInterfaces(acm); 770e41f4b71Sopenharmony_ci return HDF_FAILURE; 771e41f4b71Sopenharmony_ci} 772e41f4b71Sopenharmony_ci 773e41f4b71Sopenharmony_cistatic int32_t AcmGetPipes(struct AcmDevice *acm) 774e41f4b71Sopenharmony_ci{ 775e41f4b71Sopenharmony_ci // Obtain pipe information of dataInPipe. 776e41f4b71Sopenharmony_ci acm->dataInPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN); 777e41f4b71Sopenharmony_ci if (acm->dataInPipe == NULL) { 778e41f4b71Sopenharmony_ci goto error; 779e41f4b71Sopenharmony_ci } 780e41f4b71Sopenharmony_ci 781e41f4b71Sopenharmony_ci // Obtain pipe information of dataOutPipe. 782e41f4b71Sopenharmony_ci acm->dataOutPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT); 783e41f4b71Sopenharmony_ci if (acm->dataOutPipe == NULL) { 784e41f4b71Sopenharmony_ci goto error; 785e41f4b71Sopenharmony_ci } 786e41f4b71Sopenharmony_ci 787e41f4b71Sopenharmony_ci // Obtain pipe information of the control pipe. 788e41f4b71Sopenharmony_ci acm->ctrPipe = EnumePipe(acm, acm->ctrIface->info.interfaceIndex, USB_PIPE_TYPE_CONTROL, USB_PIPE_DIRECTION_OUT); 789e41f4b71Sopenharmony_ci if (acm->ctrPipe == NULL) { 790e41f4b71Sopenharmony_ci goto error; 791e41f4b71Sopenharmony_ci } 792e41f4b71Sopenharmony_ci 793e41f4b71Sopenharmony_ci //Obtain pipe information of the interrupt pipe. 794e41f4b71Sopenharmony_ci acm->intPipe = GetPipe(acm, USB_PIPE_TYPE_INTERRUPT, USB_PIPE_DIRECTION_IN); 795e41f4b71Sopenharmony_ci if (acm->intPipe == NULL) { 796e41f4b71Sopenharmony_ci goto error; 797e41f4b71Sopenharmony_ci } 798e41f4b71Sopenharmony_ci 799e41f4b71Sopenharmony_ci acm->readSize = acm->dataInPipe->maxPacketSize; 800e41f4b71Sopenharmony_ci acm->writeSize = acm->dataOutPipe->maxPacketSize; 801e41f4b71Sopenharmony_ci acm->ctrlSize = acm->ctrPipe->maxPacketSize; 802e41f4b71Sopenharmony_ci acm->intSize = acm->intPipe->maxPacketSize; 803e41f4b71Sopenharmony_ci return HDF_SUCCESS; 804e41f4b71Sopenharmony_ci 805e41f4b71Sopenharmony_cierror: 806e41f4b71Sopenharmony_ci // Release all pipe information on the device. 807e41f4b71Sopenharmony_ci AcmFreePipes(acm); 808e41f4b71Sopenharmony_ci return HDF_FAILURE; 809e41f4b71Sopenharmony_ci} 810e41f4b71Sopenharmony_ci 811e41f4b71Sopenharmony_cistatic void AcmFreeRequests(struct AcmDevice *acm) 812e41f4b71Sopenharmony_ci{ 813e41f4b71Sopenharmony_ci if (g_syncRequest != NULL) { 814e41f4b71Sopenharmony_ci UsbFreeRequest(g_syncRequest); 815e41f4b71Sopenharmony_ci g_syncRequest = NULL; 816e41f4b71Sopenharmony_ci } 817e41f4b71Sopenharmony_ci AcmFreeReadRequests(acm); 818e41f4b71Sopenharmony_ci AcmFreeNotifyRequest(acm); 819e41f4b71Sopenharmony_ci AcmFreeWriteRequests(acm); 820e41f4b71Sopenharmony_ci AcmWriteBufFree(acm); 821e41f4b71Sopenharmony_ci} 822e41f4b71Sopenharmony_ci 823e41f4b71Sopenharmony_cistatic int32_t AcmAllocRequests(struct AcmDevice *acm) 824e41f4b71Sopenharmony_ci{ 825e41f4b71Sopenharmony_ci int32_t ret; 826e41f4b71Sopenharmony_ci 827e41f4b71Sopenharmony_ci if (AcmWriteBufAlloc(acm) < 0) { 828e41f4b71Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 829e41f4b71Sopenharmony_ci } 830e41f4b71Sopenharmony_ci 831e41f4b71Sopenharmony_ci for (int32_t i = 0; i < ACM_NW; i++) { 832e41f4b71Sopenharmony_ci struct AcmWb *snd = &(acm->wb[i]); 833e41f4b71Sopenharmony_ci // Allocate the I/O request to be sent. 834e41f4b71Sopenharmony_ci snd->request = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataOutPipe->interfaceId), 0, acm->writeSize); 835e41f4b71Sopenharmony_ci snd->instance = acm; 836e41f4b71Sopenharmony_ci if (snd->request == NULL) { 837e41f4b71Sopenharmony_ci goto error_alloc_write_req; 838e41f4b71Sopenharmony_ci } 839e41f4b71Sopenharmony_ci } 840e41f4b71Sopenharmony_ci 841e41f4b71Sopenharmony_ci ret = AcmAllocNotifyRequest(acm); // Allocate and fill in the interrupt I/O request. 842e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 843e41f4b71Sopenharmony_ci goto error_alloc_int_req; 844e41f4b71Sopenharmony_ci } 845e41f4b71Sopenharmony_ci 846e41f4b71Sopenharmony_ci ret = AcmAllocReadRequests(acm); // Allocate and fill in the readReq I/O request. 847e41f4b71Sopenharmony_ci if (ret) { 848e41f4b71Sopenharmony_ci goto error_alloc_read_req; 849e41f4b71Sopenharmony_ci } 850e41f4b71Sopenharmony_ci 851e41f4b71Sopenharmony_ci return HDF_SUCCESS; 852e41f4b71Sopenharmony_ci 853e41f4b71Sopenharmony_cierror_alloc_read_req: 854e41f4b71Sopenharmony_ci AcmFreeNotifyRequest(acm); 855e41f4b71Sopenharmony_cierror_alloc_int_req: 856e41f4b71Sopenharmony_ci AcmFreeWriteRequests(acm); 857e41f4b71Sopenharmony_cierror_alloc_write_req: 858e41f4b71Sopenharmony_ci AcmWriteBufFree(acm); 859e41f4b71Sopenharmony_ci return HDF_FAILURE; 860e41f4b71Sopenharmony_ci} 861e41f4b71Sopenharmony_ci 862e41f4b71Sopenharmony_cistatic int32_t AcmInit(struct AcmDevice *acm) 863e41f4b71Sopenharmony_ci{ 864e41f4b71Sopenharmony_ci int32_t ret; 865e41f4b71Sopenharmony_ci struct UsbSession *session = NULL; 866e41f4b71Sopenharmony_ci 867e41f4b71Sopenharmony_ci if (acm->initFlag == true) { 868e41f4b71Sopenharmony_ci return HDF_SUCCESS; 869e41f4b71Sopenharmony_ci } 870e41f4b71Sopenharmony_ci 871e41f4b71Sopenharmony_ci // Initialize the USB Host DDK. 872e41f4b71Sopenharmony_ci ret = UsbInitHostSdk(NULL); 873e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 874e41f4b71Sopenharmony_ci return HDF_ERR_IO; 875e41f4b71Sopenharmony_ci } 876e41f4b71Sopenharmony_ci acm->session = session; 877e41f4b71Sopenharmony_ci 878e41f4b71Sopenharmony_ci // Obtain UsbInterface objects based on acm->interfaceIndex[i]. 879e41f4b71Sopenharmony_ci ret = AcmClaimInterfaces(acm); 880e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 881e41f4b71Sopenharmony_ci goto error_claim_interfaces; 882e41f4b71Sopenharmony_ci } 883e41f4b71Sopenharmony_ci 884e41f4b71Sopenharmony_ci // Open UsbInterface objects based on acm->iface[i]. 885e41f4b71Sopenharmony_ci ret = AcmOpenInterfaces(acm); 886e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 887e41f4b71Sopenharmony_ci goto error_open_interfaces; 888e41f4b71Sopenharmony_ci } 889e41f4b71Sopenharmony_ci 890e41f4b71Sopenharmony_ci // Obtain the pointer to the pipe information. 891e41f4b71Sopenharmony_ci ret = AcmGetPipes(acm); 892e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 893e41f4b71Sopenharmony_ci goto error_get_pipes; 894e41f4b71Sopenharmony_ci } 895e41f4b71Sopenharmony_ci 896e41f4b71Sopenharmony_ci ret = AcmAllocRequests(acm); 897e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 898e41f4b71Sopenharmony_ci goto error_alloc_reqs; 899e41f4b71Sopenharmony_ci } 900e41f4b71Sopenharmony_ci 901e41f4b71Sopenharmony_ci acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); // Convert to little-endian data. 902e41f4b71Sopenharmony_ci acm->lineCoding.bCharFormat = CHARFORMAT; // 8 903e41f4b71Sopenharmony_ci acm->lineCoding.bParityType = USB_CDC_NO_PARITY; 904e41f4b71Sopenharmony_ci acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS; 905e41f4b71Sopenharmony_ci acm->initFlag = true; 906e41f4b71Sopenharmony_ci return HDF_SUCCESS; 907e41f4b71Sopenharmony_ci 908e41f4b71Sopenharmony_cierror_alloc_reqs: 909e41f4b71Sopenharmony_ci AcmFreePipes(acm); 910e41f4b71Sopenharmony_cierror_get_pipes: 911e41f4b71Sopenharmony_ci // Disable all UsbInterface objects. 912e41f4b71Sopenharmony_ci AcmCloseInterfaces(acm); 913e41f4b71Sopenharmony_cierror_open_interfaces: 914e41f4b71Sopenharmony_ci // Release all UsbInterface objects. 915e41f4b71Sopenharmony_ci AcmReleaseInterfaces(acm); 916e41f4b71Sopenharmony_cierror_claim_interfaces: 917e41f4b71Sopenharmony_ci // Exit the USB DDK on the host. acm->session indicates the pointer pointing to the session context. 918e41f4b71Sopenharmony_ci UsbExitHostSdk(acm->session); 919e41f4b71Sopenharmony_ci acm->session = NULL; 920e41f4b71Sopenharmony_ci return ret; 921e41f4b71Sopenharmony_ci} 922e41f4b71Sopenharmony_ci 923e41f4b71Sopenharmony_cistatic void AcmRelease(struct AcmDevice *acm) 924e41f4b71Sopenharmony_ci{ 925e41f4b71Sopenharmony_ci if (acm->initFlag == false) { 926e41f4b71Sopenharmony_ci return; 927e41f4b71Sopenharmony_ci } 928e41f4b71Sopenharmony_ci 929e41f4b71Sopenharmony_ci AcmFreeRequests(acm); 930e41f4b71Sopenharmony_ci AcmFreePipes(acm); 931e41f4b71Sopenharmony_ci AcmCloseInterfaces(acm); 932e41f4b71Sopenharmony_ci AcmReleaseInterfaces(acm); 933e41f4b71Sopenharmony_ci // Exit the USB DDK on the host. 934e41f4b71Sopenharmony_ci UsbExitHostSdk(acm->session); 935e41f4b71Sopenharmony_ci acm->session = NULL; 936e41f4b71Sopenharmony_ci acm->initFlag = false; 937e41f4b71Sopenharmony_ci} 938e41f4b71Sopenharmony_ci 939e41f4b71Sopenharmony_cistatic int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) 940e41f4b71Sopenharmony_ci{ 941e41f4b71Sopenharmony_ci int32_t ret; 942e41f4b71Sopenharmony_ci struct AcmDevice *acm = NULL; 943e41f4b71Sopenharmony_ci 944e41f4b71Sopenharmony_ci if (device == NULL) { 945e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 946e41f4b71Sopenharmony_ci } 947e41f4b71Sopenharmony_ci acm = (struct AcmDevice *)device->service; 948e41f4b71Sopenharmony_ci // Initialize the mutex. &acm->readLock indicates the pointer pointing to the mutex. 949e41f4b71Sopenharmony_ci OsalMutexInit(&acm->readLock); 950e41f4b71Sopenharmony_ci OsalMutexInit(&acm->writeLock); 951e41f4b71Sopenharmony_ci HDF_LOGD("%s:%d busNum=%d,devAddr=%d", __func__, __LINE__, acm->busNum, acm->devAddr); 952e41f4b71Sopenharmony_ci 953e41f4b71Sopenharmony_ci // Allocate space for the USB serial port device information and assign a value. 954e41f4b71Sopenharmony_ci ret = UsbSerialDeviceAlloc(acm); 955e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 956e41f4b71Sopenharmony_ci HDF_LOGE("%s: Serial Device alloc failed", __func__); 957e41f4b71Sopenharmony_ci } 958e41f4b71Sopenharmony_ci 959e41f4b71Sopenharmony_ci acm->initFlag = false; 960e41f4b71Sopenharmony_ci g_acmReleaseFlag = false; 961e41f4b71Sopenharmony_ci return ret; 962e41f4b71Sopenharmony_ci} 963e41f4b71Sopenharmony_ci 964e41f4b71Sopenharmony_cistatic void UsbSerialDriverRelease(struct HdfDeviceObject *device) 965e41f4b71Sopenharmony_ci{ 966e41f4b71Sopenharmony_ci struct AcmDevice *acm = NULL; 967e41f4b71Sopenharmony_ci 968e41f4b71Sopenharmony_ci if (device == NULL) { 969e41f4b71Sopenharmony_ci return; 970e41f4b71Sopenharmony_ci } 971e41f4b71Sopenharmony_ci acm = (struct AcmDevice *)device->service; 972e41f4b71Sopenharmony_ci if (acm == NULL) { 973e41f4b71Sopenharmony_ci return; 974e41f4b71Sopenharmony_ci } 975e41f4b71Sopenharmony_ci 976e41f4b71Sopenharmony_ci g_acmReleaseFlag = true; 977e41f4b71Sopenharmony_ci 978e41f4b71Sopenharmony_ci if (acm->initFlag == true) { 979e41f4b71Sopenharmony_ci AcmRelease(acm); 980e41f4b71Sopenharmony_ci } 981e41f4b71Sopenharmony_ci // Release the USB serial port device information. 982e41f4b71Sopenharmony_ci UsbSeriaDevicelFree(acm); 983e41f4b71Sopenharmony_ci // Release the mutex. 984e41f4b71Sopenharmony_ci OsalMutexDestroy(&acm->writeLock); 985e41f4b71Sopenharmony_ci OsalMutexDestroy(&acm->readLock); 986e41f4b71Sopenharmony_ci OsalMutexDestroy(&acm->lock); 987e41f4b71Sopenharmony_ci OsalMemFree(acm); 988e41f4b71Sopenharmony_ci acm = NULL; 989e41f4b71Sopenharmony_ci} 990e41f4b71Sopenharmony_ci 991e41f4b71Sopenharmony_ci// Perform Bind, Init, and Release operations on the driver. 992e41f4b71Sopenharmony_cistruct HdfDriverEntry g_usbSerialDriverEntry = { 993e41f4b71Sopenharmony_ci .moduleVersion = 1, 994e41f4b71Sopenharmony_ci .moduleName = "usbhost_acm", // Driver module name, which must be the same as that configured in the .hcs file. 995e41f4b71Sopenharmony_ci .Bind = UsbSerialDriverBind, 996e41f4b71Sopenharmony_ci .Init = UsbSerialDriverInit, 997e41f4b71Sopenharmony_ci .Release = UsbSerialDriverRelease, 998e41f4b71Sopenharmony_ci}; 999e41f4b71Sopenharmony_ciHDF_INIT(g_usbSerialDriverEntry); // Driver entry. 1000e41f4b71Sopenharmony_ci``` 1001e41f4b71Sopenharmony_ci 1002e41f4b71Sopenharmony_ci#### Developing Driver Using Host Raw APIs 1003e41f4b71Sopenharmony_ci 1004e41f4b71Sopenharmony_ci```cpp 1005e41f4b71Sopenharmony_ciroot { 1006e41f4b71Sopenharmony_ci module = "usb_pnp_device"; 1007e41f4b71Sopenharmony_ci usb_pnp_config { 1008e41f4b71Sopenharmony_ci match_attr = "usb_pnp_match"; 1009e41f4b71Sopenharmony_ci usb_pnp_device_id = "UsbPnpDeviceId"; 1010e41f4b71Sopenharmony_ci UsbPnpDeviceId { 1011e41f4b71Sopenharmony_ci idTableList = [ 1012e41f4b71Sopenharmony_ci "host_acm_rawapi_table" 1013e41f4b71Sopenharmony_ci ]; 1014e41f4b71Sopenharmony_ci host_acm_rawapi_table { // Driver mapping table information. 1015e41f4b71Sopenharmony_ci // Driver module name, which must be the same as the value of moduleName in the driver entry structure. 1016e41f4b71Sopenharmony_ci moduleName = "usbhost_acm_rawapi"; 1017e41f4b71Sopenharmony_ci // Service name of the driver, which must be unique. 1018e41f4b71Sopenharmony_ci serviceName = "usbhost_acm_rawapi_service"; 1019e41f4b71Sopenharmony_ci // Keyword for matching private driver data. 1020e41f4b71Sopenharmony_ci deviceMatchAttr = "usbhost_acm_rawapi_matchAttr"; 1021e41f4b71Sopenharmony_ci // Data length starting from this field, in bytes. 1022e41f4b71Sopenharmony_ci length = 21; 1023e41f4b71Sopenharmony_ci // USB driver matching rule: vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber. 1024e41f4b71Sopenharmony_ci matchFlag = 0x0303; 1025e41f4b71Sopenharmony_ci // Vendor ID. 1026e41f4b71Sopenharmony_ci vendorId = 0x12D1; 1027e41f4b71Sopenharmony_ci // Product ID. 1028e41f4b71Sopenharmony_ci productId = 0x5000; 1029e41f4b71Sopenharmony_ci // The least significant 16 bits of the device sequence number. 1030e41f4b71Sopenharmony_ci bcdDeviceLow = 0x0000; 1031e41f4b71Sopenharmony_ci // The most significant 16 bits of the device sequence number. 1032e41f4b71Sopenharmony_ci bcdDeviceHigh = 0x0000; 1033e41f4b71Sopenharmony_ci // Device class code allocated by the USB. 1034e41f4b71Sopenharmony_ci deviceClass = 0; 1035e41f4b71Sopenharmony_ci // Child class code allocated by the USB. 1036e41f4b71Sopenharmony_ci deviceSubClass = 0; 1037e41f4b71Sopenharmony_ci // Device protocol code allocated by the USB. 1038e41f4b71Sopenharmony_ci deviceProtocol = 0; 1039e41f4b71Sopenharmony_ci // Interface type. You can enter multiple types as needed. 1040e41f4b71Sopenharmony_ci interfaceClass = [0]; 1041e41f4b71Sopenharmony_ci // Interface subtype. You can enter multiple subtypes as needed. 1042e41f4b71Sopenharmony_ci interfaceSubClass = [2, 0]; 1043e41f4b71Sopenharmony_ci // Protocol that the interface complies with. You can enter multiple protocols as needed. 1044e41f4b71Sopenharmony_ci interfaceProtocol = [1, 2]; 1045e41f4b71Sopenharmony_ci // Interface number. You can enter multiple interface numbers as needed. 1046e41f4b71Sopenharmony_ci interfaceNumber = [2, 3]; 1047e41f4b71Sopenharmony_ci } 1048e41f4b71Sopenharmony_ci } 1049e41f4b71Sopenharmony_ci } 1050e41f4b71Sopenharmony_ci} 1051e41f4b71Sopenharmony_ci``` 1052e41f4b71Sopenharmony_ci 1053e41f4b71Sopenharmony_ci```cpp 1054e41f4b71Sopenharmony_ci#include "usb_serial_rawapi.h" 1055e41f4b71Sopenharmony_ci#include <unistd.h> 1056e41f4b71Sopenharmony_ci#include "osal_mem.h" 1057e41f4b71Sopenharmony_ci#include "osal_time.h" 1058e41f4b71Sopenharmony_ci#include "securec.h" 1059e41f4b71Sopenharmony_ci#include "hdf_base.h" 1060e41f4b71Sopenharmony_ci#include "hdf_log.h" 1061e41f4b71Sopenharmony_ci#include "hdf_usb_pnp_manage.h" 1062e41f4b71Sopenharmony_ci 1063e41f4b71Sopenharmony_ci#define HDF_LOG_TAG USB_HOST_ACM_RAW_API // Labels that can be queried in logs. 1064e41f4b71Sopenharmony_ci#define USB_CTRL_REQ_SIZE 64 1065e41f4b71Sopenharmony_ci#define USB_IO_THREAD_STACK_SIZE 8192 1066e41f4b71Sopenharmony_ci#define USB_RAW_IO_SLEEP_MS_TIME 100 1067e41f4b71Sopenharmony_ci#define USB_RAW_IO_STOP_WAIT_MAX_TIME 3 1068e41f4b71Sopenharmony_ci 1069e41f4b71Sopenharmony_cistatic struct UsbRawRequest *g_syncRequest = NULL; 1070e41f4b71Sopenharmony_cistatic UsbRawIoProcessStatusType g_stopIoStatus = USB_RAW_IO_PROCESS_RUNNING; 1071e41f4b71Sopenharmony_cistruct OsalMutex g_stopIoLock; 1072e41f4b71Sopenharmony_cistatic bool g_rawAcmReleaseFlag = false; 1073e41f4b71Sopenharmony_ci...... 1074e41f4b71Sopenharmony_ci 1075e41f4b71Sopenharmony_cistatic int32_t UsbGetConfigDescriptor(UsbRawHandle *devHandle, struct UsbRawConfigDescriptor **config) 1076e41f4b71Sopenharmony_ci{ 1077e41f4b71Sopenharmony_ci UsbRawDevice *dev = NULL; 1078e41f4b71Sopenharmony_ci int32_t activeConfig; 1079e41f4b71Sopenharmony_ci int32_t ret; 1080e41f4b71Sopenharmony_ci 1081e41f4b71Sopenharmony_ci if (devHandle == NULL) { 1082e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 1083e41f4b71Sopenharmony_ci } 1084e41f4b71Sopenharmony_ci 1085e41f4b71Sopenharmony_ci // Obtain the configuration of the active device. 1086e41f4b71Sopenharmony_ci ret = UsbRawGetConfiguration(devHandle, &activeConfig); 1087e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 1088e41f4b71Sopenharmony_ci return HDF_FAILURE; 1089e41f4b71Sopenharmony_ci } 1090e41f4b71Sopenharmony_ci 1091e41f4b71Sopenharmony_ci // Obtain the device pointer based on the specified device handle. 1092e41f4b71Sopenharmony_ci dev = UsbRawGetDevice(devHandle); 1093e41f4b71Sopenharmony_ci if (dev == NULL) { 1094e41f4b71Sopenharmony_ci return HDF_FAILURE; 1095e41f4b71Sopenharmony_ci } 1096e41f4b71Sopenharmony_ci 1097e41f4b71Sopenharmony_ci // Obtain the device configuration descriptor based on the specified device ID. 1098e41f4b71Sopenharmony_ci ret = UsbRawGetConfigDescriptor(dev, activeConfig, config); 1099e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 1100e41f4b71Sopenharmony_ci HDF_LOGE("UsbRawGetConfigDescriptor failed, ret=%d\n", ret); 1101e41f4b71Sopenharmony_ci } 1102e41f4b71Sopenharmony_ci return ret; 1103e41f4b71Sopenharmony_ci} 1104e41f4b71Sopenharmony_ci... 1105e41f4b71Sopenharmony_cistatic int32_t UsbAllocWriteRequests(struct AcmDevice *acm) 1106e41f4b71Sopenharmony_ci{ 1107e41f4b71Sopenharmony_ci int32_t i; 1108e41f4b71Sopenharmony_ci 1109e41f4b71Sopenharmony_ci for (i = 0; i < ACM_NW; i++) { 1110e41f4b71Sopenharmony_ci struct AcmWb *snd = &acm->wb[i]; 1111e41f4b71Sopenharmony_ci // Allocate a transfer request with the specified number of sync packet descriptors. 1112e41f4b71Sopenharmony_ci snd->request = UsbRawAllocRequest(acm->devHandle, 0, acm->dataOutEp->maxPacketSize); 1113e41f4b71Sopenharmony_ci snd->instance = acm; 1114e41f4b71Sopenharmony_ci if (snd->request == NULL) { 1115e41f4b71Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 1116e41f4b71Sopenharmony_ci } 1117e41f4b71Sopenharmony_ci } 1118e41f4b71Sopenharmony_ci 1119e41f4b71Sopenharmony_ci return HDF_SUCCESS; 1120e41f4b71Sopenharmony_ci} 1121e41f4b71Sopenharmony_ci... 1122e41f4b71Sopenharmony_ci/* HdfDriverEntry implementations */ 1123e41f4b71Sopenharmony_cistatic int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) 1124e41f4b71Sopenharmony_ci{ 1125e41f4b71Sopenharmony_ci struct AcmDevice *acm = NULL; 1126e41f4b71Sopenharmony_ci struct UsbPnpNotifyServiceInfo *info = NULL; 1127e41f4b71Sopenharmony_ci errno_t err; 1128e41f4b71Sopenharmony_ci 1129e41f4b71Sopenharmony_ci if (device == NULL) { 1130e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 1131e41f4b71Sopenharmony_ci } 1132e41f4b71Sopenharmony_ci 1133e41f4b71Sopenharmony_ci acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm)); 1134e41f4b71Sopenharmony_ci if (acm == NULL) { 1135e41f4b71Sopenharmony_ci return HDF_FAILURE; 1136e41f4b71Sopenharmony_ci } 1137e41f4b71Sopenharmony_ci if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { 1138e41f4b71Sopenharmony_ci goto error; 1139e41f4b71Sopenharmony_ci } 1140e41f4b71Sopenharmony_ci 1141e41f4b71Sopenharmony_ci info = (struct UsbPnpNotifyServiceInfo *)device->priv; 1142e41f4b71Sopenharmony_ci if (info != NULL) { 1143e41f4b71Sopenharmony_ci acm->busNum = info->busNum; 1144e41f4b71Sopenharmony_ci acm->devAddr = info->devNum; 1145e41f4b71Sopenharmony_ci acm->interfaceCnt = info->interfaceLength; 1146e41f4b71Sopenharmony_ci err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, 1147e41f4b71Sopenharmony_ci (const void*)info->interfaceNumber, info->interfaceLength); 1148e41f4b71Sopenharmony_ci if (err != EOK) { 1149e41f4b71Sopenharmony_ci goto lock_error; 1150e41f4b71Sopenharmony_ci } 1151e41f4b71Sopenharmony_ci } else { 1152e41f4b71Sopenharmony_ci goto lock_error; 1153e41f4b71Sopenharmony_ci } 1154e41f4b71Sopenharmony_ci 1155e41f4b71Sopenharmony_ci device->service = &(acm->service); 1156e41f4b71Sopenharmony_ci device->service->Dispatch = UsbSerialDeviceDispatch; 1157e41f4b71Sopenharmony_ci acm->device = device; 1158e41f4b71Sopenharmony_ci return HDF_SUCCESS; 1159e41f4b71Sopenharmony_ci 1160e41f4b71Sopenharmony_cilock_error: 1161e41f4b71Sopenharmony_ci if (OsalMutexDestroy(&acm->lock)) { 1162e41f4b71Sopenharmony_ci HDF_LOGE("%s:%d OsalMutexDestroy failed", __func__, __LINE__); 1163e41f4b71Sopenharmony_ci } 1164e41f4b71Sopenharmony_cierror: 1165e41f4b71Sopenharmony_ci OsalMemFree(acm); 1166e41f4b71Sopenharmony_ci acm = NULL; 1167e41f4b71Sopenharmony_ci return HDF_FAILURE; 1168e41f4b71Sopenharmony_ci} 1169e41f4b71Sopenharmony_ci... 1170e41f4b71Sopenharmony_cistatic int32_t UsbAllocReadRequests(struct AcmDevice *acm) 1171e41f4b71Sopenharmony_ci{ 1172e41f4b71Sopenharmony_ci struct UsbRawFillRequestData reqData; 1173e41f4b71Sopenharmony_ci int32_t size = acm->dataInEp->maxPacketSize; 1174e41f4b71Sopenharmony_ci int32_t ret; 1175e41f4b71Sopenharmony_ci 1176e41f4b71Sopenharmony_ci for (int32_t i = 0; i < ACM_NR; i++) { 1177e41f4b71Sopenharmony_ci // Allocate a transfer request with the specified number of sync packet descriptors. 1178e41f4b71Sopenharmony_ci acm->readReq[i] = UsbRawAllocRequest(acm->devHandle, 0, size); 1179e41f4b71Sopenharmony_ci if (!acm->readReq[i]) { 1180e41f4b71Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 1181e41f4b71Sopenharmony_ci } 1182e41f4b71Sopenharmony_ci 1183e41f4b71Sopenharmony_ci reqData.endPoint = acm->dataInEp->addr; 1184e41f4b71Sopenharmony_ci reqData.numIsoPackets = 0; 1185e41f4b71Sopenharmony_ci reqData.callback = AcmReadBulkCallback; 1186e41f4b71Sopenharmony_ci reqData.userData = (void *)acm; 1187e41f4b71Sopenharmony_ci reqData.timeout = USB_CTRL_SET_TIMEOUT; 1188e41f4b71Sopenharmony_ci reqData.length = size; 1189e41f4b71Sopenharmony_ci 1190e41f4b71Sopenharmony_ci // Fill the required information in the bulk transfer request. 1191e41f4b71Sopenharmony_ci ret = UsbRawFillBulkRequest(acm->readReq[i], acm->devHandle, &reqData); 1192e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 1193e41f4b71Sopenharmony_ci return HDF_FAILURE; 1194e41f4b71Sopenharmony_ci } 1195e41f4b71Sopenharmony_ci } 1196e41f4b71Sopenharmony_ci 1197e41f4b71Sopenharmony_ci return HDF_SUCCESS; 1198e41f4b71Sopenharmony_ci} 1199e41f4b71Sopenharmony_ci... 1200e41f4b71Sopenharmony_cistatic int32_t UsbAllocNotifyRequest(struct AcmDevice *acm) 1201e41f4b71Sopenharmony_ci{ 1202e41f4b71Sopenharmony_ci struct UsbRawFillRequestData fillRequestData; 1203e41f4b71Sopenharmony_ci int32_t size = acm->notifyEp->maxPacketSize; 1204e41f4b71Sopenharmony_ci int32_t ret; 1205e41f4b71Sopenharmony_ci 1206e41f4b71Sopenharmony_ci // Allocate a transfer request with the specified number of sync packet descriptors. 1207e41f4b71Sopenharmony_ci acm->notifyReq = UsbRawAllocRequest(acm->devHandle, 0, size); 1208e41f4b71Sopenharmony_ci if (!acm->notifyReq) { 1209e41f4b71Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 1210e41f4b71Sopenharmony_ci } 1211e41f4b71Sopenharmony_ci 1212e41f4b71Sopenharmony_ci fillRequestData.endPoint = acm->notifyEp->addr; 1213e41f4b71Sopenharmony_ci fillRequestData.length = size; 1214e41f4b71Sopenharmony_ci fillRequestData.numIsoPackets = 0; 1215e41f4b71Sopenharmony_ci fillRequestData.callback = AcmNotifyReqCallback; 1216e41f4b71Sopenharmony_ci fillRequestData.userData = (void *)acm; 1217e41f4b71Sopenharmony_ci fillRequestData.timeout = USB_CTRL_SET_TIMEOUT; 1218e41f4b71Sopenharmony_ci 1219e41f4b71Sopenharmony_ci // Fill the required information in the interrupt transfer request. 1220e41f4b71Sopenharmony_ci ret = UsbRawFillInterruptRequest(acm->notifyReq, acm->devHandle, &fillRequestData); 1221e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 1222e41f4b71Sopenharmony_ci return HDF_FAILURE; 1223e41f4b71Sopenharmony_ci } 1224e41f4b71Sopenharmony_ci 1225e41f4b71Sopenharmony_ci return HDF_SUCCESS; 1226e41f4b71Sopenharmony_ci} 1227e41f4b71Sopenharmony_ci... 1228e41f4b71Sopenharmony_cistatic int32_t UsbSerialInit(struct AcmDevice *acm) 1229e41f4b71Sopenharmony_ci{ 1230e41f4b71Sopenharmony_ci struct UsbSession *session = NULL; 1231e41f4b71Sopenharmony_ci UsbRawHandle *devHandle = NULL; 1232e41f4b71Sopenharmony_ci int32_t ret; 1233e41f4b71Sopenharmony_ci 1234e41f4b71Sopenharmony_ci if (acm->initFlag == true) { 1235e41f4b71Sopenharmony_ci return HDF_SUCCESS; 1236e41f4b71Sopenharmony_ci } 1237e41f4b71Sopenharmony_ci 1238e41f4b71Sopenharmony_ci // Initialize the USB DDK in expert mode. 1239e41f4b71Sopenharmony_ci ret = UsbRawInit(NULL); 1240e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 1241e41f4b71Sopenharmony_ci return HDF_ERR_IO; 1242e41f4b71Sopenharmony_ci } 1243e41f4b71Sopenharmony_ci acm->session = session; 1244e41f4b71Sopenharmony_ci 1245e41f4b71Sopenharmony_ci // Open a USB device object. 1246e41f4b71Sopenharmony_ci devHandle = UsbRawOpenDevice(session, acm->busNum, acm->devAddr); 1247e41f4b71Sopenharmony_ci if (devHandle == NULL) { 1248e41f4b71Sopenharmony_ci ret = HDF_FAILURE; 1249e41f4b71Sopenharmony_ci goto err_open_device; 1250e41f4b71Sopenharmony_ci } 1251e41f4b71Sopenharmony_ci acm->devHandle = devHandle; 1252e41f4b71Sopenharmony_ci // Obtain the configuration of the active device, device pointer, and configuration descriptor. 1253e41f4b71Sopenharmony_ci ret = UsbGetConfigDescriptor(devHandle, &acm->config); 1254e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 1255e41f4b71Sopenharmony_ci ret = HDF_FAILURE; 1256e41f4b71Sopenharmony_ci goto err_get_desc; 1257e41f4b71Sopenharmony_ci } 1258e41f4b71Sopenharmony_ci ret = UsbParseConfigDescriptor(acm, acm->config); 1259e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 1260e41f4b71Sopenharmony_ci ret = HDF_FAILURE; 1261e41f4b71Sopenharmony_ci goto err_parse_desc; 1262e41f4b71Sopenharmony_ci } 1263e41f4b71Sopenharmony_ci 1264e41f4b71Sopenharmony_ci ret = AcmWriteBufAlloc(acm); 1265e41f4b71Sopenharmony_ci if (ret < 0) { 1266e41f4b71Sopenharmony_ci ret = HDF_FAILURE; 1267e41f4b71Sopenharmony_ci goto err_alloc_write_buf; 1268e41f4b71Sopenharmony_ci } 1269e41f4b71Sopenharmony_ci ret = UsbAllocWriteRequests(acm); 1270e41f4b71Sopenharmony_ci if (ret < 0) { 1271e41f4b71Sopenharmony_ci ret = HDF_FAILURE; 1272e41f4b71Sopenharmony_ci goto err_alloc_write_reqs; 1273e41f4b71Sopenharmony_ci } 1274e41f4b71Sopenharmony_ci ret = UsbAllocNotifyRequest(acm); 1275e41f4b71Sopenharmony_ci if (ret) { 1276e41f4b71Sopenharmony_ci goto err_alloc_notify_req; 1277e41f4b71Sopenharmony_ci } 1278e41f4b71Sopenharmony_ci ret = UsbAllocReadRequests(acm); 1279e41f4b71Sopenharmony_ci if (ret) { 1280e41f4b71Sopenharmony_ci goto err_alloc_read_reqs; 1281e41f4b71Sopenharmony_ci } 1282e41f4b71Sopenharmony_ci ret = UsbStartIo(acm); 1283e41f4b71Sopenharmony_ci if (ret) { 1284e41f4b71Sopenharmony_ci goto err_start_io; 1285e41f4b71Sopenharmony_ci } 1286e41f4b71Sopenharmony_ci 1287e41f4b71Sopenharmony_ci acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); 1288e41f4b71Sopenharmony_ci acm->lineCoding.bCharFormat = CHARFORMAT; 1289e41f4b71Sopenharmony_ci acm->lineCoding.bParityType = USB_CDC_NO_PARITY; 1290e41f4b71Sopenharmony_ci acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS; 1291e41f4b71Sopenharmony_ci 1292e41f4b71Sopenharmony_ci ret = UsbRawSubmitRequest(acm->notifyReq); 1293e41f4b71Sopenharmony_ci if (ret) { 1294e41f4b71Sopenharmony_ci goto err_submit_req; 1295e41f4b71Sopenharmony_ci } 1296e41f4b71Sopenharmony_ci 1297e41f4b71Sopenharmony_ci acm->initFlag = true; 1298e41f4b71Sopenharmony_ci return HDF_SUCCESS; 1299e41f4b71Sopenharmony_ci 1300e41f4b71Sopenharmony_cierr_submit_req: 1301e41f4b71Sopenharmony_ci UsbStopIo(acm); // Stop the I/O thread and release all resources. 1302e41f4b71Sopenharmony_cierr_start_io: 1303e41f4b71Sopenharmony_ci UsbFreeReadRequests(acm); 1304e41f4b71Sopenharmony_cierr_alloc_read_reqs: 1305e41f4b71Sopenharmony_ci UsbFreeNotifyRequest(acm); 1306e41f4b71Sopenharmony_ci err_alloc_notify_req: 1307e41f4b71Sopenharmony_ci UsbFreeWriteRequests(acm); 1308e41f4b71Sopenharmony_cierr_alloc_write_reqs: 1309e41f4b71Sopenharmony_ci AcmWriteBufFree(acm); 1310e41f4b71Sopenharmony_cierr_alloc_write_buf: 1311e41f4b71Sopenharmony_ci UsbReleaseInterfaces(acm); 1312e41f4b71Sopenharmony_cierr_parse_desc: 1313e41f4b71Sopenharmony_ci UsbRawFreeConfigDescriptor(acm->config); 1314e41f4b71Sopenharmony_ci acm->config = NULL; 1315e41f4b71Sopenharmony_cierr_get_desc: 1316e41f4b71Sopenharmony_ci (void)UsbRawCloseDevice(devHandle); // Close the USB device object. 1317e41f4b71Sopenharmony_cierr_open_device: 1318e41f4b71Sopenharmony_ci UsbRawExit(acm->session); // Exit the expert mode of the USB DDK. 1319e41f4b71Sopenharmony_ci 1320e41f4b71Sopenharmony_ci return ret; 1321e41f4b71Sopenharmony_ci} 1322e41f4b71Sopenharmony_ci 1323e41f4b71Sopenharmony_cistatic void UsbSerialRelease(struct AcmDevice *acm) 1324e41f4b71Sopenharmony_ci{ 1325e41f4b71Sopenharmony_ci if (acm->initFlag == false) { 1326e41f4b71Sopenharmony_ci return; 1327e41f4b71Sopenharmony_ci } 1328e41f4b71Sopenharmony_ci 1329e41f4b71Sopenharmony_ci /* stop io thread and release all resources */ 1330e41f4b71Sopenharmony_ci UsbStopIo(acm); 1331e41f4b71Sopenharmony_ci if (g_syncRequest != NULL) { 1332e41f4b71Sopenharmony_ci UsbRawFreeRequest(g_syncRequest); 1333e41f4b71Sopenharmony_ci g_syncRequest = NULL; 1334e41f4b71Sopenharmony_ci } 1335e41f4b71Sopenharmony_ci UsbFreeReadRequests(acm); 1336e41f4b71Sopenharmony_ci UsbFreeNotifyRequest(acm); 1337e41f4b71Sopenharmony_ci UsbFreeWriteRequests(acm); 1338e41f4b71Sopenharmony_ci AcmWriteBufFree(acm); 1339e41f4b71Sopenharmony_ci (void)UsbRawCloseDevice(acm->devHandle); 1340e41f4b71Sopenharmony_ci UsbReleaseInterfaces(acm); 1341e41f4b71Sopenharmony_ci UsbRawFreeConfigDescriptor(acm->config); 1342e41f4b71Sopenharmony_ci acm->config = NULL; 1343e41f4b71Sopenharmony_ci // Exit the expert mode of the USB DDK. 1344e41f4b71Sopenharmony_ci UsbRawExit(acm->session); 1345e41f4b71Sopenharmony_ci 1346e41f4b71Sopenharmony_ci acm->initFlag = false; 1347e41f4b71Sopenharmony_ci} 1348e41f4b71Sopenharmony_ci 1349e41f4b71Sopenharmony_cistatic int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) 1350e41f4b71Sopenharmony_ci{ 1351e41f4b71Sopenharmony_ci struct AcmDevice *acm = NULL; 1352e41f4b71Sopenharmony_ci int32_t ret; 1353e41f4b71Sopenharmony_ci 1354e41f4b71Sopenharmony_ci if (device == NULL) { 1355e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 1356e41f4b71Sopenharmony_ci } 1357e41f4b71Sopenharmony_ci acm = (struct AcmDevice *)device->service; 1358e41f4b71Sopenharmony_ci OsalMutexInit(&acm->readLock); 1359e41f4b71Sopenharmony_ci OsalMutexInit(&acm->writeLock); 1360e41f4b71Sopenharmony_ci 1361e41f4b71Sopenharmony_ci ret = UsbSerialDeviceAlloc(acm); 1362e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 1363e41f4b71Sopenharmony_ci HDF_LOGE("%s:%d UsbSerialDeviceAlloc failed", __func__, __LINE__); 1364e41f4b71Sopenharmony_ci } 1365e41f4b71Sopenharmony_ci 1366e41f4b71Sopenharmony_ci acm->initFlag = false; 1367e41f4b71Sopenharmony_ci g_rawAcmReleaseFlag = false; 1368e41f4b71Sopenharmony_ci return ret; 1369e41f4b71Sopenharmony_ci} 1370e41f4b71Sopenharmony_ci 1371e41f4b71Sopenharmony_cistatic void UsbSerialDriverRelease(struct HdfDeviceObject *device) 1372e41f4b71Sopenharmony_ci{ 1373e41f4b71Sopenharmony_ci struct AcmDevice *acm = NULL; 1374e41f4b71Sopenharmony_ci if (device == NULL) { 1375e41f4b71Sopenharmony_ci return; 1376e41f4b71Sopenharmony_ci } 1377e41f4b71Sopenharmony_ci 1378e41f4b71Sopenharmony_ci acm = (struct AcmDevice *)device->service; 1379e41f4b71Sopenharmony_ci if (acm == NULL) { 1380e41f4b71Sopenharmony_ci return; 1381e41f4b71Sopenharmony_ci } 1382e41f4b71Sopenharmony_ci 1383e41f4b71Sopenharmony_ci g_rawAcmReleaseFlag = true; 1384e41f4b71Sopenharmony_ci 1385e41f4b71Sopenharmony_ci if (acm->initFlag == true) { 1386e41f4b71Sopenharmony_ci UsbSerialRelease(acm); 1387e41f4b71Sopenharmony_ci } 1388e41f4b71Sopenharmony_ci UsbSeriaDevicelFree(acm); 1389e41f4b71Sopenharmony_ci OsalMutexDestroy(&acm->writeLock); 1390e41f4b71Sopenharmony_ci OsalMutexDestroy(&acm->readLock); 1391e41f4b71Sopenharmony_ci OsalMutexDestroy(&acm->lock); 1392e41f4b71Sopenharmony_ci OsalMemFree(acm); 1393e41f4b71Sopenharmony_ci acm = NULL; 1394e41f4b71Sopenharmony_ci} 1395e41f4b71Sopenharmony_ci 1396e41f4b71Sopenharmony_cistruct HdfDriverEntry g_usbSerialRawDriverEntry = { 1397e41f4b71Sopenharmony_ci .moduleVersion = 1, 1398e41f4b71Sopenharmony_ci .moduleName = "usbhost_acm_rawapi", // Driver module name, which must be the same as that configured in the .hcs file. 1399e41f4b71Sopenharmony_ci .Bind = UsbSerialDriverBind, 1400e41f4b71Sopenharmony_ci .Init = UsbSerialDriverInit, 1401e41f4b71Sopenharmony_ci .Release = UsbSerialDriverRelease, 1402e41f4b71Sopenharmony_ci}; 1403e41f4b71Sopenharmony_ciHDF_INIT(g_usbSerialRawDriverEntry); 1404e41f4b71Sopenharmony_ci``` 1405e41f4b71Sopenharmony_ci 1406e41f4b71Sopenharmony_ci#### Developing Driver Using Device DDK APIs 1407e41f4b71Sopenharmony_ci 1408e41f4b71Sopenharmony_ciThe core code of the USB ACM device is stored in **drivers\peripheral\usb\gadget\function\acm\cdcacm.c**. The following sample code implements driver development by using the Device DDK APIs. To develop a driver, you must create a device based on the descriptor, obtain the interface, open the interface to obtain the pipe information, receive events, and then perform USB communication (such as read and write). When the device is uninstalled, you need to close the interface, stop receiving events, and remove the device. 1409e41f4b71Sopenharmony_ci 1410e41f4b71Sopenharmony_ci1. Create a USB device. 1411e41f4b71Sopenharmony_ci 1412e41f4b71Sopenharmony_ci ```cpp 1413e41f4b71Sopenharmony_ci static int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm, struct DeviceResourceIface *iface) 1414e41f4b71Sopenharmony_ci { 1415e41f4b71Sopenharmony_ci struct UsbFnDevice *fnDev = NULL; 1416e41f4b71Sopenharmony_ci struct UsbFnDescriptorData descData; 1417e41f4b71Sopenharmony_ci uint8_t useHcs; 1418e41f4b71Sopenharmony_ci ... 1419e41f4b71Sopenharmony_ci if (useHcs == 0) { // The descriptor is sourced from the code. 1420e41f4b71Sopenharmony_ci descData.type = USBFN_DESC_DATA_TYPE_DESC; 1421e41f4b71Sopenharmony_ci descData.descriptor = &g_masterFuncDevice; 1422e41f4b71Sopenharmony_ci } else {// The descriptor is sourced from the .hcs file. 1423e41f4b71Sopenharmony_ci descData.type = USBFN_DESC_DATA_TYPE_PROP; 1424e41f4b71Sopenharmony_ci descData.property = device->property; 1425e41f4b71Sopenharmony_ci } 1426e41f4b71Sopenharmony_ci /* Create a device. */ 1427e41f4b71Sopenharmony_ci fnDev = (struct UsbFnDevice *)UsbFnDeviceCreate(acm->udcName, &descData); 1428e41f4b71Sopenharmony_ci if (fnDev == NULL) { 1429e41f4b71Sopenharmony_ci return HDF_FAILURE; 1430e41f4b71Sopenharmony_ci } 1431e41f4b71Sopenharmony_ci ... 1432e41f4b71Sopenharmony_ci } 1433e41f4b71Sopenharmony_ci ``` 1434e41f4b71Sopenharmony_ci 1435e41f4b71Sopenharmony_ci2. Obtain an interface and open the interface to obtain the pipe information. 1436e41f4b71Sopenharmony_ci 1437e41f4b71Sopenharmony_ci ```cpp 1438e41f4b71Sopenharmony_ci static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface) 1439e41f4b71Sopenharmony_ci { 1440e41f4b71Sopenharmony_ci ... 1441e41f4b71Sopenharmony_ci for (i = 0; i < fnIface->info.numPipes; i++) { 1442e41f4b71Sopenharmony_ci struct UsbFnPipeInfo pipeInfo; 1443e41f4b71Sopenharmony_ci /* Obtain pipe information. */ 1444e41f4b71Sopenharmony_ci ret = UsbFnInterfaceGetPipeInfo(fnIface, i, &pipeInfo); 1445e41f4b71Sopenharmony_ci ... 1446e41f4b71Sopenharmony_ci } 1447e41f4b71Sopenharmony_ci return HDF_SUCCESS; 1448e41f4b71Sopenharmony_ci } 1449e41f4b71Sopenharmony_ci /* Obtain an interface and open the interface to obtain the handle. */ 1450e41f4b71Sopenharmony_ci static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev) 1451e41f4b71Sopenharmony_ci { 1452e41f4b71Sopenharmony_ci ... 1453e41f4b71Sopenharmony_ci for (i = 0; i < fnDev->numInterfaces; i++) { 1454e41f4b71Sopenharmony_ci /* Obtain an interface.*/ 1455e41f4b71Sopenharmony_ci fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i); 1456e41f4b71Sopenharmony_ci ... 1457e41f4b71Sopenharmony_ci /* Open the interface. */ 1458e41f4b71Sopenharmony_ci handle = UsbFnInterfaceOpen(fnIface); 1459e41f4b71Sopenharmony_ci ... 1460e41f4b71Sopenharmony_ci } 1461e41f4b71Sopenharmony_ci return HDF_SUCCESS; 1462e41f4b71Sopenharmony_ci } 1463e41f4b71Sopenharmony_ci ``` 1464e41f4b71Sopenharmony_ci 1465e41f4b71Sopenharmony_ci3. Receive events (EP0 control transfer). 1466e41f4b71Sopenharmony_ci 1467e41f4b71Sopenharmony_ci ```cpp 1468e41f4b71Sopenharmony_ci static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int32_t num) 1469e41f4b71Sopenharmony_ci { 1470e41f4b71Sopenharmony_ci ... 1471e41f4b71Sopenharmony_ci req = UsbFnCtrlRequestAlloc(acm->ctrlIface.handle, 1472e41f4b71Sopenharmony_ci sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding)); 1473e41f4b71Sopenharmony_ci ... 1474e41f4b71Sopenharmony_ci } 1475e41f4b71Sopenharmony_ci static int32_t AcmDriverInit(struct HdfDeviceObject *device) 1476e41f4b71Sopenharmony_ci { 1477e41f4b71Sopenharmony_ci ... 1478e41f4b71Sopenharmony_ci /* Start to receive events.*/ 1479e41f4b71Sopenharmony_ci ret = UsbFnInterfaceStartRecvEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm); 1480e41f4b71Sopenharmony_ci ... 1481e41f4b71Sopenharmony_ci } 1482e41f4b71Sopenharmony_ci ``` 1483e41f4b71Sopenharmony_ci 1484e41f4b71Sopenharmony_ci4. Perform USB communication (read and write). 1485e41f4b71Sopenharmony_ci 1486e41f4b71Sopenharmony_ci ```cpp 1487e41f4b71Sopenharmony_ci static int32_t AcmSendNotifyRequest(struct UsbAcmDevice *acm, uint8_t type, 1488e41f4b71Sopenharmony_ci uint16_t value, void *data, uint32_t length) 1489e41f4b71Sopenharmony_ci { 1490e41f4b71Sopenharmony_ci ... 1491e41f4b71Sopenharmony_ci /* Send an asynchronous request.*/ 1492e41f4b71Sopenharmony_ci ret = UsbFnRequestSubmitAsync(req); 1493e41f4b71Sopenharmony_ci ... 1494e41f4b71Sopenharmony_ci } 1495e41f4b71Sopenharmony_ci ``` 1496e41f4b71Sopenharmony_ci 1497e41f4b71Sopenharmony_ci5. Close the interface, stop receiving events, and delete the device. 1498e41f4b71Sopenharmony_ci 1499e41f4b71Sopenharmony_ci ```cpp 1500e41f4b71Sopenharmony_ci static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm) 1501e41f4b71Sopenharmony_ci { 1502e41f4b71Sopenharmony_ci int32_t ret; 1503e41f4b71Sopenharmony_ci /* Close the interface. */ 1504e41f4b71Sopenharmony_ci (void)UsbFnInterfaceClose(acm->ctrlIface.handle); 1505e41f4b71Sopenharmony_ci (void)UsbFnInterfaceClose(acm->dataIface.handle); 1506e41f4b71Sopenharmony_ci /* Stop receiving the Event EP0 control transfer. */ 1507e41f4b71Sopenharmony_ci (void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn); 1508e41f4b71Sopenharmony_ci /* Delete the device. */ 1509e41f4b71Sopenharmony_ci ret = UsbFnDeviceRemove(acm->fnDev); 1510e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 1511e41f4b71Sopenharmony_ci HDF_LOGE("%s: remove usb function device failed", __func__); 1512e41f4b71Sopenharmony_ci } 1513e41f4b71Sopenharmony_ci return ret; 1514e41f4b71Sopenharmony_ci } 1515e41f4b71Sopenharmony_ci ``` 1516e41f4b71Sopenharmony_ci 1517e41f4b71Sopenharmony_ci## References 1518e41f4b71Sopenharmony_ci 1519e41f4b71Sopenharmony_ci- Code repositories: 1520e41f4b71Sopenharmony_ci 1521e41f4b71Sopenharmony_ci **[drivers\_hdf\_core](https://gitee.com/openharmony/drivers_hdf_core)** 1522e41f4b71Sopenharmony_ci 1523e41f4b71Sopenharmony_ci [drivers\_peripheral](https://gitee.com/openharmony/drivers_peripheral) 1524e41f4b71Sopenharmony_ci 1525e41f4b71Sopenharmony_ci [drivers\_interface](https://gitee.com/openharmony/drivers_interface) 1526e41f4b71Sopenharmony_ci 1527e41f4b71Sopenharmony_ci- Code paths: 1528e41f4b71Sopenharmony_ci 1529e41f4b71Sopenharmony_ci USB driver model adaptation for LiteOS: //drivers/hdf_core/adapter/khdf/liteos/model/usb 1530e41f4b71Sopenharmony_ci 1531e41f4b71Sopenharmony_ci USB DDK driver loading: //drivers/hdf_core/framework/model/usb 1532e41f4b71Sopenharmony_ci 1533e41f4b71Sopenharmony_ci USB HDI server implementation: //drivers/peripheral/usb/hdi_service 1534e41f4b71Sopenharmony_ci 1535e41f4b71Sopenharmony_ci USB HDI external APIs: //out/{product_name}/gen/drivers/interface/usb/v1_0 1536