From 69a0b9d736ecc70b2fd4d7f9a6d437f3beeb38e7 Mon Sep 17 00:00:00 2001 From: Annie_wang Date: Mon, 15 Aug 2022 11:59:15 +0800 Subject: [PATCH] update docs Signed-off-by: Annie_wang --- .../security/accesstoken-overview.md | 26 +- .../driver/driver-peripherals-camera-des.md | 4 +- .../driver/driver-platform-i3c-des.md | 532 ++++------- .../driver/driver-platform-uart-develop.md | 871 ++++++++---------- 4 files changed, 562 insertions(+), 871 deletions(-) diff --git a/en/application-dev/security/accesstoken-overview.md b/en/application-dev/security/accesstoken-overview.md index 5c530a1ce9..b58ea623fd 100644 --- a/en/application-dev/security/accesstoken-overview.md +++ b/en/application-dev/security/accesstoken-overview.md @@ -12,9 +12,9 @@ App permissions are used to protect the following objects: Without the required permissions, an app cannot access or perform operations on the target object. Permissions must be clearly defined for apps. With well-defined app permissions, the system can standardize the behavior of apps and protect user privacy. Before an app accesses the target object, the target object verifies the app's permissions and denies the access if the app does not have required permissions. -Currently, ATM performs app permission verification based on the token identity (Token ID). A token ID identifies an app. The ATM manages app permissions based on the app's token ID. +Currently, ATM verifies app permissions based on the token identity (Token ID). A token ID identifies an app. The ATM manages app permissions based on the app's token ID. -## How to Develop +## Permission Workflow Determine the permissions required for an app to access data or perform an operation. Declare the required permissions in the app installation package. @@ -22,13 +22,13 @@ Determine whether the required permissions need to be authorized by users. If ye After the user grants permissions to the app, the app can access the data or perform the operation. -The figure below shows the process. +The figure below shows the permission workflow. ![](figures/figure1.png) ## When to Use -### Scenarios +### Example Scenarios The following describes two common scenarios. @@ -62,7 +62,7 @@ Observe the following principles for permission management: To protect user privacy, ATM defines different permission levels based on the sensitivity of the data involved or the security threat of the ability. -### App APL +### App APLs The ability privilege level (APL) defines the priority of the app permission requested. Apps of different APLs can apply for permissions of different levels. @@ -76,9 +76,9 @@ The table below describes the APLs. By default, apps are of the normal APL. -For the app of the system_basic or system_core APL, declare the app APL level in the **apl** field in the app's profile, and use the profile signing tool to generate a certificate when developing the app installation package. For details about the signing process, see [Hapsigner Guide](hapsigntool-guidelines.md). +For the app of the system_basic or system_core APL, declare the app APL in the **apl** field in the app's profile, and use the profile signing tool to generate a certificate when developing the app installation package. For details about the signing process, see [Hapsigner Guide](hapsigntool-guidelines.md). -### Permission Levels +### Levels of Permissions The permissions open to apps vary with the permission level. The permission levels include the following in ascending order of seniority. @@ -121,11 +121,11 @@ If the permission required by an app has higher level than the app's APL, you ca In addition to the preceding [authorization processes](#authorization-processes), you must declare the ACL. -In other words, in addition to declaring the required permissions in the **config.json** file, you must declare the high-level permissions in the app's [profile](accesstoken-guidelines.md#declaring-the-acl). The subsequent steps of authorization are the same. +In other words, in addition to declaring the required permissions in the **config.json** file, you must [declare the ACL](accesstoken-guidelines.md#declaring-the-acl) in the app's profile. The subsequent steps of authorization are the same. -**NOTE** +**NOTICE** -Declare the target ACL in the **acl** field of the app's profile in the app installation package, and generate a certificate using the profile signing tool. For details about the signing process, see [Hapsigner Guide](hapsigntool-guidelines.md). +Declare the target ACL in the **acls** field of the app's profile in the app installation package, and generate a certificate using the profile signing tool. For details about the signing process, see [Hapsigner Guide](hapsigntool-guidelines.md). ## Permission Authorization Modes @@ -149,9 +149,7 @@ Permissions can be classified into the following types based on the authorizatio ### Authorization Processes -The process for an app obtaining the required permissions varies - -depending on the permission authorization mode. +The process for an app obtaining the required permissions varies depending on the permission authorization mode. - For a system_grant permission, you need to [declare the permission](accesstoken-guidelines.md) in the **config.json** file. The permission will be pre-granted when the app is installed. @@ -165,7 +163,7 @@ The procedure is as follows: 2. Associate the object that requires the permissions in the app with the target permissions. In this way, the user knows the operations to be granted with the specified permissions. -3. Check whether the user has granted the required permissions to the app when the app is running. If yes, the app can access the data or perform the operation. If the user has not granted the permissions to the app, display a dialog box requesting the user authorization when the app attempts to access the data or perform the operation. +3. Check whether the user has granted the required permissions to the app when the app is running. If yes, the app can access the data or perform the operation. If the user has not granted the permissions to the app, display a dialog box requesting the user authorization when the app attempts to access the data. 4. Check the user authorization result. Allow the next step only after the user has granted the permissions to the app. diff --git a/en/device-dev/driver/driver-peripherals-camera-des.md b/en/device-dev/driver/driver-peripherals-camera-des.md index 9105ff4a83..d161e03295 100644 --- a/en/device-dev/driver/driver-peripherals-camera-des.md +++ b/en/device-dev/driver/driver-peripherals-camera-des.md @@ -52,7 +52,7 @@ The camera module encapsulates camera operations in camera preview, photographin | API | Description | | ------------------------------------------------------------ | ---------------------------- | | CamRetCode GetStreamOperator(
const OHOS::sptr &callback,
OHOS::sptr &streamOperator) | Obtains the stream controller. | - | CamRetCode UpdateSettings(const std::shared_ptr &settingss) | Updates device control parameters. | + | CamRetCode UpdateSettings(const std::shared_ptr &settings) | Updates device control parameters. | | CamRetCode SetResultMode(const ResultCallbackMode &mode) | Sets the result callback mode and function.| | CamRetCode GetEnabledResults(std::vector &results) | Obtains the enabled ResultMeta. | | CamRetCode EnableResult(const std::vector &results) | Enables specific ResultMeta. | @@ -730,7 +730,7 @@ There is a camera demo in the **/drivers/peripheral/camera/hal/init** directory. "-o | --offline stream offline test\n" "-c | --capture capture one picture\n" "-w | --set WB Set white balance Cloudy\n" - "-v | --video capture Viedeo of 10s\n" + "-v | --video capture Video of 10s\n" "-a | --Set AE Set Auto exposure\n" "-f | --Set Flashlight Set flashlight ON 5s OFF\n" "-q | --quit stop preview and quit this app\n"); diff --git a/en/device-dev/driver/driver-platform-i3c-des.md b/en/device-dev/driver/driver-platform-i3c-des.md index 555bc6eaeb..1108e71375 100644 --- a/en/device-dev/driver/driver-platform-i3c-des.md +++ b/en/device-dev/driver/driver-platform-i3c-des.md @@ -1,140 +1,109 @@ -# I3C +# I3C +## Introduction -## Overview +### Function -The Improved Inter-Integrated Circuit (I3C) is a simple and cost-efficient bidirectional 2-wire synchronous serial bus protocol developed by the Mobile Industry Processor Interface (MIPI) Alliance. +Improved Inter-Integrated Circuit (I3C) is a simple and cost-efficient two-wire bidirectional synchronous serial bus protocol developed by the Mobile Industry Processor Interface (MIPI) Alliance. -I3C is backward compatible with legacy Inter-Integrated Circuit (I2C). Moreover, it provides the in-band interrupt (IBI) function and supports hot-join of I3C devices. This eliminates the need for adding an extra interrupt line to implement interrupts in I2C. +I3C is a two-wire bidirectional serial bus, optimized for multiple sensor target devices and controlled by only one I3C controller at a time. It is backward compatible with Inter-Integrated circuit (I2C) target devices, but features higher speed and lower power consumption. Moreover, I3C supports in-band interrupts (IBIs), hot-joins of target devices, and controller switchover. The IBIs over the serial bus eliminates the need for an extra interrupt line to complete interrupts in I2C. I2C devices, I3C target devices, and the I3C secondary controller can co-exist on the same I3C bus. -The I2C device, I3C slave device, and I3C secondary master device can coexist on the I3C bus. +The I3C driver APIs provide a set of common functions for I3C transfer, including: +- Opening and closing an I3C controller +- Obtaining and setting I3C controller parameters +- Performing custom I3C message transfer by using a message array +- Requesting and releasing an IBI -The I3C APIs provide a set of common functions for I3C transfer, including: +### Basic Concepts -- Opening and closing an I3C controller -- Obtaining and setting I3C controller parameters -- Performing custom I3C message transfer by using a message array -- Requesting and releasing an IBI +- IBI + + When there is no start signal on the serial clock (SCL) line, the I3C target device can pull down the serial data (SDA) line to make the controller send an SCL start signal, which initiates an IBI request. If multiple target devices send interrupt requests at the same time, the I3C controller arbitrates the requests based on the target device addresses. The request with a lower address is responded first. + +- Dynamic Address Assignment (DAA) -[Figure 1](#fig1) shows the I3C physical connection. -**Figure 1** I3C physical connection + The I3C controller can dynamically allocate addresses to target devices to avoid address conflicts. Before addresses are allocated, each I3C device connected to a I3C bus must be uniquely identified in either of the following ways: + + - The device has an I2C compliant static address that can be used by the host. + - The device has a 48-bit temporary ID. + + The host must use a 48-bit temporary ID unless the device has a static IP address. + +- Common Command Code (CCC) + + All I3C devices support CCC. The CCC can be sent to a specific I3C target device or all I3C target devices. + +- Bus Characteristic Register (BCR) + + Each I3C device connected to an I3C bus has a read-only BCR, which describes the I3C compliant device's role and capabilities for use in DAA and CCC. + +- Device Characteristic Register (DCR) + + Each I3C device connected to an I3C bus has a read-only DCR, which describes the I3C compliant device type (such as accelerometers, gyroscope, and others) for use in DAA and DCC. + +### Working Principles + +In the Hardware Driver Foundation (HDF), the I3C module uses the unified service mode for API adaptation. In this mode, a service is used as the I3C manager to handle external access requests in a unified manner. The unified service mode applies when the system has multiple device objects of the same type, for example, when there are more than 10 I3C controllers. If the independent service mode is used in this case, more device nodes need to be configured and more memory resources will be consumed. + +Multiple devices, such as I2C target device, I3C target device, and I3C secondary controller, can be connected to an I3C bus. However, the I3C bus must have only one controller. + +**Figure 1** I3C physical connection ![](figures/I3C_physical_connection.png "I3C_physical_connection") -## Available APIs +### Constraints + +Currently, the I3C module supports only the kernels (LiteOS) of mini and small systems. + +## Usage Guidelines + +### When to Use + +I3C can connect to one or more I3C or I2C target devices. It is used to: +- Communicate with sensors, such as gyroscopes, barometers, and image sensors that support the I3C protocol. +- Communicate with devices with other ports (such as UART serial ports) through software or hardware protocols. + +### Available APIs **Table 1** I3C driver APIs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Category

