提交 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.
**Figure 1** USB host driver model ### Basic Concepts
![](figures/USB_host_driver_model.png "USB host driver model") - 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.
**Figure 2** USB device driver model - Endpoint
![](figures/USB_device_driver_model.png "USB device driver model") 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.
The USB driver model offers the following APIs: - Interface
- 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 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.
- 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. - 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.
### Available APIs ### Working Principles
The tables below describe the APIs provided by the USB host driver model. #### USB Host DDK
**Table 1** usb_ddk_interface.h 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.
| API| Description| **Figure 1** USB host driver model
| -------- | -------- |
| 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.|
| 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.|
| 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;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;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.|
| sint&nbsp;UsbCancelRequest(const&nbsp;struct&nbsp;UsbRequest<br>\*request); | Cancels an asynchronous request.|
| int&nbsp;UsbSubmitRequestSync(const&nbsp;struct&nbsp;UsbRequest<br>\*request); | Sends a synchronous request.|
**Table 2** usb_raw_api.h ![](figures/USB_host_driver_model.png "USB host driver model")
| API| Description| - 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.
| -------- | -------- |
| int&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.|
| int&nbsp;UsbRawCloseDevice(const&nbsp;UsbRawHandle<br>\*devHandle); | Closes a USB device.|
| 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.|
| 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.|
| 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.|
| 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.|
| void&nbsp;UsbRawFreeConfigDescriptor(const&nbsp;struct<br>UsbRawConfigDescriptor&nbsp;\*config); | Releases the memory space of a configuration descriptor.|
| int&nbsp;UsbRawGetConfiguration(const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;int&nbsp;\*config); | Obtains the configuration in use.|
| int&nbsp;UsbRawSetConfiguration(const&nbsp;UsbRawHandle<br>\*devHandle,&nbsp;int&nbsp;config); | Sets the configuration in use.|
| 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.|
| 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.|
| 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.|
| 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| - 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.
| -------- | -------- |
| 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.|
| const&nbsp;struct&nbsp;UsbFnDevice&nbsp;\*UsbFnGetDevice(const&nbsp;char<br>\*udcName); | Obtains a USB device.|
**Table 4** usbfn_interface.h - 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.
| API| Description| - 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.
| -------- | -------- |
| int&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.|
| UsbFnInterfaceHandle&nbsp;UsbFnOpenInterface(struct&nbsp;UsbFnInterface&nbsp;\*interface); | Opens an interface.|
| int&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.|
| 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.|
**Table 5** usbfn_request.h - 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.
| API| Description| - 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.
| -------- | -------- |
| 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.|
| int&nbsp;UsbFnFreeRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | Releases a request.|
| int&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.|
| int&nbsp;UsbFnCancelRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | Cancels a request.|
#### USB Device DDK
## How to Develop 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.
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. **Figure 2** USB device driver model
![](figures/USB_device_driver_model.png "USB device driver model")
### Developing Driver Using Host DDK 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.
1. Configure the driver mapping table. - 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.
2. Initialize the USB host DDK. - 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.
3. Obtain a **UsbInterface** object. - 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.
4. Open the **UsbInterface** object to obtain the **UsbInterfaceHandle** object. - 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.
5. Obtain pipe information of the specified **pipeIndex** based on the **UsbInterfaceHandle** object. - The Adapter module is provided by the composite device configuration driver and common function driver.
6. Allocate an I/O request for the **UsbInterfaceHandle** object. ## How to Develop
7. Fill in the I/O request based on the input parameters. 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.
8. Submit the I/O request in synchronous or asynchronous mode. ### 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.
### Developing Driver Using Host Raw APIs ### Available APIs
1. Configure the driver mapping table. 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).
2. Initialize the host raw data, open the USB device, obtain the descriptor, and then obtain interface and endpoint information based on the descriptor. **Table 1** APIs for USB host driver development (common mode)
3. Allocate a request and fill in the request based on the transfer type. | API| Description|
| -------- | -------- |
| int32_t&nbsp;UsbInitHostSdk(struct&nbsp;UsbSession&nbsp;\*\*session); | Initializes 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.|
| UsbInterfaceHandle&nbsp;\*UsbOpenInterface(const&nbsp;struct<br>UsbInterface&nbsp;\*interfaceObj); | Opens 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.|
| 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.|
| 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;UsbSubmitRequestSync(const&nbsp;struct&nbsp;UsbRequest<br>\*request); | Sends a synchronous request.|
4. Submit the I/O request in synchronous or asynchronous mode. 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** APIs for USB host driver development (expert mode)
### Developing Driver Using Device DDK APIs | API| Description|
| -------- | -------- |
| int32_t&nbsp;UsbRawInit(struct&nbsp;UsbSession&nbsp;\*\*session); | Initializes 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.|
| 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.|
| 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.|
| 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.|
| 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.|
| 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.|
| 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.|
| int32_t&nbsp;UsbRawSubmitRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request); | Submits a transfer request.|
| int32_t&nbsp;UsbRawCancelRequest(const&nbsp;struct&nbsp;UsbRawRequest<br>\*request); | Cancels a transfer request.|
| int32_t&nbsp;UsbRawHandleRequests(const&nbsp;UsbRawHandle<br>\*devHandle); | Handles a transfer request event.|
1. Construct a descriptor. 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).
2. Instantiate a USB device using the descriptor constructed. **Table 3** APIs for USB device management on the device side
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. | 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.|
| 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.|
4. Call **UsbFnInterfaceStartRecvEvent** to receive events such as Enable and Setup, and respond to the events in **UsbFnEventCallback**. 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).
5. Send and receive data in synchronous or asynchronous mode. **Table 4** APIs for USB interface definition on the device side
| API| Description|
| -------- | -------- |
| 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.|
| int32_t&nbsp;UsbFnStopRecvInterfaceEvent(struct<br>UsbFnInterface&nbsp;\*interface); | Stops receiving events.|
| UsbFnInterfaceHandle&nbsp;UsbFnOpenInterface(struct&nbsp;UsbFnInterface&nbsp;\*interface); | Opens an interface.|
| int32_t&nbsp;UsbFnCloseInterface(UsbFnInterfaceHandle&nbsp;handle); | Closes an interface.|
| int32_t&nbsp;UsbFnGetInterfacePipeInfo(struct&nbsp;UsbFnInterface<br>\*interface,&nbsp;uint8_t&nbsp;pipeId,&nbsp;struct&nbsp;UsbFnPipeInfo&nbsp;\*info); | Obtains pipe information.|
| 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.|
## Development Example 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).
The following examples help you better understand the development of the USB serial port driver. **Table 5** APIs for USB data request on the device side
| API| Description|
| -------- | -------- |
| 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.|
| int32_t&nbsp;UsbFnFreeRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | Releases a request.|
| int32_t&nbsp;UsbFnSubmitRequestAsync(struct&nbsp;UsbFnRequest<br>\*req); | Sends an asynchronous request.|
| int32_t&nbsp;UsbFnSubmitRequestSync(struct&nbsp;UsbFnRequest<br>\*req,&nbsp;uint32_t&nbsp;timeout); | Sends a synchronous request.|
| int32_t&nbsp;UsbFnCancelRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | Cancels a request.|
### Developing Driver Using Host DDK APIs
### 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.
root {
#### 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"; module = "usb_pnp_device";
usb_pnp_config { usb_pnp_config {
match_attr = "usb_pnp_match"; match_attr = "usb_pnp_match";
...@@ -217,8 +203,250 @@ root { ...@@ -217,8 +203,250 @@ root {
} }
} }
} }
} }
```
2. Initialize the USB host driver DDK.
```cpp
int32_t UsbInitHostSdk(struct UsbSession **session);
```
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);
```
4. Open the **UsbInterface** object to obtain the **UsbInterfaceHandle** object.
```cpp
UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);
```
5. Obtain pipe information of the specified **pipeIndex** based on the **UsbInterfaceHandle** object.
```cpp
int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);
```
6. Pre-allocate an I/O request for the **UsbInterfaceHandle** object.
```cpp
struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int32_t isoPackets, int32_t length);
```
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.
```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
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.
```cpp
int32_t UsbRawInit(struct UsbSession **session);
```
3. Open the USB device.
```cpp
UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);
```
4. Obtain the device descriptor, and obtain the interface and endpoint information based on the descriptor.
```cpp
int32_t UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);
```
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;
}
}
```
5. Send and receive data in synchronously or asynchronously.
```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
The following example helps you better understand the development of the USB serial port driver.
#### Developing Driver Using Host DDK APIs
```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
1. Create a device. static int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm, struct DeviceResourceIface *iface)
static int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm, {
struct DeviceResourceIface *iface)
{
struct UsbFnDevice *fnDev = NULL; struct UsbFnDevice *fnDev = NULL;
struct UsbFnDescriptorData descData; struct UsbFnDescriptorData descData;
uint8_t useHcs; uint8_t useHcs;
... ...
if (useHcs == 0) { if (useHcs == 0) { // The descriptor is sourced from the code.
descData.type = USBFN_DESC_DATA_TYPE_DESC; descData.type = USBFN_DESC_DATA_TYPE_DESC;
descData.descriptor = &g_masterFuncDevice; descData.descriptor = &g_masterFuncDevice;
} else { } else {// The descriptor is sourced from the .hcs file.
descData.type = USBFN_DESC_DATA_TYPE_PROP; descData.type = USBFN_DESC_DATA_TYPE_PROP;
descData.property = device->property; descData.property = device->property;
} }
/* Create a device. */ /* Create a device. */
fnDev = (struct UsbFnDevice *)UsbFnDeviceCreate(acm->udcName, &descData); fnDev = (struct UsbFnDevice *)UsbFnDeviceCreate(acm->udcName, &descData);
if (fnDev == NULL) { if (fnDev == NULL) {
HDF_LOGE("%s: create usb function device failed", __func__);
return HDF_FAILURE; return HDF_FAILURE;
} }
... ...
} }
2. Obtain an interface and open the interface for pipe information. ```
static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface)
{ 2. Obtain an interface and open the interface to obtain the pipe information.
```cpp
static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface)
{
... ...
for (i = 0; i < fnIface->info.numPipes; i++) { for (i = 0; i < fnIface->info.numPipes; i++) {
struct UsbFnPipeInfo pipeInfo; struct UsbFnPipeInfo pipeInfo;
/* Obtain pipe information. */ /* Obtain pipe information. */
ret = UsbFnInterfaceGetPipeInfo(fnIface, i, &pipeInfo); ret = UsbFnInterfaceGetPipeInfo(fnIface, i, &pipeInfo);
... ...
} }
return HDF_SUCCESS; return HDF_SUCCESS;
} }
/* Obtain the interface and open the interface to obtain the handle. */ /* Obtain an interface and open the interface to obtain the handle. */
static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev) static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev)
{ {
... ...
for (i = 0; i < fnDev->numInterfaces; i++) { for (i = 0; i < fnDev->numInterfaces; i++) {
/* Obtain an interface.*/ /* Obtain an interface.*/
fnIface = (struct UsbFnInterface *)UsbFnDeviceGetInterface(fnDev, i); fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
... ...
/* Open the interface. */ /* Open the interface. */
handle = UsbFnInterfaceOpen(fnIface); handle = UsbFnInterfaceOpen(fnIface);
... ...
} }
return HDF_SUCCESS; return HDF_SUCCESS;
} }
3. Receive events. ```
static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int num)
{ 3. Receive events (EP0 control transfer).
```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,
```cpp
static int32_t AcmSendNotifyRequest(struct UsbAcmDevice *acm, uint8_t type,
uint16_t value, void *data, uint32_t length) uint16_t value, void *data, uint32_t length)
{ {
... ...
/* Send an asynchronous request.*/ /* Send an asynchronous request.*/
ret = UsbFnRequestSubmitAsync(req); ret = UsbFnRequestSubmitAsync(req);
... ...
} }
5. Close the interface, stop receiving events, and remove the device. ```
static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm)
{ 5. Close the interface, stop receiving events, and delete the device.
int32_t ret;
/* Close the interface. */ ```cpp
static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm)
{
int32_t ret;
/* Close the interface. */
(void)UsbFnInterfaceClose(acm->ctrlIface.handle); (void)UsbFnInterfaceClose(acm->ctrlIface.handle);
(void)UsbFnInterfaceClose(acm->dataIface.handle); (void)UsbFnInterfaceClose(acm->dataIface.handle);
/* Stop receiving events. */ /* Stop receiving the Event EP0 control transfer. */
(void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn); (void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn);
/* Remove the device. */ /* Delete the device. */
ret = UsbFnDeviceRemove(acm->fnDev); ret = UsbFnDeviceRemove(acm->fnDev);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: remove usb function device failed", __func__); HDF_LOGE("%s: remove usb function device failed", __func__);
} }
return ret; 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.
先完成此消息的编辑!
想要评论请 注册