提交 4b04ab11 编写于 作者: S shawn_he

update doc

Signed-off-by: Nshawn_he <shawn.he@huawei.com>
上级 7053d5fe
# USB # USB
## Introduction
## Overview ### Function Overview
USB host development aims to provide host-related functions, including protocol encapsulation, device management, and driver installation and uninstall. The 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.
USB device development aims to provide device-related functions, including device management, configuration management, and I/O management. These functions implement creation, configuration, and data communication of USB devices. The 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.
The following figures show the USB host and device driver models. The 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.
### Basic Concepts
- Pipe
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.
- Endpoint
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.
- Interface
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.
- Descriptor
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.
### Working Principles
#### USB Host DDK
The 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.
**Figure 1** USB host driver model **Figure 1** USB host driver model
![](figures/USB_host_driver_model.png "USB host driver model") ![](figures/USB_host_driver_model.png "USB host driver model")
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
#### USB Device DDK
The 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.
**Figure 2** USB device driver model **Figure 2** USB device driver model
![](figures/USB_device_driver_model.png "USB device driver model") ![](figures/USB_device_driver_model.png "USB device driver model")
The USB driver model offers the following APIs: - 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.
- 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.
- 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.
- 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.
- 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.
- The Adapter module is provided by the composite device configuration driver and common function driver.
## How to Develop
- The USB host Driver Development Kit (DDK) provides driver capability APIs that can be directly called in user mode. The APIs can be classified into the DDK initialization class, interface operation class, and request operation class by function. These APIs can be used to perform DDK initialization, bind/release and open/close an interface, allocate/release a request, and implement synchronous or asynchronous transfer. The 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.
- The USB device DDK provides device management, I/O management, and configuration management APIs, which can be used to create or delete a device, obtain or open an interface, and perform synchronous or asynchronous transfer. ### When to Use
The 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.
### Available APIs ### Available APIs
The tables below describe the APIs provided by the USB host driver model. The 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).
**Table 1** usb_ddk_interface.h **Table 1** APIs for USB host driver development (common mode)
| API| Description| | API| Description|
| -------- | -------- | | -------- | -------- |
| int32_t&nbsp;UsbInitHostSdk(struct&nbsp;UsbSession&nbsp;\*\*session); | Initializes the USB host driver DDK.| | int32_t&nbsp;UsbInitHostSdk(struct&nbsp;UsbSession&nbsp;\*\*session); | Initializes the USB host driver DDK.|
| int32_t&nbsp;UsbExitHostSdk(const&nbsp;struct&nbsp;UsbSession<br>\*session); | Exits the USB host driver DDK.|
| const&nbsp;struct&nbsp;UsbInterface&nbsp;\*UsbClaimInterface(const<br>struct&nbsp;UsbSession&nbsp;\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t<br>usbAddr,&nbsp;uint8_t&nbsp;interfaceIndex); | Obtains a USB interface.| | const&nbsp;struct&nbsp;UsbInterface&nbsp;\*UsbClaimInterface(const<br>struct&nbsp;UsbSession&nbsp;\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t<br>usbAddr,&nbsp;uint8_t&nbsp;interfaceIndex); | Obtains a USB interface.|
| int&nbsp;UsbReleaseInterface(const&nbsp;struct&nbsp;UsbInterface<br>\*interfaceObj); | Releases a USB interface.|
| int&nbsp;UsbAddOrRemoveInterface(const&nbsp;struct&nbsp;UsbSession<br>\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t&nbsp;usbAddr,&nbsp;uint8_t<br>interfaceIndex,&nbsp;UsbInterfaceStatus&nbsp;status); | Adds or removes a USB interface.|
| UsbInterfaceHandle&nbsp;\*UsbOpenInterface(const&nbsp;struct<br>UsbInterface&nbsp;\*interfaceObj); | Opens a USB interface.| | UsbInterfaceHandle&nbsp;\*UsbOpenInterface(const&nbsp;struct<br>UsbInterface&nbsp;\*interfaceObj); | Opens a USB interface.|
| int32_t&nbsp;UsbCloseInterface(const&nbsp;UsbInterfaceHandle<br>\*interfaceHandle); | Closes a USB interface.|
| int32_t&nbsp;UsbSelectInterfaceSetting(const<br>UsbInterfaceHandle&nbsp;\*interfaceHandle,&nbsp;uint8_t<br>settingIndex,&nbsp;struct&nbsp;UsbInterface&nbsp;\*\*interfaceObj); | Sets a USB interface.|
| int32_t&nbsp;UsbGetPipeInfo(const&nbsp;UsbInterfaceHandle<br>\*interfaceHandle,&nbsp;uint8_t&nbsp;settingIndex,&nbsp;uint8_t&nbsp;pipeId,<br>struct&nbsp;UsbPipeInfo&nbsp;\*pipeInfo); | Obtains USB pipe information.| | int32_t&nbsp;UsbGetPipeInfo(const&nbsp;UsbInterfaceHandle<br>\*interfaceHandle,&nbsp;uint8_t&nbsp;settingIndex,&nbsp;uint8_t&nbsp;pipeId,<br>struct&nbsp;UsbPipeInfo&nbsp;\*pipeInfo); | Obtains USB pipe information.|
| int32_t&nbsp;UsbClearInterfaceHalt(const<br>UsbInterfaceHandle&nbsp;\*interfaceHandle,&nbsp;uint8_t<br>pipeAddress); | Clears the state of the pipe with the specified index.| | struct&nbsp;UsbRequest&nbsp;\*UsbAllocRequest(const<br>UsbInterfaceHandle&nbsp;\*interfaceHandle,&nbsp;int32_t&nbsp;isoPackets<br>,&nbsp;int32_t&nbsp;length); | Allocates a request object.|
| struct&nbsp;UsbRequest&nbsp;\*UsbAllocRequest(const<br>UsbInterfaceHandle&nbsp;\*interfaceHandle,&nbsp;int&nbsp;isoPackets<br>,&nbsp;int&nbsp;length); | Allocates a request object.|
| int&nbsp;UsbFreeRequest(const&nbsp;struct&nbsp;UsbRequest<br>\*request); | Releases a request object.|
| int&nbsp;UsbSubmitRequestAsync(const&nbsp;struct&nbsp;UsbRequest<br>\*request); | Sends an asynchronous request.|
| int32_t&nbsp;UsbFillRequest(const&nbsp;struct&nbsp;UsbRequest<br>\*request,&nbsp;const&nbsp;UsbInterfaceHandle&nbsp;\*interfaceHandle,<br>const&nbsp;struct&nbsp;UsbRequestParams&nbsp;\*params); | Fills in a request.| | int32_t&nbsp;UsbFillRequest(const&nbsp;struct&nbsp;UsbRequest<br>\*request,&nbsp;const&nbsp;UsbInterfaceHandle&nbsp;\*interfaceHandle,<br>const&nbsp;struct&nbsp;UsbRequestParams&nbsp;\*params); | Fills in a request.|
| sint&nbsp;UsbCancelRequest(const&nbsp;struct&nbsp;UsbRequest<br>\*request); | Cancels an asynchronous request.| | int32_t&nbsp;UsbSubmitRequestSync(const&nbsp;struct&nbsp;UsbRequest<br>\*request); | Sends a synchronous request.|
| int&nbsp;UsbSubmitRequestSync(const&nbsp;struct&nbsp;UsbRequest<br>\*request); | Sends a synchronous request.|
The 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).
**Table 2** usb_raw_api.h **Table 2** APIs for USB host driver development (expert mode)
| API| Description| | API| Description|
| -------- | -------- | | -------- | -------- |
| int&nbsp;UsbRawInit(struct&nbsp;UsbSession&nbsp;\*\*session); | Initializes the USB raw APIs.| | int32_t&nbsp;UsbRawInit(struct&nbsp;UsbSession&nbsp;\*\*session); | Initializes the USB raw APIs.|
| int&nbsp;UsbRawExit(const&nbsp;struct&nbsp;UsbSession&nbsp;\*session); | Exits the USB raw APIs.|
| UsbRawHandle&nbsp;\*UsbRawOpenDevice(const&nbsp;struct<br>UsbSession&nbsp;\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t<br>usbAddr); | Opens a USB device.| | UsbRawHandle&nbsp;\*UsbRawOpenDevice(const&nbsp;struct<br>UsbSession&nbsp;\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t<br>usbAddr); | Opens a USB device.|
| int&nbsp;UsbRawCloseDevice(const&nbsp;UsbRawHandle<br>\*devHandle); | Closes a USB device.| | int32_t&nbsp;UsbRawSendControlRequest(const&nbsp;struct<br>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbControlRequestData<br>\*requestData); | Performs a control transfer synchronously.|
| int&nbsp;UsbRawSendControlRequest(const&nbsp;struct<br>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbControlRequestData<br>\*requestData); | Performs a control transfer synchronously.| | int32_t&nbsp;UsbRawSendBulkRequest(const&nbsp;struct<br>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbRequestData<br>\*requestData); | Performs a bulk transfer synchronously.|
| int&nbsp;UsbRawSendBulkRequest(const&nbsp;struct<br>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbRequestData<br>\*requestData); | Performs a bulk transfer synchronously.| | int32_t&nbsp;UsbRawSendInterruptRequest(const&nbsp;struct<br>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbRequestData<br>\*requestData); | Performs an interrupt transfer synchronously.|
| int&nbsp;UsbRawSendInterruptRequest(const&nbsp;struct<br>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbRequestData<br>\*requestData); | Performs an interrupt transfer synchronously.| | int32_t&nbsp;UsbRawGetConfigDescriptor(const&nbsp;UsbRawDevice<br>\*rawDev,&nbsp;uint8_t&nbsp;configIndex,&nbsp;struct<br>UsbRawConfigDescriptor&nbsp;\*\*config); | Obtains the configuration descriptor of a device.|
| int&nbsp;UsbRawGetConfigDescriptor(const&nbsp;UsbRawDevice<br>\*rawDev,&nbsp;uint8_t&nbsp;configIndex,&nbsp;struct<br>UsbRawConfigDescriptor&nbsp;\*\*config); | Obtains the configuration descriptor of a device.| | int32_t&nbsp;UsbRawFillInterruptRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br>UsbRawFillRequestData&nbsp;\*fillData); | Fills in an interrupt transfer request.|
| void&nbsp;UsbRawFreeConfigDescriptor(const&nbsp;struct<br>UsbRawConfigDescriptor&nbsp;\*config); | Releases the memory space of a configuration descriptor.| | int32_t&nbsp;UsbRawFillIsoRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br>UsbRawFillRequestData&nbsp;\*fillData); | Fills in an isochronous transfer request.|
| int&nbsp;UsbRawGetConfiguration(const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;int&nbsp;\*config); | Obtains the configuration in use.| | int32_t&nbsp;UsbRawSubmitRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request); | Submits a transfer request.|
| int&nbsp;UsbRawSetConfiguration(const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;int&nbsp;config); | Sets the configuration in use.| | int32_t&nbsp;UsbRawCancelRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request); | Cancels a transfer request.|
| int&nbsp;UsbRawGetDescriptor(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br>UsbRawDescriptorParam&nbsp;\*param,&nbsp;const&nbsp;unsigned&nbsp;char<br>\*data); | Obtains descriptor information.| | int32_t&nbsp;UsbRawHandleRequests(const&nbsp;UsbRawHandle<br>\*devHandle); | Handles a transfer request event.|
| UsbRawDevice&nbsp;\*UsbRawGetDevice(const&nbsp;UsbRawHandle<br>\*devHandle); | Obtains the device pointer based on the device handle.|
| int&nbsp;UsbRawGetDeviceDescriptor(const&nbsp;UsbRawDevice<br>\*rawDev,&nbsp;struct<br>UsbDeviceDescriptor&nbsp;\*desc); | Obtains the device descriptor of the specified USB device.| The 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).
| int&nbsp;UsbRawClaimInterface(const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;int<br>interfaceNumber); | Declares the interface on the specified device handle.|
| int&nbsp;UsbRawReleaseInterface(const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;in<br>t&nbsp;interfaceNumber); | Releases the previously declared interface.| **Table 3** APIs for USB device management on the device side
| int&nbsp;UsbRawResetDevice(const&nbsp;UsbRawHandle<br>\*devHandle); | Resets a device.|
| struct&nbsp;UsbRawRequest&nbsp;\*UsbRawAllocRequest(const<br>UsbRawHandle<br>\*devHandle,&nbsp;int&nbsp;isoPackets,&nbsp;int&nbsp;length); | Allocates a transfer request with the specified number of sync packet descriptors.|
| int&nbsp;UsbRawFreeRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request); | Releases the previously allocated transfer request.|
| int&nbsp;UsbRawFillBulkRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br>UsbRawFillRequestData&nbsp;\*fillData); | Fills in a bulk transfer request.|
| int&nbsp;UsbRawFillControlSetup(const&nbsp;unsigned&nbsp;char&nbsp;\*setup,<br>const&nbsp;struct&nbsp;UsbControlRequestData&nbsp;\*requestData); | Fills in a control setup packet.|
| int&nbsp;UsbRawFillControlRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br>UsbRawFillRequestData&nbsp;\*fillData); | Fills in a control transfer request.|
| int&nbsp;UsbRawFillInterruptRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br>UsbRawFillRequestData&nbsp;\*fillData); | Fills in an interrupt transfer request.|
| int&nbsp;UsbRawFillIsoRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br>UsbRawFillRequestData&nbsp;\*fillData); | Fills in an isochronous transfer request.|
| int&nbsp;UsbRawSubmitRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request); | Submits a transfer request.|
| int&nbsp;UsbRawCancelRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request); | Cancels a transfer request.|
| int&nbsp;UsbRawHandleRequests(const&nbsp;UsbRawHandle<br>\*devHandle); | Handles a transfer request event.|
The tables below describe the APIs provided by the USB device driver model.
**Table 3** usbfn_device.h
| API| Description| | API| Description|
| -------- | -------- | | -------- | -------- |
| const&nbsp;struct&nbsp;UsbFnDevice&nbsp;\*UsbFnCreateDevice(const<br>char&nbsp;\*udcName,&nbsp;const&nbsp;struct&nbsp;UsbFnDescriptorData<br>\*descriptor); | Creates a USB device.| | const&nbsp;struct&nbsp;UsbFnDevice&nbsp;\*UsbFnCreateDevice(const<br>char&nbsp;\*udcName,&nbsp;const&nbsp;struct&nbsp;UsbFnDescriptorData<br>\*descriptor); | Creates a USB device.|
| int&nbsp;UsbFnRemoveDevice(struct&nbsp;UsbFnDevice<br>\*fnDevice); | Deletes a USB device.| | int32_t&nbsp;UsbFnRemoveDevice(struct&nbsp;UsbFnDevice<br>\*fnDevice); | Deletes a USB device.|
| const&nbsp;struct&nbsp;UsbFnDevice&nbsp;\*UsbFnGetDevice(const&nbsp;char<br>\*udcName); | Obtains a USB device.| | const&nbsp;struct&nbsp;UsbFnDevice&nbsp;\*UsbFnGetDevice(const&nbsp;char<br>\*udcName); | Obtains a USB device.|
**Table 4** usbfn_interface.h The 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).
**Table 4** APIs for USB interface definition on the device side
| API| Description| | API| Description|
| -------- | -------- | | -------- | -------- |
| int&nbsp;UsbFnStartRecvInterfaceEvent(struct<br>UsbFnInterface&nbsp;\*interface,&nbsp;uint32_t&nbsp;eventMask,<br>UsbFnEventCallback&nbsp;callback,&nbsp;void&nbsp;\*context); | Starts receiving events.| | int32_t&nbsp;UsbFnStartRecvInterfaceEvent(struct<br>UsbFnInterface&nbsp;\*interface,&nbsp;uint32_t&nbsp;eventMask,<br>UsbFnEventCallback&nbsp;callback,&nbsp;void&nbsp;\*context); | Starts receiving events.|
| int&nbsp;UsbFnStopRecvInterfaceEvent(struct<br>UsbFnInterface&nbsp;\*interface); | Stops receiving events.| | int32_t&nbsp;UsbFnStopRecvInterfaceEvent(struct<br>UsbFnInterface&nbsp;\*interface); | Stops receiving events.|
| UsbFnInterfaceHandle&nbsp;UsbFnOpenInterface(struct&nbsp;UsbFnInterface&nbsp;\*interface); | Opens an interface.| | UsbFnInterfaceHandle&nbsp;UsbFnOpenInterface(struct&nbsp;UsbFnInterface&nbsp;\*interface); | Opens an interface.|
| int&nbsp;UsbFnCloseInterface(UsbFnInterfaceHandle&nbsp;handle); | Closes an interface.| | int32_t&nbsp;UsbFnCloseInterface(UsbFnInterfaceHandle&nbsp;handle); | Closes an interface.|
| int&nbsp;UsbFnGetInterfacePipeInfo(struct&nbsp;UsbFnInterface<br>\*interface,&nbsp;uint8_t&nbsp;pipeId,&nbsp;struct&nbsp;UsbFnPipeInfo&nbsp;\*info); | Obtains pipe information.| | int32_t&nbsp;UsbFnGetInterfacePipeInfo(struct&nbsp;UsbFnInterface<br>\*interface,&nbsp;uint8_t&nbsp;pipeId,&nbsp;struct&nbsp;UsbFnPipeInfo&nbsp;\*info); | Obtains pipe information.|
| int&nbsp;UsbFnSetInterfaceProp(const&nbsp;struct&nbsp;UsbFnInterface<br>\*interface,&nbsp;const&nbsp;char&nbsp;\*name,&nbsp;const&nbsp;char&nbsp;\*value); | Sets custom properties.| | int32_t&nbsp;UsbFnSetInterfaceProp(const&nbsp;struct&nbsp;UsbFnInterface<br>\*interface,&nbsp;const&nbsp;char&nbsp;\*name,&nbsp;const&nbsp;char&nbsp;\*value); | Sets custom properties.|
The 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).
**Table 5** usbfn_request.h **Table 5** APIs for USB data request on the device side
| API| Description| | API| Description|
| -------- | -------- | | -------- | -------- |
| struct&nbsp;UsbFnRequest<br>\*UsbFnAllocCtrlRequest(UsbFnInterfaceHandle&nbsp;handle,<br>uint32_t&nbsp;len); | Allocates a control transfer request.| | struct&nbsp;UsbFnRequest<br>\*UsbFnAllocCtrlRequest(UsbFnInterfaceHandle&nbsp;handle,<br>uint32_t&nbsp;len); | Allocates a control transfer request.|
| struct&nbsp;UsbFnRequest&nbsp;\*UsbFnAllocRequest(UsbFnInterfaceHandle&nbsp;handle,<br>uint8_t&nbsp;pipe,&nbsp;uint32_t&nbsp;len); | Allocates a data request.| | struct&nbsp;UsbFnRequest&nbsp;\*UsbFnAllocRequest(UsbFnInterfaceHandle&nbsp;handle,<br>uint8_t&nbsp;pipe,&nbsp;uint32_t&nbsp;len); | Allocates a data request.|
| int&nbsp;UsbFnFreeRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | Releases a request.| | int32_t&nbsp;UsbFnFreeRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | Releases a request.|
| int&nbsp;UsbFnSubmitRequestAsync(struct&nbsp;UsbFnRequest<br>\*req); | Sends an asynchronous request.| | int32_t&nbsp;UsbFnSubmitRequestAsync(struct&nbsp;UsbFnRequest<br>\*req); | Sends an asynchronous request.|
| int&nbsp;UsbFnSubmitRequestSync(struct&nbsp;UsbFnRequest<br>\*req,&nbsp;uint32_t&nbsp;timeout); | Sends a synchronous request.| | int32_t&nbsp;UsbFnSubmitRequestSync(struct&nbsp;UsbFnRequest<br>\*req,&nbsp;uint32_t&nbsp;timeout); | Sends a synchronous request.|
| int&nbsp;UsbFnCancelRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | Cancels a request.| | int32_t&nbsp;UsbFnCancelRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | Cancels a request.|
### How to Develop
USB 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.
#### Developing Driver Using Host DDK APIs
1. Configure USB host driver information in the .hcs file of private device data.
```cpp
root {
module = "usb_pnp_device";
usb_pnp_config {
match_attr = "usb_pnp_match";
usb_pnp_device_id = "UsbPnpDeviceId";
UsbPnpDeviceId {
idTableList = [
"host_acm_table"
];
host_acm_table {
// Driver module name, which must be the same as the value of moduleName in the driver entry structure.
moduleName = "usbhost_acm";
// Service name of the driver, which must be unique.
serviceName = "usbhost_acm_pnp_service";
// Keyword for matching private driver data.
deviceMatchAttr = "usbhost_acm_pnp_matchAttr";
// Data length starting from this field, in bytes.
length = 21;
// USB driver matching rule: vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber.
matchFlag = 0x0303;
// Vendor ID.
vendorId = 0x12D1;
// Product ID.
productId = 0x5000;
// The least significant 16 bits of the device sequence number.
bcdDeviceLow = 0x0000;
// The most significant 16 bits of the device sequence number.
bcdDeviceHigh = 0x0000;
// Device class code allocated by the USB.
deviceClass = 0;
// Child class code allocated by the USB.
deviceSubClass = 0;
// Device protocol code allocated by the USB.
deviceProtocol = 0;
// Interface type. You can enter multiple types as needed.
interfaceClass = [0];
// Interface subtype. You can enter multiple subtypes as needed.
interfaceSubClass = [2, 0];
// Protocol that the interface complies with. You can enter multiple protocols as needed.
interfaceProtocol = [1, 2];
// Interface number. You can enter multiple interface numbers as needed.
interfaceNumber = [2, 3];
}
}
}
}
```
2. Initialize the USB host driver DDK.
## How to Develop ```cpp
int32_t UsbInitHostSdk(struct UsbSession **session);
```
The USB driver is 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 document uses a serial port as an example to describe how to develop drivers for the USB host and USB device. 3. Obtain the **UsbInterface** object after initialization.
```cpp
const struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex);
```
### Developing Driver Using Host DDK APIs 4. Open the **UsbInterface** object to obtain the **UsbInterfaceHandle** object.
1. Configure the driver mapping table. ```cpp
UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);
```
2. Initialize the USB host DDK. 5. Obtain pipe information of the specified **pipeIndex** based on the **UsbInterfaceHandle** object.
3. Obtain a **UsbInterface** object. ```cpp
int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);
```
4. Open the **UsbInterface** object to obtain the **UsbInterfaceHandle** object. 6. Pre-allocate an I/O request for the **UsbInterfaceHandle** object.
5. Obtain pipe information of the specified **pipeIndex** based on the **UsbInterfaceHandle** object. ```cpp
struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int32_t isoPackets, int32_t length);
6. Allocate an I/O request for the **UsbInterfaceHandle** object. ```
7. Fill in the I/O request based on the input parameters. 7. Fill in the I/O request based on the input parameters.
```cpp
int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params);
```
8. Submit the I/O request in synchronous or asynchronous mode. 8. Submit the I/O request in synchronous or asynchronous mode.
```cpp
int32_t UsbSubmitRequestSync(const struct UsbRequest *request); // Send a synchronous I/O request.
int32_t UsbSubmitRequestAsync(const struct UsbRequest *request); // Send an asynchronous I/O request.
```
### Developing Driver Using Host Raw APIs #### Developing Driver Using Host Raw APIs
1. Configure the driver mapping table. 1. Configure USB host driver information in the .hcs file of private device data. For details, see step 1 in the previous section.
2. Initialize the host raw data, open the USB device, obtain the descriptor, and then obtain interface and endpoint information based on the descriptor. 2. Initialize the host raw data, open the USB device, obtain the descriptor, and then obtain interface and endpoint information based on the descriptor.
3. Allocate a request and fill in the request based on the transfer type. ```cpp
int32_t UsbRawInit(struct UsbSession **session);
4. Submit the I/O request in synchronous or asynchronous mode. ```
3. Open the USB device.
### Developing Driver Using Device DDK APIs
```cpp
1. Construct a descriptor. UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);
```
2. Instantiate a USB device using the descriptor constructed.
4. Obtain the device descriptor, and obtain the interface and endpoint information based on the descriptor.
3. Call **UsbFnDeviceGetInterface** to obtain an interface, call **UsbFnInterfaceGetPipeInfo** to obtain pipe information based on the interface, call **UsbFnInterfaceOpen** to open the interface to obtain the handle, and call **UsbFnRequestAlloc** to obtain the request based on the handle and pipe ID.
```cpp
4. Call **UsbFnInterfaceStartRecvEvent** to receive events such as Enable and Setup, and respond to the events in **UsbFnEventCallback**. int32_t UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);
```
5. Send and receive data in synchronous or asynchronous mode.
5. Allocate a request and fill in the request based on the transfer type.
```cpp
int32_t UsbRawFillBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // Populate the request for bulk transfer.
int32_t UsbRawFillControlSetup(const unsigned char *setup, const struct UsbControlRequestData *requestData);
int32_t UsbRawFillControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // Populate the request for control transfer.
int32_t UsbRawFillInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // Populate the request for interrupt transfer.
int32_t UsbRawFillIsoRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData); // Populate the request for isochronous transfer.
```
6. Submit the I/O request in synchronous or asynchronous mode.
```cpp
int32_t UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData); // Send a synchronous request for control transfer.
int32_t UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData); // Send a synchronous request for bulk transfer.
int32_t UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData); // Send a synchronous request for interrupt transfer.
int32_t UsbRawSubmitRequest(const struct UsbRawRequest *request); // Send an asynchronous I/O request.
```
#### Developing Driver Using Device DDK APIs
1. Construct a descriptor in the device function code.
```cpp
static struct UsbFnFunction g_acmFunction = { // Function descriptor
.enable = true,
.funcName = "f_generic.a",
.strings = g_acmStrings,
.fsDescriptors = g_acmFsFunction,
.hsDescriptors = g_acmHsFunction,
.ssDescriptors = g_acmSsFunction,
.sspDescriptors = NULL,
};
struct UsbFnFunction *g_functions[] = {
#ifdef CDC_ECM
&g_ecmFunction,
#endif
#ifdef CDC_ACM
&g_acmFunction,
#endif
NULL
};
static struct UsbFnConfiguration g_masterConfig = { // Configuration descriptor
.configurationValue = 1,
.iConfiguration = USB_FUNC_CONFIG_IDX,
.attributes = USB_CFG_BUS_POWERED,
.maxPower = POWER,
.functions = g_functions,
};
static struct UsbFnConfiguration *g_configs[] = {
&g_masterConfig,
NULL,
};
static struct UsbDeviceDescriptor g_cdcMasterDeviceDesc = { // Device descriptor
.bLength = sizeof(g_cdcMasterDeviceDesc),
.bDescriptorType = USB_DDK_DT_DEVICE,
.bcdUSB = CpuToLe16(BCD_USB),
.bDeviceClass = 0,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = USB_MAX_PACKET_SIZE,
.idVendor = CpuToLe16(DEVICE_VENDOR_ID),
.idProduct = CpuToLe16(DEVICE_PRODUCT_ID),
.bcdDevice = CpuToLe16(DEVICE_VERSION),
.iManufacturer = USB_FUNC_MANUFACTURER_IDX,
.iProduct = USB_FUNC_PRODUCT_IDX,
.iSerialNumber = USB_FUNC_SERIAL_IDX,
.bNumConfigurations = 1,
};
static struct UsbFnDeviceDesc g_masterFuncDevice = { // Descriptor entry
.deviceDesc = &g_cdcMasterDeviceDesc,
.deviceStrings = g_devStrings,
.configs = g_configs,
};
```
2. Create a USB device. Call **UsbFnDeviceCreate** and pass in the UDC controller and **UsbFnDescriptorData** structure to create a USB device.
```cpp
if (useHcs == 0) { // Descriptor written in the code.
descData.type = USBFN_DESC_DATA_TYPE_DESC;
descData.descriptor = &g_acmFuncDevice;
} else { // Descriptor compiled by using the .hcs file.
descData.type = USBFN_DESC_DATA_TYPE_PROP;
descData.property = acm->device->property;
}
// Create a USB device.
fnDev = (struct UsbFnDevice *) UsbFnCreateDevice(acm->udcName, &descData);
```
3. Call **UsbFnGetInterface** to obtain a **UsbInterface** object, and call **UsbFnGetInterfacePipeInfo** to obtain the USB pipe information.
```cpp
// Obtain an interface.
fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
// Obtain the pipe information.
UsbFnGetInterfacePipeInfo(fnIface, i, &pipeInfo);
// Obtain a handle.
handle = UsbFnOpenInterface(fnIface);
// Obtain a control (EP0) request.
req = UsbFnAllocCtrlRequest(acm->ctrlIface.handle,
sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
// Obtain the request.
req = UsbFnAllocCtrlRequest(acm->ctrlIface.handle,
sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
```
4. Call **UsbFnStartRecvInterfaceEvent** to receive events, and call **UsbFnEventCallback** to respond to the events.
```cpp
// Start receiving events.
ret = UsbFnStartRecvInterfaceEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm);
// Process the event in the callback.
static void UsbAcmEventCallback(struct UsbFnEvent *event)
{
struct UsbAcmDevice *acm = NULL;
if (event == NULL || event->context == NULL) {
HDF_LOGE("%s: event is null", __func__);
return;
}
acm = (struct UsbAcmDevice *)event->context;
switch (event->type) {
case USBFN_STATE_BIND:
HDF_LOGI("%s: receive bind event", __func__);
break;
case USBFN_STATE_UNBIND:
HDF_LOGI("%s: receive unbind event", __func__);
break;
case USBFN_STATE_ENABLE:
HDF_LOGI("%s: receive enable event", __func__);
AcmEnable(acm);
break;
case USBFN_STATE_DISABLE:
HDF_LOGI("%s: receive disable event", __func__);
AcmDisable(acm);
acm->enableEvtCnt = 0;
break;
case USBFN_STATE_SETUP:
HDF_LOGI("%s: receive setup event", __func__);
if (event->setup != NULL) {
AcmSetup(acm, event->setup);
}
break;
case USBFN_STATE_SUSPEND:
HDF_LOGI("%s: receive suspend event", __func__);
AcmSuspend(acm);
break;
case USBFN_STATE_RESUME:
HDF_LOGI("%s: receive resume event", __func__);
AcmResume(acm);
break;
default:
break;
}
}
```
## Development Example 5. Send and receive data in synchronously or asynchronously.
The following examples help you better understand the development of the USB serial port driver. ```cpp
notify = (struct UsbCdcNotification *)req->buf;
...
if (memcpy_s((void *)(notify + 1), length, data, length) != EOK) {
return HDF_FAILURE;
}
ret = UsbFnSubmitRequestAsync(req); // Send data asynchronously.
```
### Development Example
### Developing Driver Using Host DDK APIs The following example helps you better understand the development of the USB serial port driver.
#### Developing Driver Using Host DDK APIs
```
root {
module = "usb_pnp_device";
usb_pnp_config {
match_attr = "usb_pnp_match";
usb_pnp_device_id = "UsbPnpDeviceId";
UsbPnpDeviceId {
idTableList = [
"host_acm_table"
];
host_acm_table {
// Driver module name, which must be the same as the value of moduleName in the driver entry structure.
moduleName = "usbhost_acm";
// Service name of the driver, which must be unique.
serviceName = "usbhost_acm_pnp_service";
// Keyword for matching private driver data.
deviceMatchAttr = "usbhost_acm_pnp_matchAttr";
// Data length starting from this field, in bytes.
length = 21;
// USB driver matching rule: vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber.
matchFlag = 0x0303;
// Vendor ID.
vendorId = 0x12D1;
// Product ID.
productId = 0x5000;
// The least significant 16 bits of the device sequence number.
bcdDeviceLow = 0x0000;
// The most significant 16 bits of the device sequence number.
bcdDeviceHigh = 0x0000;
// Device class code allocated by the USB.
deviceClass = 0;
// Child class code allocated by the USB.
deviceSubClass = 0;
// Device protocol code allocated by the USB.
deviceProtocol = 0;
// Interface type. You can enter multiple types as needed.
interfaceClass = [0];
// Interface subtype. You can enter multiple subtypes as needed.
interfaceSubClass = [2, 0];
// Protocol that the interface complies with. You can enter multiple protocols as needed.
interfaceProtocol = [1, 2];
// Interface number. You can enter multiple interface numbers as needed.
interfaceNumber = [2, 3];
}
}
}
}
```cpp
#include "usb_serial.h" #include "usb_serial.h"
#include "hdf_base.h" #include "hdf_base.h"
#include "hdf_log.h" #include "hdf_log.h"
...@@ -231,53 +459,52 @@ root { ...@@ -231,53 +459,52 @@ root {
#define HDF_LOG_TAG USB_HOST_ACM #define HDF_LOG_TAG USB_HOST_ACM
#define STR_LEN 512 #define STR_LEN 512
static struct UsbRequest *g_syncRequest = NULL; static struct UsbRequest *g_syncRequest = NULL; // Define a USB request.
static struct UsbRequest *g_ctrlCmdRequest = NULL; static struct UsbRequest *g_ctrlCmdRequest = NULL;
static bool g_acmReleaseFlag = false; static bool g_acmReleaseFlag = false;
static uint8_t *g_acmReadBuffer = NULL; static uint8_t *g_acmReadBuffer = NULL;
... ...
static int SerialCtrlMsg(struct AcmDevice *acm, uint8_t request, static int32_t SerialCtrlMsg(struct AcmDevice *acm, uint8_t request,
uint16_t value, void *buf, uint16_t len) uint16_t value, void *buf, uint16_t len)
{ {
int ret; int32_t ret;
uint16_t index = acm->intPipe->interfaceId; uint16_t index = acm->intPipe->interfaceId;
struct UsbControlParams controlParams; struct UsbControlParams controlParams;
struct UsbRequestParams params; struct UsbRequestParams params; // Define a UsbRequestParams object.
if (acm == NULL || buf == NULL) { if (acm == NULL || buf == NULL) {
HDF_LOGE("%s:invalid param", __func__);
return HDF_ERR_IO; return HDF_ERR_IO;
} }
if (acm->ctrlReq == NULL) { if (acm->ctrlReq == NULL) {
// Pre-allocate the IO Request object to be sent to UsbInterfaceHandle.
acm->ctrlReq = UsbAllocRequest(acm->ctrDevHandle, 0, len); acm->ctrlReq = UsbAllocRequest(acm->ctrDevHandle, 0, len);
if (acm->ctrlReq == NULL) { if (acm->ctrlReq == NULL) {
HDF_LOGE("%s: UsbAllocRequest failed", __func__);
return HDF_ERR_IO; return HDF_ERR_IO;
} }
} }
controlParams.request = request; controlParams.request = request;
controlParams.target = USB_REQUEST_TARGET_INTERFACE; controlParams.target = USB_REQUEST_TARGET_INTERFACE; // Interface object
controlParams.reqType = USB_REQUEST_TYPE_CLASS; controlParams.reqType = USB_REQUEST_TYPE_CLASS; // Request type
controlParams.direction = USB_REQUEST_DIR_TO_DEVICE; controlParams.direction = USB_REQUEST_DIR_TO_DEVICE; // Data transfer from the host to the device
controlParams.value = value; controlParams.value = value;
controlParams.index = index; controlParams.index = index;
controlParams.data = buf; controlParams.data = buf;
controlParams.size = len; controlParams.size = len;
params.interfaceId = USB_CTRL_INTERFACE_ID; params.interfaceId = USB_CTRL_INTERFACE_ID; // Define the default ID of the USB control interface.
params.pipeAddress = acm->ctrPipe->pipeAddress; params.pipeAddress = acm->ctrPipe->pipeAddress;
params.pipeId = acm->ctrPipe->pipeId; params.pipeId = acm->ctrPipe->pipeId;
params.requestType = USB_REQUEST_PARAMS_CTRL_TYPE; params.requestType = USB_REQUEST_PARAMS_CTRL_TYPE; // Control type.
params.timeout = USB_CTRL_SET_TIMEOUT; params.timeout = USB_CTRL_SET_TIMEOUT; // Set the timeout interval.
params.ctrlReq = UsbControlSetUp(&controlParams); params.ctrlReq = UsbControlSetUp(&controlParams);
// Fill in the pre-allocated I/O request based on UsbRequestParams.
ret = UsbFillRequest(acm->ctrlReq, acm->ctrDevHandle, &params); ret = UsbFillRequest(acm->ctrlReq, acm->ctrDevHandle, &params);
if (HDF_SUCCESS != ret) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: failed, ret=%d ", __func__, ret);
return ret; return ret;
} }
ret = UsbSubmitRequestSync(acm->ctrlReq); // Send an I/O request synchronously. // Send an I/O request synchronously.
if (HDF_SUCCESS != ret) { ret = UsbSubmitRequestSync(acm->ctrlReq);
HDF_LOGE("UsbSubmitRequestSync failed, ret=%d ", ret); if (ret != HDF_SUCCESS) {
return ret; return ret;
} }
if (!acm->ctrlReq->compInfo.status) { if (!acm->ctrlReq->compInfo.status) {
...@@ -290,8 +517,8 @@ static struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm, ...@@ -290,8 +517,8 @@ static struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm,
uint8_t interfaceIndex) uint8_t interfaceIndex)
{ {
struct UsbInterface *tmpIf = NULL; struct UsbInterface *tmpIf = NULL;
tmpIf = (struct UsbInterface *)UsbClaimInterface(acm->session, acm->busNum, // Obtain a UsbInterface object.
acm->devAddr, interfaceIndex); // Obtain the UsbInterface object. tmpIf = (struct UsbInterface *)UsbClaimInterface(acm->session, acm->busNum, acm->devAddr, interfaceIndex);
return tmpIf; return tmpIf;
} }
... ...
...@@ -299,9 +526,9 @@ static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm, ...@@ -299,9 +526,9 @@ static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm,
uint8_t interfaceIndex, UsbPipeType pipeType, UsbPipeDirection pipeDirection) uint8_t interfaceIndex, UsbPipeType pipeType, UsbPipeDirection pipeDirection)
{ {
uint8_t i; uint8_t i;
int ret; int32_t ret;
struct UsbInterfaceInfo *info = NULL; struct UsbInterfaceInfo *info = NULL; // Define a UsbInterfaceInfo object.
UsbInterfaceHandle *interfaceHandle = NULL; UsbInterfaceHandle *interfaceHandle = NULL; // Define a USB interface operation handle (that is, the void * type).
if (pipeType == USB_PIPE_TYPE_CONTROL) if (pipeType == USB_PIPE_TYPE_CONTROL)
{ {
info = &acm->ctrIface->info; info = &acm->ctrIface->info;
...@@ -310,19 +537,20 @@ static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm, ...@@ -310,19 +537,20 @@ static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm,
else else
{ {
info = &acm->iface[interfaceIndex]->info; info = &acm->iface[interfaceIndex]->info;
// Obtain the device handle based on interfaceIndex.
interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex); interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex);
} }
for (i = 0; i <= info->pipeNum; i++) { for (i = 0; i <= info->pipeNum; i++) {
struct UsbPipeInfo p; struct UsbPipeInfo p;
ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);// Obtain information about the pipe with index i. // Obtain the pipeInfo object whose index is i.
ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);
if (ret < 0) { if (ret < 0) {
continue; continue;
} }
if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) { if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) {
struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi)); struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi)); // Allocate and initialize the memory.
if (pi == NULL) { if (pi == NULL) {
HDF_LOGE("%s: Alloc pipe failed", __func__);
return NULL; return NULL;
} }
p.interfaceId = info->interfaceIndex; p.interfaceId = info->interfaceIndex;
...@@ -338,7 +566,6 @@ static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm, ...@@ -338,7 +566,6 @@ static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm,
{ {
uint8_t i; uint8_t i;
if (acm == NULL) { if (acm == NULL) {
HDF_LOGE("%s: invalid params", __func__);
return NULL; return NULL;
} }
for (i = 0; i < acm->interfaceCnt; i++) { for (i = 0; i < acm->interfaceCnt; i++) {
...@@ -346,6 +573,7 @@ static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm, ...@@ -346,6 +573,7 @@ static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm,
if (!acm->iface[i]) { if (!acm->iface[i]) {
continue; continue;
} }
// Obtain pipe information of the control pipe.
p = EnumePipe(acm, i, pipeType, pipeDirection); p = EnumePipe(acm, i, pipeType, pipeDirection);
if (p == NULL) { if (p == NULL) {
continue; continue;
...@@ -362,40 +590,32 @@ static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) ...@@ -362,40 +590,32 @@ static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device)
errno_t err; errno_t err;
struct AcmDevice *acm = NULL; struct AcmDevice *acm = NULL;
if (device == NULL) { if (device == NULL) {
HDF_LOGE("%s: device is null", __func__);
return HDF_ERR_INVALID_OBJECT; return HDF_ERR_INVALID_OBJECT;
} }
acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm)); acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm));
if (acm == NULL) { if (acm == NULL) {
HDF_LOGE("%s: Alloc usb serial device failed", __func__);
return HDF_FAILURE; return HDF_FAILURE;
} }
// Initialize the mutex. &acm->lock indicates the pointer pointing to the mutex.
if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) {
HDF_LOGE("%s:%d OsalMutexInit failed", __func__, __LINE__);
goto error; goto error;
} }
info = (struct UsbPnpNotifyServiceInfo *)device->priv; info = (struct UsbPnpNotifyServiceInfo *)device->priv;
if (info != NULL) { if (info != NULL) {
HDF_LOGD("%s:%d busNum=%d,devAddr=%d,interfaceLength=%d",
__func__, __LINE__, info->busNum, info->devNum, info->interfaceLength);
acm->busNum = info->busNum; acm->busNum = info->busNum;
acm->devAddr = info->devNum; acm->devAddr = info->devNum;
acm->interfaceCnt = info->interfaceLength; acm->interfaceCnt = info->interfaceLength;
err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES,
(const void*)info->interfaceNumber, info->interfaceLength); (const void*)info->interfaceNumber, info->interfaceLength);
if (err != EOK) { if (err != EOK) {
HDF_LOGE("%s:%d memcpy_s failed err=%d",
__func__, __LINE__, err);
goto lock_error; goto lock_error;
} }
} else { } else {
HDF_LOGE("%s:%d info is NULL!", __func__, __LINE__);
goto lock_error; goto lock_error;
} }
acm->device = device; acm->device = device;
device->service = &(acm->service); device->service = &(acm->service);
acm->device->service->Dispatch = UsbSerialDeviceDispatch; acm->device->service->Dispatch = UsbSerialDeviceDispatch;
HDF_LOGD("UsbSerialDriverBind=========================OK");
return HDF_SUCCESS; return HDF_SUCCESS;
lock_error: lock_error:
...@@ -408,14 +628,14 @@ error: ...@@ -408,14 +628,14 @@ error:
return HDF_FAILURE; return HDF_FAILURE;
} }
... ...
static int AcmAllocReadRequests(struct AcmDevice *acm) static int32_t AcmAllocReadRequests(struct AcmDevice *acm)
{ {
int ret; int32_t ret;
struct UsbRequestParams readParams; struct UsbRequestParams readParams;
for (int i = 0; i < ACM_NR; i++) { for (int32_t i = 0; i < ACM_NR; i++) {
acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize); // Allocate the readReq I/O request to be sent. // Allocate the readReq I/O request to be sent.
acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize);
if (!acm->readReq[i]) { if (!acm->readReq[i]) {
HDF_LOGE("readReq request failed");
goto error; goto error;
} }
readParams.userData = (void *)acm; readParams.userData = (void *)acm;
...@@ -423,14 +643,14 @@ static int AcmAllocReadRequests(struct AcmDevice *acm) ...@@ -423,14 +643,14 @@ static int AcmAllocReadRequests(struct AcmDevice *acm)
readParams.pipeId = acm->dataInPipe->pipeId; readParams.pipeId = acm->dataInPipe->pipeId;
readParams.interfaceId = acm->dataInPipe->interfaceId; readParams.interfaceId = acm->dataInPipe->interfaceId;
readParams.callback = AcmReadBulk; readParams.callback = AcmReadBulk;
readParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE; readParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE; /* Data type */
readParams.timeout = USB_CTRL_SET_TIMEOUT; readParams.timeout = USB_CTRL_SET_TIMEOUT;
readParams.dataReq.numIsoPackets = 0; readParams.dataReq.numIsoPackets = 0;
readParams.dataReq.direction = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1; readParams.dataReq.direction = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1;
readParams.dataReq.length = acm->readSize; readParams.dataReq.length = acm->readSize;
ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParams); // Fills in the readReq object to be sent. // Fill in the readReq IO Request object to be sent based on readParams.
if (HDF_SUCCESS != ret) { ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParams);
HDF_LOGE("%s: UsbFillRequest failed, ret=%d n", __func__, ret); if (ret != HDF_SUCCESS) {
goto error; goto error;
} }
} }
...@@ -441,13 +661,13 @@ error: ...@@ -441,13 +661,13 @@ error:
return HDF_ERR_MALLOC_FAIL; return HDF_ERR_MALLOC_FAIL;
} }
static int AcmAllocNotifyRequest(struct AcmDevice *acm) static int32_t AcmAllocNotifyRequest(struct AcmDevice *acm)
{ {
int ret; int32_t ret;
struct UsbRequestParams intParams = {}; struct UsbRequestParams intParams = {};
acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize); // Allocate the interrupt I/O request object to be sent. // Allocate the interrupt I/O request to be sent.
acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize);
if (!acm->notifyReq) { if (!acm->notifyReq) {
HDF_LOGE("notifyReq request failed");
return HDF_ERR_MALLOC_FAIL; return HDF_ERR_MALLOC_FAIL;
} }
intParams.userData = (void *)acm; intParams.userData = (void *)acm;
...@@ -460,9 +680,9 @@ static int AcmAllocNotifyRequest(struct AcmDevice *acm) ...@@ -460,9 +680,9 @@ static int AcmAllocNotifyRequest(struct AcmDevice *acm)
intParams.dataReq.numIsoPackets = 0; intParams.dataReq.numIsoPackets = 0;
intParams.dataReq.direction = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK; intParams.dataReq.direction = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK;
intParams.dataReq.length = acm->intSize; intParams.dataReq.length = acm->intSize;
ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParams); // Fill in the interrupt I/O request. // Fill in the interrupt I/O request.
if (HDF_SUCCESS != ret) { ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParams);
HDF_LOGE("%s: UsbFillRequest failed, ret=%d n", __func__, ret); if (ret != HDF_SUCCESS) {
goto error; goto error;
} }
return HDF_SUCCESS; return HDF_SUCCESS;
...@@ -474,8 +694,9 @@ error: ...@@ -474,8 +694,9 @@ error:
static void AcmReleaseInterfaces(struct AcmDevice *acm) static void AcmReleaseInterfaces(struct AcmDevice *acm)
{ {
for (int i = 0; i < acm->interfaceCnt; i++) { for (int32_t i = 0; i < acm->interfaceCnt; i++) {
if (acm->iface[i]) { if (acm->iface[i]) {
// Release a USB interface object.
UsbReleaseInterface(acm->iface[i]); UsbReleaseInterface(acm->iface[i]);
acm->iface[i] = NULL; acm->iface[i] = NULL;
} }
...@@ -488,31 +709,33 @@ static void AcmReleaseInterfaces(struct AcmDevice *acm) ...@@ -488,31 +709,33 @@ static void AcmReleaseInterfaces(struct AcmDevice *acm)
static int32_t AcmClaimInterfaces(struct AcmDevice *acm) static int32_t AcmClaimInterfaces(struct AcmDevice *acm)
{ {
for (int i = 0; i < acm->interfaceCnt; i++) { for (int32_t i = 0; i < acm->interfaceCnt; i++) {
acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]); // Obtain the UsbInterface object. // Obtain a UsbInterface object.
acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]);
if (acm->iface[i] == NULL) { if (acm->iface[i] == NULL) {
HDF_LOGE("%s: interface%d is null", __func__, acm->interfaceIndex[i]);
goto error; goto error;
} }
} }
acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID); // Obtain the UsbInterface object corresponding to the control interface. // Obtain the UsbInterface object corresponding to the control interface.
acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID);
if (acm->ctrIface == NULL) { if (acm->ctrIface == NULL) {
HDF_LOGE("%s: GetUsbInterfaceById null", __func__);
goto error; goto error;
} }
return HDF_SUCCESS; return HDF_SUCCESS;
error: error:
// Release the UsbInterface object cyclically based on acm->interfaceCnt.
AcmReleaseInterfaces(acm); AcmReleaseInterfaces(acm);
return HDF_FAILURE; return HDF_FAILURE;
} }
static void AcmCloseInterfaces(struct AcmDevice *acm) static void AcmCloseInterfaces(struct AcmDevice *acm)
{ {
for (int i = 0; i < acm->interfaceCnt; i++) { for (int32_t i = 0; i < acm->interfaceCnt; i++) {
if (acm->devHandle[i]) { if (acm->devHandle[i]) {
// Close a USB device object.
UsbCloseInterface(acm->devHandle[i]); UsbCloseInterface(acm->devHandle[i]);
acm->devHandle[i] = NULL; acm->devHandle[i] = NULL;
} }
...@@ -525,51 +748,51 @@ static void AcmCloseInterfaces(struct AcmDevice *acm) ...@@ -525,51 +748,51 @@ static void AcmCloseInterfaces(struct AcmDevice *acm)
static int32_t AcmOpenInterfaces(struct AcmDevice *acm) static int32_t AcmOpenInterfaces(struct AcmDevice *acm)
{ {
for (int i = 0; i < acm->interfaceCnt; i++) { for (int32_t i = 0; i < acm->interfaceCnt; i++) {
if (acm->iface[i]) { if (acm->iface[i]) {
acm->devHandle[i] = UsbOpenInterface(acm->iface[i]); // Open the UsbInterface object obtained. // Open the UsbInterface object obtained.
acm->devHandle[i] = UsbOpenInterface(acm->iface[i]);
if (acm->devHandle[i] == NULL) { if (acm->devHandle[i] == NULL) {
HDF_LOGE("%s: UsbOpenInterface null", __func__);
goto error; goto error;
} }
} }
} }
acm->ctrDevHandle = UsbOpenInterface(acm->ctrIface); acm->ctrDevHandle = UsbOpenInterface(acm->ctrIface);
if (acm->ctrDevHandle == NULL) { if (acm->ctrDevHandle == NULL) {
HDF_LOGE("%s: ctrDevHandle UsbOpenInterface null", __func__);
goto error; goto error;
} }
return HDF_SUCCESS; return HDF_SUCCESS;
error: error:
// Disable all UsbInterface objects.
AcmCloseInterfaces(acm); AcmCloseInterfaces(acm);
return HDF_FAILURE; return HDF_FAILURE;
} }
static int32_t AcmGetPipes(struct AcmDevice *acm) static int32_t AcmGetPipes(struct AcmDevice *acm)
{ {
acm->dataInPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN);// Obtain pipe information of dataInPipe. // Obtain pipe information of dataInPipe.
acm->dataInPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN);
if (acm->dataInPipe == NULL) { if (acm->dataInPipe == NULL) {
HDF_LOGE("dataInPipe is NULL");
goto error; goto error;
} }
acm->dataOutPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT); // Obtain pipe information of dataOutPipe. // Obtain pipe information of dataOutPipe.
acm->dataOutPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT);
if (acm->dataOutPipe == NULL) { if (acm->dataOutPipe == NULL) {
HDF_LOGE("dataOutPipe is NULL");
goto error; goto error;
} }
acm->ctrPipe = EnumePipe(acm, acm->ctrIface->info.interfaceIndex, USB_PIPE_TYPE_CONTROL, USB_PIPE_DIRECTION_OUT); // Obtain pipe information of the control pipe. // Obtain pipe information of the control pipe.
acm->ctrPipe = EnumePipe(acm, acm->ctrIface->info.interfaceIndex, USB_PIPE_TYPE_CONTROL, USB_PIPE_DIRECTION_OUT);
if (acm->ctrPipe == NULL) { if (acm->ctrPipe == NULL) {
HDF_LOGE("ctrPipe is NULL");
goto error; goto error;
} }
acm->intPipe = GetPipe(acm, USB_PIPE_TYPE_INTERRUPT, USB_PIPE_DIRECTION_IN); // Obtain pipe information of the interrupt pipe. //Obtain pipe information of the interrupt pipe.
acm->intPipe = GetPipe(acm, USB_PIPE_TYPE_INTERRUPT, USB_PIPE_DIRECTION_IN);
if (acm->intPipe == NULL) { if (acm->intPipe == NULL) {
HDF_LOGE("intPipe is NULL");
goto error; goto error;
} }
...@@ -577,10 +800,10 @@ static int32_t AcmGetPipes(struct AcmDevice *acm) ...@@ -577,10 +800,10 @@ static int32_t AcmGetPipes(struct AcmDevice *acm)
acm->writeSize = acm->dataOutPipe->maxPacketSize; acm->writeSize = acm->dataOutPipe->maxPacketSize;
acm->ctrlSize = acm->ctrPipe->maxPacketSize; acm->ctrlSize = acm->ctrPipe->maxPacketSize;
acm->intSize = acm->intPipe->maxPacketSize; acm->intSize = acm->intPipe->maxPacketSize;
return HDF_SUCCESS; return HDF_SUCCESS;
error: error:
// Release all pipe information on the device.
AcmFreePipes(acm); AcmFreePipes(acm);
return HDF_FAILURE; return HDF_FAILURE;
} }
...@@ -602,29 +825,26 @@ static int32_t AcmAllocRequests(struct AcmDevice *acm) ...@@ -602,29 +825,26 @@ static int32_t AcmAllocRequests(struct AcmDevice *acm)
int32_t ret; int32_t ret;
if (AcmWriteBufAlloc(acm) < 0) { if (AcmWriteBufAlloc(acm) < 0) {
HDF_LOGE("%s: AcmWriteBufAlloc failed", __func__);
return HDF_ERR_MALLOC_FAIL; return HDF_ERR_MALLOC_FAIL;
} }
for (int i = 0; i < ACM_NW; i++) { for (int32_t i = 0; i < ACM_NW; i++) {
struct AcmWb *snd = &(acm->wb[i]); struct AcmWb *snd = &(acm->wb[i]);
snd->request = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataOutPipe->interfaceId), 0, acm->writeSize); // Allocate the I/O request object to be sent. // Allocate the I/O request to be sent.
snd->request = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataOutPipe->interfaceId), 0, acm->writeSize);
snd->instance = acm; snd->instance = acm;
if (snd->request == NULL) { if (snd->request == NULL) {
HDF_LOGE("%s:%d snd request failed", __func__, __LINE__);
goto error_alloc_write_req; goto error_alloc_write_req;
} }
} }
ret = AcmAllocNotifyRequest(acm); // Allocate and fill in the interrupt I/O request object. ret = AcmAllocNotifyRequest(acm); // Allocate and fill in the interrupt I/O request.
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s:%d AcmAllocNotifyRequest failed", __func__, __LINE__);
goto error_alloc_int_req; goto error_alloc_int_req;
} }
ret = AcmAllocReadRequests(acm); // Allocate and fill in the readReq I/O request object. ret = AcmAllocReadRequests(acm); // Allocate and fill in the readReq I/O request.
if (ret) { if (ret) {
HDF_LOGE("%s:%d AcmAllocReadRequests failed", __func__, __LINE__);
goto error_alloc_read_req; goto error_alloc_read_req;
} }
...@@ -645,57 +865,56 @@ static int32_t AcmInit(struct AcmDevice *acm) ...@@ -645,57 +865,56 @@ static int32_t AcmInit(struct AcmDevice *acm)
struct UsbSession *session = NULL; struct UsbSession *session = NULL;
if (acm->initFlag == true) { if (acm->initFlag == true) {
HDF_LOGE("%s:%d: initFlag is true", __func__, __LINE__);
return HDF_SUCCESS; return HDF_SUCCESS;
} }
ret = UsbInitHostSdk(NULL); // Initialize the Host DDK. // Initialize the USB Host DDK.
ret = UsbInitHostSdk(NULL);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: UsbInitHostSdk failed", __func__);
return HDF_ERR_IO; return HDF_ERR_IO;
} }
acm->session = session; acm->session = session;
// Obtain UsbInterface objects based on acm->interfaceIndex[i].
ret = AcmClaimInterfaces(acm); ret = AcmClaimInterfaces(acm);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: AcmClaimInterfaces failed", __func__);
goto error_claim_interfaces; goto error_claim_interfaces;
} }
// Open UsbInterface objects based on acm->iface[i].
ret = AcmOpenInterfaces(acm); ret = AcmOpenInterfaces(acm);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: AcmOpenInterfaces failed", __func__);
goto error_open_interfaces; goto error_open_interfaces;
} }
// Obtain the pointer to the pipe information.
ret = AcmGetPipes(acm); ret = AcmGetPipes(acm);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: AcmGetPipes failed", __func__);
goto error_get_pipes; goto error_get_pipes;
} }
ret = AcmAllocRequests(acm); ret = AcmAllocRequests(acm);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: AcmAllocRequests failed", __func__);
goto error_alloc_reqs; goto error_alloc_reqs;
} }
acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); // Convert to little-endian data.
acm->lineCoding.bCharFormat = CHARFORMAT; acm->lineCoding.bCharFormat = CHARFORMAT; // 8
acm->lineCoding.bParityType = USB_CDC_NO_PARITY; acm->lineCoding.bParityType = USB_CDC_NO_PARITY;
acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS; acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS;
acm->initFlag = true; acm->initFlag = true;
HDF_LOGD("%s:%d========OK", __func__, __LINE__);
return HDF_SUCCESS; return HDF_SUCCESS;
error_alloc_reqs: error_alloc_reqs:
AcmFreePipes(acm); AcmFreePipes(acm);
error_get_pipes: error_get_pipes:
// Disable all UsbInterface objects.
AcmCloseInterfaces(acm); AcmCloseInterfaces(acm);
error_open_interfaces: error_open_interfaces:
// Release all UsbInterface objects.
AcmReleaseInterfaces(acm); AcmReleaseInterfaces(acm);
error_claim_interfaces: error_claim_interfaces:
// Exit the USB DDK on the host. acm->session indicates the pointer pointing to the session context.
UsbExitHostSdk(acm->session); UsbExitHostSdk(acm->session);
acm->session = NULL; acm->session = NULL;
return ret; return ret;
...@@ -704,7 +923,6 @@ error_claim_interfaces: ...@@ -704,7 +923,6 @@ error_claim_interfaces:
static void AcmRelease(struct AcmDevice *acm) static void AcmRelease(struct AcmDevice *acm)
{ {
if (acm->initFlag == false) { if (acm->initFlag == false) {
HDF_LOGE("%s:%d: initFlag is false", __func__, __LINE__);
return; return;
} }
...@@ -712,9 +930,9 @@ static void AcmRelease(struct AcmDevice *acm) ...@@ -712,9 +930,9 @@ static void AcmRelease(struct AcmDevice *acm)
AcmFreePipes(acm); AcmFreePipes(acm);
AcmCloseInterfaces(acm); AcmCloseInterfaces(acm);
AcmReleaseInterfaces(acm); AcmReleaseInterfaces(acm);
// Exit the USB DDK on the host.
UsbExitHostSdk(acm->session); UsbExitHostSdk(acm->session);
acm->session = NULL; acm->session = NULL;
acm->initFlag = false; acm->initFlag = false;
} }
...@@ -724,15 +942,15 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) ...@@ -724,15 +942,15 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
struct AcmDevice *acm = NULL; struct AcmDevice *acm = NULL;
if (device == NULL) { if (device == NULL) {
HDF_LOGE("%s: device is null", __func__);
return HDF_ERR_INVALID_OBJECT; return HDF_ERR_INVALID_OBJECT;
} }
acm = (struct AcmDevice *)device->service; acm = (struct AcmDevice *)device->service;
// Initialize the mutex. &acm->readLock indicates the pointer pointing to the mutex.
OsalMutexInit(&acm->readLock); OsalMutexInit(&acm->readLock);
OsalMutexInit(&acm->writeLock); OsalMutexInit(&acm->writeLock);
HDF_LOGD("%s:%d busNum=%d,devAddr=%d", HDF_LOGD("%s:%d busNum=%d,devAddr=%d", __func__, __LINE__, acm->busNum, acm->devAddr);
__func__, __LINE__, acm->busNum, acm->devAddr);
// Allocate space for the USB serial port device information and assign a value.
ret = UsbSerialDeviceAlloc(acm); ret = UsbSerialDeviceAlloc(acm);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: Serial Device alloc failed", __func__); HDF_LOGE("%s: Serial Device alloc failed", __func__);
...@@ -740,9 +958,6 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) ...@@ -740,9 +958,6 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
acm->initFlag = false; acm->initFlag = false;
g_acmReleaseFlag = false; g_acmReleaseFlag = false;
HDF_LOGD("%s:%d init ok!", __func__, __LINE__);
return ret; return ret;
} }
...@@ -751,30 +966,29 @@ static void UsbSerialDriverRelease(struct HdfDeviceObject *device) ...@@ -751,30 +966,29 @@ static void UsbSerialDriverRelease(struct HdfDeviceObject *device)
struct AcmDevice *acm = NULL; struct AcmDevice *acm = NULL;
if (device == NULL) { if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return; return;
} }
acm = (struct AcmDevice *)device->service; acm = (struct AcmDevice *)device->service;
if (acm == NULL) { if (acm == NULL) {
HDF_LOGE("%s: acm is null", __func__);
return; return;
} }
g_acmReleaseFlag = true; g_acmReleaseFlag = true;
if (acm->initFlag == true) { if (acm->initFlag == true) {
HDF_LOGE("%s:%d AcmRelease", __func__, __LINE__);
AcmRelease(acm); AcmRelease(acm);
} }
// Release the USB serial port device information.
UsbSeriaDevicelFree(acm); UsbSeriaDevicelFree(acm);
// Release the mutex.
OsalMutexDestroy(&acm->writeLock); OsalMutexDestroy(&acm->writeLock);
OsalMutexDestroy(&acm->readLock); OsalMutexDestroy(&acm->readLock);
OsalMutexDestroy(&acm->lock); OsalMutexDestroy(&acm->lock);
OsalMemFree(acm); OsalMemFree(acm);
acm = NULL; acm = NULL;
HDF_LOGD("%s:%d exit", __func__, __LINE__);
} }
// Perform Bind, Init, and Release operations on the driver.
struct HdfDriverEntry g_usbSerialDriverEntry = { struct HdfDriverEntry g_usbSerialDriverEntry = {
.moduleVersion = 1, .moduleVersion = 1,
.moduleName = "usbhost_acm", // Driver module name, which must be the same as that configured in the .hcs file. .moduleName = "usbhost_acm", // Driver module name, which must be the same as that configured in the .hcs file.
...@@ -782,14 +996,12 @@ struct HdfDriverEntry g_usbSerialDriverEntry = { ...@@ -782,14 +996,12 @@ struct HdfDriverEntry g_usbSerialDriverEntry = {
.Init = UsbSerialDriverInit, .Init = UsbSerialDriverInit,
.Release = UsbSerialDriverRelease, .Release = UsbSerialDriverRelease,
}; };
HDF_INIT(g_usbSerialDriverEntry); HDF_INIT(g_usbSerialDriverEntry); // Driver entry.
``` ```
#### Developing Driver Using Host Raw APIs
### Developing Driver Using Host Raw APIs
``` ```cpp
root { root {
module = "usb_pnp_device"; module = "usb_pnp_device";
usb_pnp_config { usb_pnp_config {
...@@ -836,7 +1048,9 @@ root { ...@@ -836,7 +1048,9 @@ root {
} }
} }
} }
```
```cpp
#include "usb_serial_rawapi.h" #include "usb_serial_rawapi.h"
#include <unistd.h> #include <unistd.h>
#include "osal_mem.h" #include "osal_mem.h"
...@@ -846,7 +1060,7 @@ root { ...@@ -846,7 +1060,7 @@ root {
#include "hdf_log.h" #include "hdf_log.h"
#include "hdf_usb_pnp_manage.h" #include "hdf_usb_pnp_manage.h"
#define HDF_LOG_TAG USB_HOST_ACM_RAW_API #define HDF_LOG_TAG USB_HOST_ACM_RAW_API // Labels that can be queried in logs.
#define USB_CTRL_REQ_SIZE 64 #define USB_CTRL_REQ_SIZE 64
#define USB_IO_THREAD_STACK_SIZE 8192 #define USB_IO_THREAD_STACK_SIZE 8192
#define USB_RAW_IO_SLEEP_MS_TIME 100 #define USB_RAW_IO_SLEEP_MS_TIME 100
...@@ -858,51 +1072,46 @@ struct OsalMutex g_stopIoLock; ...@@ -858,51 +1072,46 @@ struct OsalMutex g_stopIoLock;
static bool g_rawAcmReleaseFlag = false; static bool g_rawAcmReleaseFlag = false;
...... ......
static int UsbGetConfigDescriptor(UsbRawHandle *devHandle, struct UsbRawConfigDescriptor **config) static int32_t UsbGetConfigDescriptor(UsbRawHandle *devHandle, struct UsbRawConfigDescriptor **config)
{ {
UsbRawDevice *dev = NULL; UsbRawDevice *dev = NULL;
int activeConfig; int32_t activeConfig;
int ret; int32_t ret;
if (devHandle == NULL) { if (devHandle == NULL) {
HDF_LOGE("%s:%d devHandle is NULL",
__func__, __LINE__);
return HDF_ERR_INVALID_PARAM; return HDF_ERR_INVALID_PARAM;
} }
// Obtain the configuration of the active device.
ret = UsbRawGetConfiguration(devHandle, &activeConfig); ret = UsbRawGetConfiguration(devHandle, &activeConfig);
if (ret) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s:%d UsbRawGetConfiguration failed, ret=%d",
__func__, __LINE__, ret);
return HDF_FAILURE; return HDF_FAILURE;
} }
HDF_LOGE("%s:%d activeConfig=%d", __func__, __LINE__, activeConfig);
// Obtain the device pointer based on the specified device handle.
dev = UsbRawGetDevice(devHandle); dev = UsbRawGetDevice(devHandle);
if (dev == NULL) { if (dev == NULL) {
HDF_LOGE("%s:%d UsbRawGetDevice failed",
__func__, __LINE__);
return HDF_FAILURE; return HDF_FAILURE;
} }
// Obtain the device configuration descriptor based on the specified device ID.
ret = UsbRawGetConfigDescriptor(dev, activeConfig, config); ret = UsbRawGetConfigDescriptor(dev, activeConfig, config);
if (ret) { if (ret != HDF_SUCCESS) {
HDF_LOGE("UsbRawGetConfigDescriptor failed, ret=%dn", ret); HDF_LOGE("UsbRawGetConfigDescriptor failed, ret=%d\n", ret);
return HDF_FAILURE;
} }
return ret;
return HDF_SUCCESS;
} }
... ...
static int UsbAllocWriteRequests(struct AcmDevice *acm) static int32_t UsbAllocWriteRequests(struct AcmDevice *acm)
{ {
int i; int32_t i;
for (i = 0; i < ACM_NW; i++) { for (i = 0; i < ACM_NW; i++) {
struct AcmWb *snd = &acm->wb[i]; struct AcmWb *snd = &acm->wb[i];
// Allocate a transfer request with the specified number of sync packet descriptors.
snd->request = UsbRawAllocRequest(acm->devHandle, 0, acm->dataOutEp->maxPacketSize); snd->request = UsbRawAllocRequest(acm->devHandle, 0, acm->dataOutEp->maxPacketSize);
snd->instance = acm; snd->instance = acm;
if (snd->request == NULL) { if (snd->request == NULL) {
HDF_LOGE("%s: UsbRawAllocRequest failed", __func__);
return HDF_ERR_MALLOC_FAIL; return HDF_ERR_MALLOC_FAIL;
} }
} }
...@@ -918,17 +1127,14 @@ static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) ...@@ -918,17 +1127,14 @@ static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device)
errno_t err; errno_t err;
if (device == NULL) { if (device == NULL) {
HDF_LOGE("%s: device is null", __func__);
return HDF_ERR_INVALID_OBJECT; return HDF_ERR_INVALID_OBJECT;
} }
acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm)); acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm));
if (acm == NULL) { if (acm == NULL) {
HDF_LOGE("%s: Alloc usb serial device failed", __func__);
return HDF_FAILURE; return HDF_FAILURE;
} }
if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) {
HDF_LOGE("%s:%d OsalMutexInit failed", __func__, __LINE__);
goto error; goto error;
} }
...@@ -940,19 +1146,15 @@ static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) ...@@ -940,19 +1146,15 @@ static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device)
err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES,
(const void*)info->interfaceNumber, info->interfaceLength); (const void*)info->interfaceNumber, info->interfaceLength);
if (err != EOK) { if (err != EOK) {
HDF_LOGE("%s:%d memcpy_s failed err=%d",
__func__, __LINE__, err);
goto lock_error; goto lock_error;
} }
} else { } else {
HDF_LOGE("%s:%d info is NULL!", __func__, __LINE__);
goto lock_error; goto lock_error;
} }
device->service = &(acm->service); device->service = &(acm->service);
device->service->Dispatch = UsbSerialDeviceDispatch; device->service->Dispatch = UsbSerialDeviceDispatch;
acm->device = device; acm->device = device;
HDF_LOGD("UsbSerialDriverBind=========================OK");
return HDF_SUCCESS; return HDF_SUCCESS;
lock_error: lock_error:
...@@ -965,16 +1167,16 @@ error: ...@@ -965,16 +1167,16 @@ error:
return HDF_FAILURE; return HDF_FAILURE;
} }
... ...
static int UsbAllocReadRequests(struct AcmDevice *acm) static int32_t UsbAllocReadRequests(struct AcmDevice *acm)
{ {
struct UsbRawFillRequestData reqData; struct UsbRawFillRequestData reqData;
int size = acm->dataInEp->maxPacketSize; int32_t size = acm->dataInEp->maxPacketSize;
int ret; int32_t ret;
for (int i = 0; i < ACM_NR; i++) { for (int32_t i = 0; i < ACM_NR; i++) {
// Allocate a transfer request with the specified number of sync packet descriptors.
acm->readReq[i] = UsbRawAllocRequest(acm->devHandle, 0, size); acm->readReq[i] = UsbRawAllocRequest(acm->devHandle, 0, size);
if (!acm->readReq[i]) { if (!acm->readReq[i]) {
HDF_LOGE("readReq request failed");
return HDF_ERR_MALLOC_FAIL; return HDF_ERR_MALLOC_FAIL;
} }
...@@ -985,10 +1187,9 @@ static int UsbAllocReadRequests(struct AcmDevice *acm) ...@@ -985,10 +1187,9 @@ static int UsbAllocReadRequests(struct AcmDevice *acm)
reqData.timeout = USB_CTRL_SET_TIMEOUT; reqData.timeout = USB_CTRL_SET_TIMEOUT;
reqData.length = size; reqData.length = size;
// Fill the required information in the bulk transfer request.
ret = UsbRawFillBulkRequest(acm->readReq[i], acm->devHandle, &reqData); ret = UsbRawFillBulkRequest(acm->readReq[i], acm->devHandle, &reqData);
if (ret) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: FillBulkRequest failed, ret=%d n",
__func__, ret);
return HDF_FAILURE; return HDF_FAILURE;
} }
} }
...@@ -996,15 +1197,15 @@ static int UsbAllocReadRequests(struct AcmDevice *acm) ...@@ -996,15 +1197,15 @@ static int UsbAllocReadRequests(struct AcmDevice *acm)
return HDF_SUCCESS; return HDF_SUCCESS;
} }
... ...
static int UsbAllocNotifyRequest(struct AcmDevice *acm) static int32_t UsbAllocNotifyRequest(struct AcmDevice *acm)
{ {
struct UsbRawFillRequestData fillRequestData; struct UsbRawFillRequestData fillRequestData;
int size = acm->notifyEp->maxPacketSize; int32_t size = acm->notifyEp->maxPacketSize;
int ret; int32_t ret;
// Allocate a transfer request with the specified number of sync packet descriptors.
acm->notifyReq = UsbRawAllocRequest(acm->devHandle, 0, size); acm->notifyReq = UsbRawAllocRequest(acm->devHandle, 0, size);
if (!acm->notifyReq) { if (!acm->notifyReq) {
HDF_LOGE("notifyReq request failed");
return HDF_ERR_MALLOC_FAIL; return HDF_ERR_MALLOC_FAIL;
} }
...@@ -1015,9 +1216,9 @@ static int UsbAllocNotifyRequest(struct AcmDevice *acm) ...@@ -1015,9 +1216,9 @@ static int UsbAllocNotifyRequest(struct AcmDevice *acm)
fillRequestData.userData = (void *)acm; fillRequestData.userData = (void *)acm;
fillRequestData.timeout = USB_CTRL_SET_TIMEOUT; fillRequestData.timeout = USB_CTRL_SET_TIMEOUT;
// Fill the required information in the interrupt transfer request.
ret = UsbRawFillInterruptRequest(acm->notifyReq, acm->devHandle, &fillRequestData); ret = UsbRawFillInterruptRequest(acm->notifyReq, acm->devHandle, &fillRequestData);
if (ret) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: FillInterruptRequest failed, ret=%d", __func__, ret);
return HDF_FAILURE; return HDF_FAILURE;
} }
...@@ -1031,62 +1232,55 @@ static int32_t UsbSerialInit(struct AcmDevice *acm) ...@@ -1031,62 +1232,55 @@ static int32_t UsbSerialInit(struct AcmDevice *acm)
int32_t ret; int32_t ret;
if (acm->initFlag == true) { if (acm->initFlag == true) {
HDF_LOGE("%s:%d: initFlag is true", __func__, __LINE__);
return HDF_SUCCESS; return HDF_SUCCESS;
} }
// Initialize the USB DDK in expert mode.
ret = UsbRawInit(NULL); ret = UsbRawInit(NULL);
if (ret) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s:%d UsbRawInit failed", __func__, __LINE__);
return HDF_ERR_IO; return HDF_ERR_IO;
} }
acm->session = session; acm->session = session;
// Open a USB device object.
devHandle = UsbRawOpenDevice(session, acm->busNum, acm->devAddr); devHandle = UsbRawOpenDevice(session, acm->busNum, acm->devAddr);
if (devHandle == NULL) { if (devHandle == NULL) {
HDF_LOGE("%s:%d UsbRawOpenDevice failed", __func__, __LINE__);
ret = HDF_FAILURE; ret = HDF_FAILURE;
goto err_open_device; goto err_open_device;
} }
acm->devHandle = devHandle; acm->devHandle = devHandle;
// Obtain the configuration of the active device, device pointer, and configuration descriptor.
ret = UsbGetConfigDescriptor(devHandle, &acm->config); ret = UsbGetConfigDescriptor(devHandle, &acm->config);
if (ret) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s:%d UsbGetConfigDescriptor failed", __func__, __LINE__);
ret = HDF_FAILURE; ret = HDF_FAILURE;
goto err_get_desc; goto err_get_desc;
} }
ret = UsbParseConfigDescriptor(acm, acm->config); ret = UsbParseConfigDescriptor(acm, acm->config);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s:%d UsbParseConfigDescriptor failed", __func__, __LINE__);
ret = HDF_FAILURE; ret = HDF_FAILURE;
goto err_parse_desc; goto err_parse_desc;
} }
ret = AcmWriteBufAlloc(acm); ret = AcmWriteBufAlloc(acm);
if (ret < 0) { if (ret < 0) {
HDF_LOGE("%s:%d AcmWriteBufAlloc failed", __func__, __LINE__);
ret = HDF_FAILURE; ret = HDF_FAILURE;
goto err_alloc_write_buf; goto err_alloc_write_buf;
} }
ret = UsbAllocWriteRequests(acm); ret = UsbAllocWriteRequests(acm);
if (ret < 0) { if (ret < 0) {
HDF_LOGE("%s:%d UsbAllocWriteRequests failed", __func__, __LINE__);
ret = HDF_FAILURE; ret = HDF_FAILURE;
goto err_alloc_write_reqs; goto err_alloc_write_reqs;
} }
ret = UsbAllocNotifyRequest(acm); ret = UsbAllocNotifyRequest(acm);
if (ret) { if (ret) {
HDF_LOGE("%s:%d UsbAllocNotifyRequests failed", __func__, __LINE__);
goto err_alloc_notify_req; goto err_alloc_notify_req;
} }
ret = UsbAllocReadRequests(acm); ret = UsbAllocReadRequests(acm);
if (ret) { if (ret) {
HDF_LOGE("%s:%d UsbAllocReadRequests failed", __func__, __LINE__);
goto err_alloc_read_reqs; goto err_alloc_read_reqs;
} }
ret = UsbStartIo(acm); ret = UsbStartIo(acm);
if (ret) { if (ret) {
HDF_LOGE("%s:%d UsbAllocReadRequests failed", __func__, __LINE__);
goto err_start_io; goto err_start_io;
} }
...@@ -1097,18 +1291,14 @@ static int32_t UsbSerialInit(struct AcmDevice *acm) ...@@ -1097,18 +1291,14 @@ static int32_t UsbSerialInit(struct AcmDevice *acm)
ret = UsbRawSubmitRequest(acm->notifyReq); ret = UsbRawSubmitRequest(acm->notifyReq);
if (ret) { if (ret) {
HDF_LOGE("%s:%d UsbRawSubmitRequest failed", __func__, __LINE__);
goto err_submit_req; goto err_submit_req;
} }
acm->initFlag = true; acm->initFlag = true;
HDF_LOGD("%s:%d=========================OK", __func__, __LINE__);
return HDF_SUCCESS; return HDF_SUCCESS;
err_submit_req: err_submit_req:
UsbStopIo(acm); UsbStopIo(acm); // Stop the I/O thread and release all resources.
err_start_io: err_start_io:
UsbFreeReadRequests(acm); UsbFreeReadRequests(acm);
err_alloc_read_reqs: err_alloc_read_reqs:
...@@ -1123,9 +1313,9 @@ err_parse_desc: ...@@ -1123,9 +1313,9 @@ err_parse_desc:
UsbRawFreeConfigDescriptor(acm->config); UsbRawFreeConfigDescriptor(acm->config);
acm->config = NULL; acm->config = NULL;
err_get_desc: err_get_desc:
(void)UsbRawCloseDevice(devHandle); (void)UsbRawCloseDevice(devHandle); // Close the USB device object.
err_open_device: err_open_device:
UsbRawExit(acm->session); UsbRawExit(acm->session); // Exit the expert mode of the USB DDK.
return ret; return ret;
} }
...@@ -1133,7 +1323,6 @@ err_open_device: ...@@ -1133,7 +1323,6 @@ err_open_device:
static void UsbSerialRelease(struct AcmDevice *acm) static void UsbSerialRelease(struct AcmDevice *acm)
{ {
if (acm->initFlag == false) { if (acm->initFlag == false) {
HDF_LOGE("%s:%d: initFlag is false", __func__, __LINE__);
return; return;
} }
...@@ -1151,6 +1340,7 @@ static void UsbSerialRelease(struct AcmDevice *acm) ...@@ -1151,6 +1340,7 @@ static void UsbSerialRelease(struct AcmDevice *acm)
UsbReleaseInterfaces(acm); UsbReleaseInterfaces(acm);
UsbRawFreeConfigDescriptor(acm->config); UsbRawFreeConfigDescriptor(acm->config);
acm->config = NULL; acm->config = NULL;
// Exit the expert mode of the USB DDK.
UsbRawExit(acm->session); UsbRawExit(acm->session);
acm->initFlag = false; acm->initFlag = false;
...@@ -1162,7 +1352,6 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) ...@@ -1162,7 +1352,6 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
int32_t ret; int32_t ret;
if (device == NULL) { if (device == NULL) {
HDF_LOGE("%s:%d device is null", __func__, __LINE__);
return HDF_ERR_INVALID_OBJECT; return HDF_ERR_INVALID_OBJECT;
} }
acm = (struct AcmDevice *)device->service; acm = (struct AcmDevice *)device->service;
...@@ -1176,9 +1365,6 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) ...@@ -1176,9 +1365,6 @@ static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device)
acm->initFlag = false; acm->initFlag = false;
g_rawAcmReleaseFlag = false; g_rawAcmReleaseFlag = false;
HDF_LOGD("%s:%d init ok!", __func__, __LINE__);
return ret; return ret;
} }
...@@ -1186,20 +1372,17 @@ static void UsbSerialDriverRelease(struct HdfDeviceObject *device) ...@@ -1186,20 +1372,17 @@ static void UsbSerialDriverRelease(struct HdfDeviceObject *device)
{ {
struct AcmDevice *acm = NULL; struct AcmDevice *acm = NULL;
if (device == NULL) { if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return; return;
} }
acm = (struct AcmDevice *)device->service; acm = (struct AcmDevice *)device->service;
if (acm == NULL) { if (acm == NULL) {
HDF_LOGE("%s: acm is null", __func__);
return; return;
} }
g_rawAcmReleaseFlag = true; g_rawAcmReleaseFlag = true;
if (acm->initFlag == true) { if (acm->initFlag == true) {
HDF_LOGE("%s:%d UsbSerialRelease", __func__, __LINE__);
UsbSerialRelease(acm); UsbSerialRelease(acm);
} }
UsbSeriaDevicelFree(acm); UsbSeriaDevicelFree(acm);
...@@ -1208,12 +1391,11 @@ static void UsbSerialDriverRelease(struct HdfDeviceObject *device) ...@@ -1208,12 +1391,11 @@ static void UsbSerialDriverRelease(struct HdfDeviceObject *device)
OsalMutexDestroy(&acm->lock); OsalMutexDestroy(&acm->lock);
OsalMemFree(acm); OsalMemFree(acm);
acm = NULL; acm = NULL;
HDF_LOGD("%s:%d exit", __func__, __LINE__);
} }
struct HdfDriverEntry g_usbSerialRawDriverEntry = { struct HdfDriverEntry g_usbSerialRawDriverEntry = {
.moduleVersion = 1, .moduleVersion = 1,
..moduleName = "usbhost_acm_rawapi", // Driver module name, which must be the same as that configured in the .hcs file. .moduleName = "usbhost_acm_rawapi", // Driver module name, which must be the same as that configured in the .hcs file.
.Bind = UsbSerialDriverBind, .Bind = UsbSerialDriverBind,
.Init = UsbSerialDriverInit, .Init = UsbSerialDriverInit,
.Release = UsbSerialDriverRelease, .Release = UsbSerialDriverRelease,
...@@ -1221,100 +1403,133 @@ struct HdfDriverEntry g_usbSerialRawDriverEntry = { ...@@ -1221,100 +1403,133 @@ struct HdfDriverEntry g_usbSerialRawDriverEntry = {
HDF_INIT(g_usbSerialRawDriverEntry); HDF_INIT(g_usbSerialRawDriverEntry);
``` ```
#### Developing Driver Using Device DDK APIs
### Developing Driver Using Device DDK APIs The 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.
The core code of the USB Abstract Control Model (ACM) device is available in **drivers\peripheral\usb\gadget\function\acm\cdcacm.c**. The following is an example. 1. Create a USB device.
```cpp
``` static int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm, struct DeviceResourceIface *iface)
1. Create a device. {
static int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev = NULL;
struct DeviceResourceIface *iface) struct UsbFnDescriptorData descData;
{ uint8_t useHcs;
struct UsbFnDevice *fnDev = NULL; ...
struct UsbFnDescriptorData descData; if (useHcs == 0) { // The descriptor is sourced from the code.
uint8_t useHcs; descData.type = USBFN_DESC_DATA_TYPE_DESC;
... descData.descriptor = &g_masterFuncDevice;
if (useHcs == 0) { } else {// The descriptor is sourced from the .hcs file.
descData.type = USBFN_DESC_DATA_TYPE_DESC; descData.type = USBFN_DESC_DATA_TYPE_PROP;
descData.descriptor = &g_masterFuncDevice; descData.property = device->property;
} else { }
descData.type = USBFN_DESC_DATA_TYPE_PROP; /* Create a device. */
descData.property = device->property; fnDev = (struct UsbFnDevice *)UsbFnDeviceCreate(acm->udcName, &descData);
} if (fnDev == NULL) {
/* Create a device. */ return HDF_FAILURE;
fnDev = (struct UsbFnDevice *)UsbFnDeviceCreate(acm->udcName, &descData); }
if (fnDev == NULL) {
HDF_LOGE("%s: create usb function device failed", __func__);
return HDF_FAILURE;
}
...
}
2. Obtain an interface and open the interface for pipe information.
static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface)
{
...
for (i = 0; i < fnIface->info.numPipes; i++) {
struct UsbFnPipeInfo pipeInfo;
/* Obtain pipe information. */
ret = UsbFnInterfaceGetPipeInfo(fnIface, i, &pipeInfo);
... ...
} }
return HDF_SUCCESS; ```
}
/* Obtain the interface and open the interface to obtain the handle. */ 2. Obtain an interface and open the interface to obtain the pipe information.
static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev)
{ ```cpp
... static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface)
for (i = 0; i < fnDev->numInterfaces; i++) { {
/* Obtain an interface.*/
fnIface = (struct UsbFnInterface *)UsbFnDeviceGetInterface(fnDev, i);
... ...
/* Open the interface. */ for (i = 0; i < fnIface->info.numPipes; i++) {
handle = UsbFnInterfaceOpen(fnIface); struct UsbFnPipeInfo pipeInfo;
/* Obtain pipe information. */
ret = UsbFnInterfaceGetPipeInfo(fnIface, i, &pipeInfo);
...
}
return HDF_SUCCESS;
}
/* Obtain an interface and open the interface to obtain the handle. */
static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev)
{
... ...
for (i = 0; i < fnDev->numInterfaces; i++) {
/* Obtain an interface.*/
fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
...
/* Open the interface. */
handle = UsbFnInterfaceOpen(fnIface);
...
}
return HDF_SUCCESS;
} }
return HDF_SUCCESS; ```
}
3. Receive events. 3. Receive events (EP0 control transfer).
static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int num)
{ ```cpp
... static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int32_t num)
{
...
req = UsbFnCtrlRequestAlloc(acm->ctrlIface.handle, req = UsbFnCtrlRequestAlloc(acm->ctrlIface.handle,
sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding)); sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
... ...
} }
static int32_t AcmDriverInit(struct HdfDeviceObject *device) static int32_t AcmDriverInit(struct HdfDeviceObject *device)
{ {
... ...
/* Start to receive events.*/ /* Start to receive events.*/
ret = UsbFnInterfaceStartRecvEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm); ret = UsbFnInterfaceStartRecvEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm);
... ...
} }
```
4. Perform USB communication (read and write). 4. Perform USB communication (read and write).
static int32_t AcmSendNotifyRequest(struct UsbAcmDevice *acm, uint8_t type,
uint16_t value, void *data, uint32_t length) ```cpp
{ static int32_t AcmSendNotifyRequest(struct UsbAcmDevice *acm, uint8_t type,
... uint16_t value, void *data, uint32_t length)
/* Send an asynchronous request.*/ {
ret = UsbFnRequestSubmitAsync(req); ...
... /* Send an asynchronous request.*/
} ret = UsbFnRequestSubmitAsync(req);
5. Close the interface, stop receiving events, and remove the device. ...
static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm)
{
int32_t ret;
/* Close the interface. */
(void)UsbFnInterfaceClose(acm->ctrlIface.handle);
(void)UsbFnInterfaceClose(acm->dataIface.handle);
/* Stop receiving events. */
(void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn);
/* Remove the device. */
ret = UsbFnDeviceRemove(acm->fnDev);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: remove usb function device failed", __func__);
} }
return ret; ```
}
``` 5. Close the interface, stop receiving events, and delete the device.
```cpp
static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm)
{
int32_t ret;
/* Close the interface. */
(void)UsbFnInterfaceClose(acm->ctrlIface.handle);
(void)UsbFnInterfaceClose(acm->dataIface.handle);
/* Stop receiving the Event EP0 control transfer. */
(void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn);
/* Delete the device. */
ret = UsbFnDeviceRemove(acm->fnDev);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: remove usb function device failed", __func__);
}
return ret;
}
```
## References
- Code repositories:
**[drivers\_hdf\_core](https://gitee.com/openharmony/drivers_hdf_core)**
[drivers\_peripheral](https://gitee.com/openharmony/drivers_peripheral)
[drivers\_interface](https://gitee.com/openharmony/drivers_interface)
- Code paths:
USB driver model adaptation for LiteOS: //drivers/hdf_core/adapter/khdf/liteos/model/usb
USB DDK driver loading: //drivers/hdf_core/framework/model/usb
USB HDI server implementation: //drivers/peripheral/usb/hdi_service
USB HDI external APIs: //out/{product_name}/gen/drivers/interface/usb/v1_0
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册