-

API

-

Description

-

I3C controller management

-

I3cOpen

-
Opens an I3C controller.

-

I3cClose

-

Closes an I3C controller.

-

I3C transfer

-

I3cTransfer

-

Customizes an I3C transfer.

-

I3C controller configuration

-

I3cSetConfig

-
Sets an I3C controller.

-

I3cGetConfig

-

Obtains the I3C controller configuration.

-

I3C IBI

-

I3cRequestIbi

-
Requests an IBI.

-

I3cFreeIbi

-

Releases an IBI.

-
- - - ->![](../public_sys-resources/icon-note.gif) **NOTE** -> ->All functions described in this document can be called only in the kernel space. - -## Usage Guidelines - -### How to Use - -[Figure 2](#fig2) shows how I3C works. - -**Figure 2** How I3C works + +| API | Description | +| ------------- | ----------------- | +| I3cOpen | Opens an I3C controller. | +| I3cClose | Closes an I3C controller. | +| I3cTransfer | Performs custom transfer. | +| I3cSetConfig | Sets the I3C controller. | +| I3cGetConfig | Obtains the I3C controller configuration. | +| I3cRequestIbi | Requests an IBI. | +| I3cFreeIbi | Releases an IBI. | + +>![](../public_sys-resources/icon-note.gif) **NOTE**
+>All APIs described in this document can be called only in kernel mode. + +### How to Develop + +The figure below illustrates the use of I3C driver APIs. + +**Figure 2** Process of using I3C driver APIs ![](figures/I3C_usage_flowchart.png "I3C_usage_flowchart") -### Opening an I3C Controller +#### Opening an I3C Controller -Before I3C communication, call **I3cOpen** to open an I3C controller. +Before I3C communication, call **I3cOpen()** to open an I3C controller. ```c DevHandle I3cOpen(int16_t number); ``` **Table 2** Description of I3cOpen - - - - - - - - - - - - - - - - - - - -

Parameter

-

Description

-

number

-

I3C controller ID.

-

Return Value

-

Description

-

NULL

-

Failed to open the I3C controller.

-

Controller handle

-

Handle of the I3C controller opened.

-
- -The following example opens I3C controller 1 of the eight I3C controllers (numbered from 0 to 7) in the system. +| Name | Description | +| ---------- | ------------------- | +| number | I3C controller number. | +| **Return Value**| **Description** | +| NULL | The operation failed. | +| Controller handle| The operation is successful. The handle of the I3C controller opened is returned. | + +Example: Open I3C controller 1 of the eight I3C controllers numbered from 0 to 7 in the system. ```c DevHandle i3cHandle = NULL; /* I3C controller handle. / @@ -147,7 +116,7 @@ if (i3cHandle == NULL) { } ``` -### Performing I3C Communication +#### Performing I3C Communication Call **I3cTransfer()** to transfer messages. ```c @@ -156,53 +125,18 @@ int32_t I3cTransfer(DevHandle handle, struct I3cMsg *msgs, int16_t count, enum T **Table 3** Description of I3cTransfer - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Parameter

-

Description

-

handle

-

I3C controller handle.

-

msgs

-

Pointer to the message structure array of the data to be transmitted.

-

count

-

Length of the message array.

-

mode

-

Transmission mode, where the value 0 indicates the I2C mode, 1 indicates the I3C mode, and 2 indicates transmission of the Common Command Code (CCC). -

Return Value

-

Description

-

Positive integer

-

Number of message structures successfully transferred.

-

Negative number

-

The operation failed.

-
- -The I3C messages are of the I3cMsg type. Each message structure indicates a read or write operation. A message array is used to perform multiple read or write operations. + +| Name | Description | +| ---------- | -------------------------------------------- | +| handle | I3C controller handle. | +| msgs | Pointer to the message array of the data to transfer. | +| count | Length of the message array. | +| mode | Transmission mode. The value **0** indicates I2C mode, **1** indicates I3C mode, and **2** indicates CCC transmission. | +| **Return Value**| **Description** | +| Positive integer | The operation is successful. The number of message structures that are successfully transmitted is returned. | +| Negative value | The operation failed. | + +The I3C messages are of the I3cMsg type. Each message structure indicates a read or write operation. A message array can be used to perform multiple read or write operations. ```c int32_t ret; @@ -225,13 +159,14 @@ if (ret != 2) { } ``` ->![](../public_sys-resources/icon-caution.gif) **Caution** -> +>![](./public_sys-resources/icon-caution.gif) **Caution**
>- The device address in the **I3cMsg** structure does not contain the read/write flag bit. The read/write information is passed by the read/write control bit in the member variable **flags**. >- The **I3cTransfer()** function does not limit the number of message structures or the length of data in each message structure. The I3C controller determines these two limits. >- Using **I3cTransfer()** may cause the system to sleep. Do not call it in the interrupt context. -### Obtaining the I3C Controller Configuration +#### Obtaining the I3C Controller Configuration + +Call **I3cGetConfig()** to obtain the configuration of an I3C controller. ```c int32_t I3cGetConfig(DevHandle handle, struct I3cConfig *config); @@ -239,43 +174,30 @@ int32_t I3cGetConfig(DevHandle handle, struct I3cConfig *config); **Table 4** Description of I3cGetConfig - - - - - - - - - - - - - - - - - - - - - - -

Parameter

-

Description

-

handle

-

I3C controller handle.

-

config

-

Pointer to the I3C controller configuration.

-

Return Value

-

Description

-

0

-

The operation is successful.

-

Negative number

-

Failed to obtain the I3C controller configuration.

-
- -### Configuring an I3C Controller + +| Name | Description | +| ---------- | -------------- | +| handle | I3C controller handle. | +| config | Pointer to the I3C controller configuration. | +| **Return Value**| **Description**| +| 0 | The operation is successful. | +| Negative value | The operation failed. | + +The following is an example of obtaining the I3C controller configuration: + +```c +struct I3cConfig config; + +ret = I3cGetConfig(i3cHandle, &config); +if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: Get config fail!", __func__); + return HDF_FAILURE; +} +``` + +#### Setting an I3C Controller + +Call **I3cSetConfig()** to set an I3C controller. ```c int32_t I3cSetConfig(DevHandle handle, struct I3cConfig *config); @@ -283,43 +205,32 @@ int32_t I3cSetConfig(DevHandle handle, struct I3cConfig *config); **Table 5** Description of I3cSetConfig - - - - - - - - - - - - - - - - - - - - - - -

Parameter

-

Description

-

handle

-

I3C controller handle.

-

config

-

Pointer to the I3C controller configuration.

-

Return Value

-

Description

-

0

-

The operation is successful.

-

Negative number

-

Failed to configure the I3C controller.

-
- -### Requesting an IBI + +| Name | Description | +| ---------- | -------------- | +| handle | I3C controller handle. | +| config | Pointer to the I3C controller configuration. | +| **Return Value**| **Description**| +| 0 | The operation is successful. | +| Negative value | The operation failed. | + +The following is an example of setting an I3C controller: + +```c +struct I3cConfig config; + +config->busMode = I3C_BUS_HDR_MODE; +config->curMaster = NULL; +ret = I3cSetConfig(i3cHandle, &config); +if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: Set config fail!", __func__); + return HDF_FAILURE; +} +``` + +#### Requesting an IBI + +Call **I3cRequestIbi()** to request an IBI. ```c int32_t I3cRequestIbi(DevHandle handle, uint16_t addr, I3cIbiFunc func, uint32_t payload); @@ -327,51 +238,18 @@ int32_t I3cRequestIbi(DevHandle handle, uint16_t addr, I3cIbiFunc func, uint32_t **Table 6** Description of I3cRequestIbi - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Parameter

-

Description

-

handle

-

I3C controller handle.

-

addr

-

I3C device address.

-

func

-

Callback used to return the IBI.

-

payload

-

IBI payload.

-

Return Value

-

Description

-

0

-

The operation is successful.

-

Negative number

-

Failed to request the IBI.

-
+ +| Name | Description | +| ---------- | -------------- | +| handle | I3C controller handle. | +| addr | I3C device address. | +| func | Callback used to return the IBI. | +| payload | IBI payload. | +| **Return Value**| **Description**| +| 0 | The operation is successful. | +| Negative value | The operation failed. | + +The following is an example: ```c static int32_t TestI3cIbiFunc(DevHandle handle, uint16_t addr, struct I3cIbiData data) @@ -388,7 +266,7 @@ int32_t I3cTestRequestIbi(void) DevHandle i3cHandle = NULL; int32_t ret; - /* Open an I3C controller. */ + /* Open the I3C controller. */ i3cHandle = I3cOpen(1); if (i3cHandle == NULL) { HDF_LOGE("I3cOpen: failed\n"); @@ -396,7 +274,7 @@ int32_t I3cTestRequestIbi(void) } ret = I3cRequestIbi(i3cHandle, 0x3F, TestI3cIbiFunc, 16); if (ret != 0) { - HDF_LOGE("%s: Requset IBI failed!", __func__); + HDF_LOGE("%s: Request IBI failed!", __func__); return -1; } @@ -407,7 +285,9 @@ int32_t I3cTestRequestIbi(void) } ``` -### Releasing an IBI +#### Releasing an IBI + +Call **I3cFreeIbi()** to release an IBI. ```c int32_t I3cFreeIbi(DevHandle handle, uint16_t addr); @@ -415,47 +295,22 @@ int32_t I3cFreeIbi(DevHandle handle, uint16_t addr); **Table 7** Description of I3cFreeIbi - - - - - - - - - - - - - - - - - - - - - - -

Parameter

-

Description

-

handle

-

I3C controller handle.

-

addr

-

I3C device address.

-

Return Value

-

Description

-

0

-

The operation is successful.

-

Negative number

-

Failed to release the IBI.

-
+ +| Name | Description | +| ---------- | -------------- | +| handle | I3C controller handle. | +| addr | I3C device address. | +| **Return Value**| **Description**| +| 0 | The operation is successful. | +| Negative value | The operation failed. | + +The following is an example: ```c I3cFreeIbi(i3cHandle, 0x3F); /* Release an IBI. */ ``` -### Closing an I3C controller +#### Closing an I3C Controller Call **I3cClose()** to close the I3C controller after the communication is complete. ```c @@ -464,28 +319,18 @@ void I3cClose(DevHandle handle); **Table 8** Description of I3cClose - - - - - - - - - -

Parameter

-

Description

-

handle

-

I3C controller handle.

-
+| Name | Description | +| ---------- | -------------- | +| handle | I3C controller handle. | +The following is an example: ```c -I3cClose(i3cHandle); /* Close an I3C controller. */ +I3cClose(i3cHandle); /* Close the I3C controller. */ ``` -## Example +## Development Example This following example shows how to use I3C APIs to manage an I3C device on a Hi3516D V300 development board. @@ -503,10 +348,9 @@ The sample code is as follows: ```c #include "i3c_if.h" /* Header file for I3C standard APIs */ -#include "i3c_ccc.h" /* Header file for I3C CCC */ #include "hdf_log.h" /* Header file for log APIs */ ##include "osal_io.h" /* Header file for I/O read and write APIs */ -##include "osal_time.h" /* Header file for delay and sleep APIs */ +#include "osal_time.h" /* Header file for delay and sleep APIs */ /* Define a device structure to hold information. */ struct TestI3cDevice { @@ -516,7 +360,7 @@ struct TestI3cDevice { DevHandle i3cHandle; /* I3C controller handle */ }; -/* Use I3cTransfer to encapsulate a register read/write helper function. Use flag to indicate a read or write operation. */ +/* Use I3cTransfer() to encapsulate a register read/write helper function. Use flag to indicate a read or write operation. */ static int TestI3cReadWrite(struct TestI3cDevice *testDevice, unsigned int regAddr, unsigned char *regData, unsigned int dataLen, uint8_t flag) { @@ -539,7 +383,7 @@ static int TestI3cReadWrite(struct TestI3cDevice *testDevice, unsigned int regAd msgs[0].buf = regBuf; msgs[1].addr = testDevice->addr; - msgs[1].flags = (flag == 1) ? I3C_FLAG_READ: 0; /* Add a read flag bit to read data. */ + msgs[1].flags = (flag == 1) ? I3C_FLAG_READ : 0; /* Add the read flag. */ msgs[1].len = dataLen; msgs[1].buf = regData; diff --git a/en/device-dev/driver/driver-platform-uart-develop.md b/en/device-dev/driver/driver-platform-uart-develop.md index bc6d827363..565e815cb5 100644 --- a/en/device-dev/driver/driver-platform-uart-develop.md +++ b/en/device-dev/driver/driver-platform-uart-develop.md @@ -1,16 +1,20 @@ -# UART +# UART -## Overview -In the Hardware Driver Foundation \(HDF\), the Universal Asynchronous Receiver/Transmitter \(UART\) uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to handle external access requests. After receiving an access request from an API, the device manager extracts the parameters in the request to call the internal method of the target device. In the independent service mode, the service management capabilities of the HDF Device Manager can be directly used. However, you need to configure a device node for each device, which increases the memory usage. +## Overview -**Figure 1** Independent service mode -![](figures/independent-service-mode.png "independent-service-mode-14") +In the Hardware Driver Foundation (HDF), the Universal Asynchronous Receiver/Transmitter (UART) uses the independent service mode for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device, which increases memory usage. -## Available APIs + **Figure 1** Independent service mode -UartHostMethod + ![image](figures/independent-service-mode.png) + +## Available APIs + +**UartHostMethod**: + + ``` struct UartHostMethod { int32_t (*Init)(struct UartHost *host); @@ -26,525 +30,370 @@ struct UartHostMethod { }; ``` -**Table 1** Callbacks for the members in the UartHostMethod structure - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Callback

-

Input Parameter

-

Output Parameter

-

Return Value

-

Description

-

Init

-

host: structure pointer to the UART controller at the core layer.

-

-

HDF_STATUS

-

Initializes the UART device.

-

Deinit

-

host: structure pointer to the UART controller at the core layer.

-

-

HDF_STATUS

-

Deinitializes the UART device.

-

Read

-

host: structure pointer to the UART controller at the core layer.

-

size: data size, which is of the uint32_t type.

-

data: uint8_t pointer to the output data.

-

HDF_STATUS

-

Receives data.

-

Write

-

host: structure pointer to the UART controller at the core layer.

-

data: pointer to the input data, which is of the uint8_t type.

-

size: data size, which is of the uint32_t type.

-

-

HDF_STATUS

-

Sends data.

-

SetBaud

-

host: structure pointer to the UART controller at the core layer.

-

baudRate: pointer to the input baud rate, which is of the uint32_t type.

-

-

HDF_STATUS

-

Sets the baud rate.

-

GetBaud

-

host: structure pointer to the UART controller at the core layer.

-

baudRate: uint32_t pointer to the output baud rate.

-

HDF_STATUS

-

Obtains the current baud rate.

-

GetAttribute

-

host: structure pointer to the UART controller at the core layer.

-

attribute: structure pointer to the output attributes. For details, see UartAttribute in uart_if.h.

-

HDF_STATUS

-

Obtains UART attributes.

-

SetAttribute

-

host: structure pointer to the UART controller at the core layer.

-

attribute: structure pointer to the input attributes.

-

-

HDF_STATUS

-

Sets UART attributes.

-

SetTransMode

-

host: structure pointer to the UART controller at the core layer.

-

mode: transmission mode, which is an enumerated value. For details, see UartTransMode in uart_if.h).

-

-

HDF_STATUS

-

Sets the UART transmission mode.

-

PollEvent

-

host: structure pointer to the UART controller at the core layer.

-

filep: void pointer to a file.

-

table: void pointer to a poll_table.

-

-

HDF_STATUS

-

Polls for pending events.

-
- -## How to Develop - -The UART module adaptation involves the following steps: - -1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. + **Table 1** Description of the callback functions in UartHostMethod -2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **uart\_config.hcs** file. +| Function| Input Parameter| Output Parameter| Return Value| Description| +| -------- | -------- | -------- | -------- | -------- | +| Init | **host**: structure pointer to the UART controller at the core layer.| –| HDF_STATUS| Initializes a UART device.| +| Deinit | **host**: structure pointer to the UART controller at the core layer.| –| HDF_STATUS| Deinitializes a UART device.| +| Read | **host**: structure pointer to the UART controller at the core layer.
**size**: data size, which is of the uint32_t type.| **data**: pointer to the output data. The value is of the uint8_t type.| HDF_STATUS| Reads data.| +| Write | **host**: structure pointer to the UART controller at the core layer.
**data**: pointer to the input data. The value is of the uint8_t type.
**size**: data size, which is of the uint32_t type.| –| HDF_STATUS| Writes data.| +| SetBaud | **host**: structure pointer to the UART controller at the core layer.
**baudRate**: pointer to the input baud rate. The value is of the uint32_t type. | –| HDF_STATUS| Sets the baud rate.| +| GetBaud | **host**: structure pointer to the UART controller at the core layer.| **baudRate**: pointer to the output baud rate. The value is of the uint32_t type.| HDF_STATUS| Obtains the current baud rate.| +| GetAttribute | **host**: structure pointer to the UART controller at the core layer.| **attribute**: structure pointer to the UART attributes. For details, see **UartAttribute** in **uart_if.h**.| HDF_STATUS| Obtains UART attributes.| +| SetAttribute | **host**: structure pointer to the UART controller at the core layer.
**attribute**: structure pointer to the UART attributes to set.| –| HDF_STATUS| Sets UART attributes.| +| SetTransMode | **host**: structure pointer to the UART controller at the core layer.
**mode**: transfer mode to set. For details, see **UartTransMode** in **uart_if.h**.| –| HDF_STATUS| Sets the UART transfer mode.| +| PollEvent | **host**: structure pointer to the UART controller at the core layer.
**filep**: void pointer to a file.
**table**: void pointer to poll_table.| –| HDF_STATUS| Polls for pending events.| -3. Instantiate the UART controller object. - - Initialize **UartHost**. - - Instantiate **UartHostMethod** in the **UartHost** object. - >![](../public_sys-resources/icon-note.gif) **NOTE** - - >For details, see [Available APIs](#available-apis). +## How to Develop +The UART module adaptation involves the following steps: -4. Debug the driver. - - \(Optional\) For new drivers, verify the basic functions, such as the UART control status and response to interrupts. +1. Instantiate the driver entry. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF. + +2. Configure attribute files. + - Add the **deviceNode** information to the **device_info.hcs** file. + - (Optional) Add the **uart_config.hcs** file. + +3. Instantiate the UART controller object. + - Initialize **UartHost**. + - Instantiate **UartHostMethod** in the **UartHost** object. + > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
+ > For details about the functions in **UartHostMethod**, see [Available APIs](#available-apis). + +4. Debug the driver.
+ (Optional) For new drivers, verify the basic functions, such as the UART status control and response to interrupts. + + +## Development Example + +The following uses **uart_hi35xx.c** as an example to present the information required for implementing device functions. + +1. Instantiate the driver entry.
The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. + Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit. + + UART driver entry example: + + ``` + struct HdfDriverEntry g_hdfUartDevice = { + .moduleVersion = 1, + .moduleName = "HDF_PLATFORM_UART", // (Mandatory) The value must be the same as that in the .hcs file. + .Bind = HdfUartDeviceBind, // See the Bind function. + .Init = HdfUartDeviceInit, // See the Init function. + .Release = HdfUartDeviceRelease, //See the Release function. + }; + // Call HDF_INIT to register the driver entry with the HDF. + HDF_INIT(g_hdfUartDevice); + ``` + +2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **uart_config.hcs** file.
The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **UartHost** members at the core layer. + In this example, there is only one UART controller. If there are multiple UART controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **uart_config** file for each controller. + - **device_info.hcs** configuration example + + + ``` + root { + device_info { + match_attr = "hdf_manager"; + platform :: host { + hostName = "platform_host"; + priority = 50; + device_uart :: device { + device0 :: deviceNode { + policy = 1; // The driver publishes services only for kernel-mode processes. + priority = 40; // Driver startup priority. + permission = 0644; // Permission for the driver to create a device node. + moduleName = "HDF_PLATFORM_UART"; // Driver name, which must be the same as moduleName in the HdfDriverEntry structure. + serviceName = "HDF_PLATFORM_UART_0";// Unique name of the service published by the driver. The name is in the HDF_PLATFORM_UART_X format. X indicates the UART controller number. + deviceMatchAttr = "hisilicon_hi35xx_uart_0"; // Keyword for matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver. + } + device1 :: deviceNode { + policy = 2; // The driver publishes services for both kernel- and user-mode processes. + permission = 0644; + priority = 40; + moduleName = "HDF_PLATFORM_UART"; + serviceName = "HDF_PLATFORM_UART_1"; + deviceMatchAttr = "hisilicon_hi35xx_uart_1"; + } + ... + } + } + } + } + ``` + + - **uart_config.hcs** configuration example + + + ``` + root { + platform { + template uart_controller { // Template configuration. In the template, you can configure the common parameters shared by device nodes. + match_attr = ""; + num = 0; // (Mandatory) Device number + baudrate = 115200; // (Mandatory) Baud rate. Set the value based on service requirements. + fifoRxEn = 1; // (Mandatory) Enable FIFOs to be received. + fifoTxEn = 1; // (Mandatory) Enable FIFOs to be transferred. + flags = 4; // (Mandatory) Flag signal. + regPbase = 0x120a0000; // (Mandatory) Used for address mapping. + interrupt = 38; // (Mandatory) Interrupt number. + iomemCount = 0x48; // (Mandatory) Used for address mapping. + } + controller_0x120a0000 :: uart_controller { + match_attr = "hisilicon_hi35xx_uart_0";// (Mandatory) The value must be the same as that of deviceMatchAttr of the corresponding device in device_info.hcs. + } + controller_0x120a1000 :: uart_controller { + num = 1; + baudrate = 9600; + regPbase = 0x120a1000; + interrupt = 39; + match_attr = "hisilicon_hi35xx_uart_1"; + } + ... + //(Optional) Add more controller data. The node information must have been added in the device_info.hcs file. + } + } + ``` + +3. Initialize the **UartHost** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**) to instantiate **UartHostMethod** in **UartHost** (so that the underlying driver functions can be called). + - Defining a custom structure + + To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **uart_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the device number, to the **UartHost** object at the core layer. + + ``` + struct UartPl011Port { // Interface structure + int32_t enable; + unsigned long physBase; // Physical address + uint32_t irqNum; // Interrupt number + uint32_t defaultBaudrate;// Default baud rate + uint32_t flags; // Flags related to the following three macros. + #define PL011_FLG_IRQ_REQUESTED (1 << 0) + #define PL011_FLG_DMA_RX_REQUESTED (1 << 1) + #define PL011_FLG_DMA_TX_REQUESTED (1 << 2) + struct UartDmaTransfer *rxUdt; // DMA transfer + struct UartDriverData *udd; // The data structure is defined as follows: + }; + struct UartDriverData { // Structure related to data transfer + uint32_t num; + uint32_t baudrate; // Baud rate (configurable) + struct UartAttribute attr; // Attributes, such as the data bit and stop bit, related to data transfer + struct UartTransfer *rxTransfer; // Buffer (FIFO structure) + wait_queue_head_t wait; // Queuing signal related to conditional variables + int32_t count; // Data count + int32_t state; // UART controller state + #define UART_STATE_NOT_OPENED 0 + #define UART_STATE_OPENING 1 + #define UART_STATE_USEABLE 2 + #define UART_STATE_SUSPENDED 3 + uint32_t flags; // Status flags + #define UART_FLG_DMA_RX (1 << 0) + #define UART_FLG_DMA_TX (1 << 1) + #define UART_FLG_RD_BLOCK (1 << 2) + RecvNotify recv; // Pointer to the function that receives serial port data + struct UartOps *ops; // Custom function pointer structure. For details, see device/hisilicon/drivers/uart/uart_pl011.c. + void *private; // It stores the pointer to the start address of UartPl011Port for easy invocation. + }; + + // UartHost is the controller structure at the core layer. The Init function assigns values to the members of UartHost. + struct UartHost { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + uint32_t num; + OsalAtomic atom; + void *priv; // It stores the pointer to the start address of the vendor's custom structure for easy invocation. + struct UartHostMethod *method; // Hook at the core layer. You need to implement and instantiate its member functions. + }; + ``` + - Instantiating **UartHostMethod** in **UartHost** (other members are initialized by **Bind**) -## Development Example + + ``` + // Example in uart_hi35xx.c: instantiate the hook. + struct UartHostMethod g_uartHostMethod = { + .Init = Hi35xxInit, + .Deinit = Hi35xxDeinit, + .Read = Hi35xxRead, + .Write = Hi35xxWrite, + .SetBaud = Hi35xxSetBaud, + .GetBaud = Hi35xxGetBaud, + .SetAttribute = Hi35xxSetAttribute, + .GetAttribute = Hi35xxGetAttribute, + .SetTransMode = Hi35xxSetTransMode, + .pollEvent = Hi35xxPollEvent, + }; + ``` + + - **Bind** function + + Input parameter: + + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information. + + Return value: + + HDF_STATUS
The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file. + + **Table 2** HDF_STATUS + + | Status| Description| + | -------- | -------- | + | HDF_ERR_INVALID_OBJECT | Invalid controller object.| + | HDF_ERR_MALLOC_FAIL | Failed to allocate memory.| + | HDF_ERR_INVALID_PARAM | Invalid parameter.| + | HDF_ERR_IO | I/O error.| + | HDF_SUCCESS | Initialization successful.| + | HDF_FAILURE | Initialization failed.| + + Function description: + + Initializes the custom structure object and **UartHost**. -The following uses **uart\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. + + ``` + //uart_hi35xx.c + static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device) + { + ... + return (UartHostCreate(device) == NULL)? HDF_FAILURE: HDF_SUCCESS;// (Mandatory) Call UartHostCreate. + } + // Description of UartHostCreate() in uart_core.c + struct UartHost *UartHostCreate(struct HdfDeviceObject *device) + { + struct UartHost *host = NULL; // Create UartHost. + ... + host = (struct UartHost *)OsalMemCalloc(sizeof(*host));// Allocate memory. + ... + host->device = device; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and UartHost + device->service = &(host->service; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and UartHost + host->device->service->Dispatch = UartIoDispatch;// Assign values to Dispatch of service. + OsalAtomicSet(&host->atom, 0); // Initialize or set the atomic services. + host->priv = NULL; + host->method = NULL; + return host; + } + ``` + + - **Init** function + + Input parameter: + + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information. + + Return value: + + HDF_STATUS + + Function description: + + Initializes the custom structure object and **UartHost**, calls the **artAddDev** function at the core layer, and connects to the VFS. -1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. + + ``` + int32_t HdfUartDeviceInit(struct HdfDeviceObject *device) + { + int32_t ret; + struct UartHost *host = NULL; + HDF_LOGI("%s: entry", __func__); + ... + host = UartHostFromDevice(device);// Forcibly convert to UartHost by using service. The values are assigned by Bind(). + ... + ret = Hi35xxAttach(host, device); // Initialize the UartHost object. + ... + host->method = &g_uartHostMethod; // Hook the UartHostMethod instance. + return ret; + } + // Initialize UartHost. + static int32_t Hi35xxAttach(struct UartHost *host, struct HdfDeviceObject *device) + { + int32_t ret; + // udd and port are customized structure objects. Implement the related functions as required. + struct UartDriverData *udd = NULL; + struct UartPl011Port *port = NULL; + ... + // Steps 1 to 7 instantiate and assign values to the udd object, and then assign values to UartHost. + udd = (struct UartDriverData *)OsalMemCalloc(sizeof(*udd));// Step 1 + ... + port = (struct UartPl011Port *)OsalMemCalloc(sizeof(struct UartPl011Port));// Step 2 + ... + udd->ops = Pl011GetOps(); // Step 3 Hook the functions for starting or stopping a device, setting attributes, and sending data. + udd->recv = PL011UartRecvNotify;// Step 4 Hook the data receiving notification function (conditional lock mechanism). + udd->count = 0; // Step 5 + port->udd = udd; // Step 6 Enable conversion between UartPl011Port and UartDriverData. + ret = UartGetConfigFromHcs(port, device->property);// Pass the attributes of HdfDeviceObject to the custom structure. + // The sample code is as follows: + ... + udd->private = port; // Step 7 + + host->priv = udd; // (Mandatory) Enable conversion between UartHost and UartDriverData. + host->num = udd->num; // (Mandatory) UART device number + UartAddDev(host); // (Mandatory) Function (in uart_dev.c) used to register a character device node to the VFS so that the UART can be accessed through the virtual file node in user mode. + return HDF_SUCCESS; + } + + static int32_t UartGetConfigFromHcs(struct UartPl011Port *port, const struct DeviceResourceNode *node) + { + uint32_t tmp, regPbase, iomemCount; + struct UartDriverData *udd = port->udd; + struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + ... + // Extract the values based on the request and assign the values to the custom structure. + if (iface->GetUint32(node, "num", &udd->num, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: read busNum fail", __func__); + return HDF_FAILURE; + } + ... + return 0; + } + ``` + - **Release** function - Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. + Input parameter: - - UART driver entry reference + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information. - ``` - struct HdfDriverEntry g_hdfUartDevice = { - .moduleVersion = 1, - .moduleName = "HDF_PLATFORM_UART", // (Mandatory) This parameter must be the same as that in the .hcs file. - .Bind = HdfUartDeviceBind, // See the Bind function. - .Init = HdfUartDeviceInit, // See the Init function. - .Release = HdfUartDeviceRelease, //See the Release function. - }; - // Call HDF_INIT to register the driver entry with the HDF. - HDF_INIT(g_hdfUartDevice); - ``` + Return value: -2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **uart\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **UartHost** members at the core layer. + No value is returned. - In this example, there is only one UART controller. If there are multiple UART controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **uart\_config** file. + Function description: - - **device\_info.hcs** configuration reference + Releases the memory and deletes the controller. This function assigns values to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when **Init()** has the corresponding value assignment operations. - ``` - root { - device_info { - match_attr = "hdf_manager"; - platform :: host { - hostName = "platform_host"; - priority = 50; - device_uart :: device { - device0 :: deviceNode { - policy = 1; // The value 1 indicates that the driver publishes kernel-mode services. The value 2 indicates that the driver publishes user-mode services. - priority = 40; // Driver startup priority - permission = 0644; // Permission for the driver to create a device node - moduleName = "HDF_PLATFORM_UART"; // Driver name, which must be the same as that of moduleName in the driver entry structure. - serviceName = "HDF_PLATFORM_UART_0";// Unique name of the service published by the driver. The name is in the HDF_PLATFORM_UART_X format. X indicates the UART controller number. - deviceMatchAttr = "hisilicon_hi35xx_uart_0"; // Keyword matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver. - } - device1 :: deviceNode { - policy = 2; - permission = 0644; - priority = 40; - moduleName = "HDF_PLATFORM_UART"; - serviceName = "HDF_PLATFORM_UART_1"; - deviceMatchAttr = "hisilicon_hi35xx_uart_1"; - } - ... - } - } + + ``` + void HdfUartDeviceRelease(struct HdfDeviceObject *device) + { + struct UartHost *host = NULL; + ... + host = UartHostFromDevice(device);// Forcibly convert HdfDeviceObject to UartHost by using service. For details about the value assignment, see the Bind function. + ... + if (host->priv != NULL) { + Hi35xxDetach(host); // Customized memory release function. } - } - ``` - - - **uart\_config.hcs** configuration reference - - ``` - root { - platform { - template uart_controller {// Template configuration. In the template, you can configure the common parameters shared by service nodes. - match_attr = ""; - num = 0; // (Mandatory) Device number - baudrate = 115200; // (Mandatory) Baud rate. Set the value based on service requirements. - fifoRxEn = 1; // (Mandatory) Enable the receive of FIFOs. - fifoTxEn = 1; // (Mandatory) Enable the transmit of FIFOs. - flags = 4; // (Mandatory) Flag signal - regPbase = 0x120a0000; // (Mandatory) Used for address mapping. - interrupt = 38; // (Mandatory) Interrupt number - iomemCount = 0x48; // (Mandatory) Used for address mapping. - } - controller_0x120a0000 :: uart_controller { - match_attr = "hisilicon_hi35xx_uart_0";// (Mandatory) The value must be the same as that of deviceMatchAttr of the corresponding device in device_info.hcs. - } - controller_0x120a1000 :: uart_controller { - num = 1; - baudrate = 9600; - regPbase = 0x120a1000; - interrupt = 39; - match_attr = "hisilicon_hi35xx_uart_1"; - } - ... - //(Optional) Add nodes to the device_info.hcs file as required. + UartHostDestroy(host); // Call the function of the core layer to release the host. + } + + static void Hi35xxDetach(struct UartHost *host) + { + struct UartDriverData *udd = NULL; + struct UartPl011Port *port = NULL; + ... + udd = host->priv; // Convert UartHost to UartDriverData. + ... + UartRemoveDev(host);// Remove the VFS. + port = udd->private;// Convert UartDriverData to UartPl011Port. + if (port != NULL) { + if (port->physBase != 0) { + OsalIoUnmap((void *)port->physBase);// Unmap addresses. + } + OsalMemFree(port); + udd->private = NULL; } - } - ``` - -3. Initialize the **UartHost** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **UartHostMethod** \(used to call underlying functions of the driver\) in **UartHost**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - - Custom structure reference - - To the driver, the custom structure carries parameters and data. The values in the **uart\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number, are also passed to the objects at the core layer. - - ``` - struct UartPl011Port {// Structure related to the API - int32_t enable; - unsigned long physBase; // Physical address - uint32_t irqNum; // Interrupt number - uint32_t defaultBaudrate;// Default baud rate - uint32_t flags; // Flag signal, which is related to the following three macros. - #define PL011_FLG_IRQ_REQUESTED (1 << 0) - #define PL011_FLG_DMA_RX_REQUESTED (1 << 1) - #define PL011_FLG_DMA_TX_REQUESTED (1 << 2) - struct UartDmaTransfer *rxUdt; // DMA transmission - struct UartDriverData *udd; // See the following description. - }; - struct UartDriverData {// Structure related to data transmission - uint32_t num; - uint32_t baudrate; // Baud rate (configurable) - struct UartAttribute attr; // Transmission attributes, such as the data bit and stop bit - struct UartTransfer *rxTransfer; // FIFO structure related to the buffer - wait_queue_head_t wait; // Queuing signal related to conditional variables - int32_t count; // Data count - int32_t state; // UART controller status - #define UART_STATE_NOT_OPENED 0 - #define UART_STATE_OPENING 1 - #define UART_STATE_USEABLE 2 - #define UART_STATE_SUSPENED 3 - uint32_t flags; // Status flag - #define UART_FLG_DMA_RX (1 << 0) - #define UART_FLG_DMA_TX (1 << 1) - #define UART_FLG_RD_BLOCK (1 << 2) - RecvNotify recv; // Pointer to the function that receives serial port data - struct UartOps *ops; // Custom function pointer structure. For details, see device/hisilicon/drivers/uart/uart_pl011.c. - void *private; // It stores the pointer to the start address of UartPl011Port for easy invocation. - }; - - // UartHost is the controller structure at the core layer. Its members are assigned with values by using the Init function. - struct UartHost { - struct IDeviceIoService service; - struct HdfDeviceObject *device; - uint32_t num; - OsalAtomic atom; - void *priv; // It stores the pointer to the start address of the vendor's custom structure for invoking the structure. - struct UartHostMethod *method; // Hook at the core layer. The vendor needs to implement and instantiate its member functions. - }; - ``` - - - Instantiate the callback function structure **UartHostMethod** in **UartHost**. Other members are initialized by using the **Bind** function. - - ``` - // Example in pwm_hi35xx.c: instantiate the hook. - struct UartHostMethod g_uartHostMethod = { - .Init = Hi35xxInit, - .Deinit = Hi35xxDeinit, - .Read = Hi35xxRead, - .Write = Hi35xxWrite, - .SetBaud = Hi35xxSetBaud, - .GetBaud = Hi35xxGetBaud, - .SetAttribute = Hi35xxSetAttribute, - .GetAttribute = Hi35xxGetAttribute, - .SetTransMode = Hi35xxSetTransMode, - .pollEvent = Hi35xxPollEvent, - }; - ``` - - - Bind function - - Input parameters: - - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. - - Return values: - - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) - - **Table 2** Input parameters and return values of the Bind function - - - - - - - - - - - - - - - - - - - - - - - - - -

Status (Value)

-

Description

-

HDF_ERR_INVALID_OBJECT

-

Invalid controller object

-

HDF_ERR_MALLOC_FAIL

-

Failed to allocate memory

-

HDF_ERR_INVALID_PARAM

-

Invalid parameter

-

HDF_ERR_IO

-

I/O error

-

HDF_SUCCESS

-

Initialization successful

-

HDF_FAILURE

-

Initialization failed

-
- - Function description: - - Initializes the custom structure object and **UartHost**. - - ``` - //uart_hi35xx.c - static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device) - { - ... - return (UartHostCreate(device) == NULL)? HDF_FAILURE: HDF_SUCCESS;// (Mandatory) Call UartHostCreate. - } - // Description of the UartHostCreate function at the core layer in uart_core.c - struct UartHost *UartHostCreate(struct HdfDeviceObject *device) - { - struct UartHost *host = NULL; // Create a UartHost. - ... - host = (struct UartHost *)OsalMemCalloc(sizeof(*host));// Apply for memory. - ... - host->device = device; // (Mandatory) Enable conversion between HdfDeviceObject and UartHost. - device->service = &(host->service); // (Mandatory) Enable conversion between HdfDeviceObject and UartHost. - host->device->service->Dispatch = UartIoDispatch;// Assign a value to the Dispatch method of service. - OsalAtomicSet(&host->atom, 0); // Initialize or set atomic data. - host->priv = NULL; - host->method = NULL; - return host; - } - ``` - - - Init function - - Input parameters: - - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. - - Return values: - - HDF\_STATUS - - Function description: - - Initializes the custom structure object and **UartHost**, calls the **artAddDev** function at the core layer, and connects to VFS. - - ``` - int32_t HdfUartDeviceInit(struct HdfDeviceObject *device) - { - int32_t ret; - struct UartHost *host = NULL; - HDF_LOGI("%s: entry", __func__); - ... - host = UartHostFromDevice(device);// Forcibly convert to UartHost by using service. The value is assigned in the Bind function. - ... - ret = Hi35xxAttach(host, device); // Initialize the UartHost object. - ... - host->method = &g_uartHostMethod; // Connect to the UARTHostMethod instance. - return ret; - } - // Complete initialization of the UartHost object. - static int32_t Hi35xxAttach(struct UartHost *host, struct HdfDeviceObject *device) - { - int32_t ret; - // udd and port are structure objects customized by the vendor. The vendor needs to implement related functions as required. - struct UartDriverData *udd = NULL; - struct UartPl011Port *port = NULL; - ... - // Steps [1] to [7] assign values to udd and then to the UartHost object at the core layer. - udd = (struct UartDriverData *)OsalMemCalloc(sizeof(*udd));// [1] - ... - port = (struct UartPl011Port *)OsalMemCalloc(sizeof(struct UartPl011Port));// [2] - ... - udd->ops = Pl011GetOps();// [3] Perform operations, such as starting or stopping a device, setting attributes, and sending data. - udd->recv = PL011UartRecvNotify;// [4] Connect to the data receiving notification function (conditional lock mechanism). - udd->count = 0; // [5] - port->udd = udd; // [6] Enable conversion between UartPl011Port and UartDriverData. - ret = UartGetConfigFromHcs(port, device->property);// (Mandatory) Transfer the attributes of HdfDeviceObject to the vendor custom structure. - // The sample code is as follows: - ... - udd->private = port; // [7] - - host->priv = udd; // (Mandatory) Enable conversion between UartHost and UartDriverData. - host->num = udd->num;// (Mandatory) UART device number - UartAddDev(host); // (Mandatory) Function in uart_dev.c at the core layer used to register a character device node with the VFS so that the UART can be accessed in user mode through this virtual file node. - return HDF_SUCCESS; - } - - static int32_t UartGetConfigFromHcs(struct UartPl011Port *port, const struct DeviceResourceNode *node) - { - uint32_t tmp, regPbase, iomemCount; - struct UartDriverData *udd = port->udd; - struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); - ... - // Extract the value based on the request parameter and assign the value to the vendor custom structure. - if (iface->GetUint32(node, "num", &udd->num, 0) != HDF_SUCCESS) { - HDF_LOGE("%s: read busNum fail", __func__); - return HDF_FAILURE; - } - ... - return 0; - } - ``` - - - Release function - - Input parameters: - - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. - - Return values: - - – - - Function description: - - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. - - ``` - void HdfUartDeviceRelease(struct HdfDeviceObject *device) - { - struct UartHost *host = NULL; - ... - host = UartHostFromDevice(device);// Forcibly convert HdfDeviceObject to UartHost by using service. For details about the value assignment, see the Bind function. - ... - if (host->priv != NULL) { - Hi35xxDetach(host); // Memory release function customized by the vendor. For details, see the following description. - } - UartHostDestroy(host); // Call the function of the core layer to release the host. - } - - static void Hi35xxDetach(struct UartHost *host) - { - struct UartDriverData *udd = NULL; - struct UartPl011Port *port = NULL; - ... - udd = host->priv; // Convert UartHost to UartDriverData. - ... - UartRemoveDev(host);// Remove the VFS. - port = udd->private;// Convert UartDriverData to UartPl011Port. - if (port != NULL) { - if (port->physBase != 0) { - OsalIoUnmap((void *)port->physBase);// Remove address mapping. - } - (void)OsalMemFree(port); - udd->private = NULL; - } - (void)OsalMemFree(udd);// Release UartDriverData. - host->priv = NULL; - } - ``` - - - + OsalMemFree(udd);//Release UartDriverData. + host->priv = NULL; + } + ``` -- GitLab