未验证 提交 8ea3e5b4 编写于 作者: O openharmony_ci 提交者: Gitee

!2064 #I4U985完成,请审批

Merge pull request !2064 from Annie_wang/PR1290
......@@ -2,20 +2,23 @@
## Overview<a name="section1"></a>
- The High-Definition Multimedia Interface (HDMI) is an audio/video transmission protocol released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson, Toshiba.
- The HDMI works in master/slave mode and usually has a source and a sink.
- The HDMI APIs provide a set of common functions for HDMI transmission, including:
High-Definition Multimedia Interface (HDMI) is an audio/video transmission protocol released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson, and Toshiba.
- Opening and closing an HDMI controller.
- Starting and stopping HDMI transmission.
- Setting audio, video, and High Dynamic Range (HDR) attributes, color depth, and AV mute.
- Reading the raw Extended Display Identification Data (EDID) from a sink.
- Registering and unregistering a callback for HDMI hot plug detect.
- [Figure 1](#fig1) shows the HDMI physical connection.
HDMI works in master/slave mode and usually has a source and a sink.
**Figure 1** HDMI physical connection<a name="fig1"></a>
![](figures/HDMI_physical_connection.png "HDMI_physical_connection")
The HDMI APIs provide a set of common functions for HDMI transmission, including:
- Opening and closing an HDMI controller
- Starting and stopping HDMI transmission
- Setting audio, video, and High Dynamic Range (HDR) attributes, color depth, and AV mute
- Reading the raw Extended Display Identification Data (EDID) from a sink
- Registering and unregistering a callback for HDMI hot plug detect (HPD)
[Figure 1](#fig1) shows the HDMI physical connection.
**Figure 1** HDMI physical connection<a name="fig1"></a>
![](figures/HDMI_physical_connection.png "HDMI_physical_connection")
## Available APIs<a name="section2"></a>
......@@ -94,16 +97,16 @@
<td class="cellrowborder" valign="top" width="53.339999999999996%">Reads the raw EDID from a sink.</p>
</td>
</tr>
<tr><td class="cellrowborder" bgcolor="#ffffff" rowspan="2" valign="top" width="18.63%"><p>Registering or unregistering a callback for HDMI hot plug detect</p>
<tr><td class="cellrowborder" bgcolor="#ffffff" rowspan="2" valign="top" width="18.63%"><p>Registering or unregistering a callback for HDMI HPD</p>
</td>
<td class="cellrowborder" valign="top" width="28.03%"><p>HdmiRegisterHpdCallbackFunc</p>
</td>
<td class="cellrowborder" valign="top" width="53.339999999999996%">Registers a callback for HDMI hot plug detect.</p>
<td class="cellrowborder" valign="top" width="53.339999999999996%">Registers a callback for HDMI HPD.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top"><p>HdmiUnregisterHpdCallbackFunc</p>
</td>
<td class="cellrowborder" valign="top"><p>Unregisters the callback for HDMI hot plug detect.</p>
<td class="cellrowborder" valign="top"><p>Unregisters the callback for HDMI HPD.</p>
</td>
</tr>
</tbody>
......@@ -121,7 +124,7 @@
### Opening an HDMI Controller<a name="section5"></a>
Before HDMI communication, call **HdmiOpen** to enable an HDMI controller.
Before HDMI communication, call **HdmiOpen** to open an HDMI controller.
```c
DevHandle HdmiOpen(int16_t number);
......@@ -173,7 +176,7 @@ if (hdmiHandle == NULL) {
}
```
### Registering a Callback for Hot Plug Detect<a name="section6"></a>
### Registering a Callback for HPD<a name="section6"></a>
```c
int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo *callback);
......@@ -196,7 +199,7 @@ int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>callback</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Callback invoked to return the hot plug detect result.</p>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the callback to be invoked to return the HPD result.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
......@@ -217,10 +220,10 @@ int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo
</tbody>
</table>
The following is an example of registering a callback for hot plug detect:
The following is an example of registering a callback for HPD:
```c
/* Definition of the callback for hot plug detect */
/* Definition of the callback for HPD */
static void HdmiHpdHandle(void *data, bool hpd)
{
if (data == NULL) {
......@@ -237,7 +240,7 @@ static void HdmiHpdHandle(void *data, bool hpd)
}
}
/* Example of registering a callback for hot plug detect */
/* Example of registering a callback for HPD */
struct HdmiHpdCallbackInfo info = {0};
info.data = handle;
info.callbackFunc = HdmiHpdHandle;
......@@ -247,7 +250,7 @@ static void HdmiHpdHandle(void *data, bool hpd)
}
```
### Reading the EDID<a name="section7"></a>
### Reading the RAW EDID<a name="section7"></a>
```c
int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len);
......@@ -270,7 +273,7 @@ int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len);
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>buffer</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Data buffer.</p>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the data buffer.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>len</p>
......@@ -296,7 +299,7 @@ int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len);
</tbody>
</table>
The following is an example of reading the raw EDID data from a sink:
The following is an example of reading the raw EDID from a sink:
```c
int32_t len;
......@@ -333,7 +336,7 @@ int32_t HdmiSetAudioAttribute(DevHandle handle, struct HdmiAudioAttr *attr);
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>attr</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p> Audio attributes.</p>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the audio attributes.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
......@@ -394,7 +397,7 @@ int32_t HdmiSetVideoAttribute(DevHandle handle, struct HdmiVideoAttr *attr);
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>attr</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Video attributes.</p>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the video attributes.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
......@@ -454,7 +457,7 @@ int32_t HdmiSetHdrAttribute(DevHandle handle, struct HdmiHdrAttr *attr);
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>attr</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDR attributes.</p>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the HDR attributes.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
......@@ -627,7 +630,7 @@ int32_t HdmiDeepColorGet(DevHandle handle, enum HdmiDeepColor *color);
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>color</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Color depth.</p>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the color depth.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
......@@ -760,7 +763,7 @@ if (ret != 0) {
}
```
### Unregistering the Callback for Hot Plug Detect<a name="section12"></a>
### Unregistering the Callback for HPD<a name="section12"></a>
```c
int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle);
......@@ -799,7 +802,7 @@ int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle);
</tbody>
</table>
The following is an example of unregistering the callback for hot plug detect:
The following is an example of unregistering the callback for HPD:
```c
int32_t ret;
......@@ -856,7 +859,7 @@ The sample code is as follows:
```c
#include "hdmi_if.h" /* Header file for HDMI standard APIs */
#include "hdf_log.h" /* Header file for log APIs */
##include "osal_time.h" /* Header file for delay and sleep APIs */
#include "osal_time.h" /* Header file for delay and sleep APIs */
/* Callback for hog plug detect */
static void HdmiHpdHandle(void *data, bool hpd)
......
......@@ -5,22 +5,20 @@
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.
I3C is backward compatible with legacy Inter-Integrated Circuit (I2C) devices. 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 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.
The I2C device, I3C slave device, and I3C secondary master device can coexist on the I3C bus.
The I3C APIs provide a set of common functions for I3C transfer, including:
- Opening and closing an I3C controller.
- Obtaining and setting I3C controller parameters.
- Performing customized I3C message transfer by using a message array.
- Requesting and releasing an IBI.
- 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
[Figure 1](#fig1) shows the I3C physical connection.
**Figure 1** I3C physical connection<a name="fig1"></a>
![](figures/I3C_physical_connection.png "I3C_physical_connection.png")
![](figures/I3C_physical_connection.png "I3C_physical_connection")
## Available APIs<a name="section2"></a>
......@@ -83,8 +81,9 @@ The I3C APIs provide a set of common functions for I3C transfer, including:
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>All functions described in this document can be called only in kernel space.
>![](../public_sys-resources/icon-note.gif) **NOTE**
>
>All functions described in this document can be called only in the kernel space.
## Usage Guidelines<a name="section3"></a>
......@@ -93,7 +92,6 @@ The I3C APIs provide a set of common functions for I3C transfer, including:
[Figure 2](#fig2) shows how I3C works.
**Figure 2** How I3C works<a name="fig2"></a>
![](figures/I3C_usage_flowchart.png "I3C_usage_flowchart")
### Opening an I3C Controller<a name="section5"></a>
......@@ -107,7 +105,7 @@ DevHandle I3cOpen(int16_t number);
<a name="table2"></a>
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="20.66%"><p> Parameter</strong></p>
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="20.66%"><p>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="79.34%"><p><strong>Description</strong></p>
</th>
......@@ -136,7 +134,7 @@ DevHandle I3cOpen(int16_t number);
</tbody>
</table>
In the following example, open I3C controller 1 of the eight I3C controllers (numbered from 0 to 7) in the system.
The following example opens I3C controller 1 of the eight I3C controllers (numbered from 0 to 7) in the system.
```c
DevHandle i3cHandle = NULL; /* I3C controller handle. /
......@@ -173,7 +171,7 @@ int32_t I3cTransfer(DevHandle handle, struct I3cMsg *msgs, int16_t count, enum T
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>msgs</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Message structure array of the data to be transmitted.</p>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the message structure array of the data to be transmitted.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>count</p>
......@@ -183,7 +181,7 @@ int32_t I3cTransfer(DevHandle handle, struct I3cMsg *msgs, int16_t count, enum T
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>mode</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>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).
<td class="cellrowborder" valign="top" width="50%"><p>Transmission mode, where the value <b>0</b> indicates the I2C mode, <b>1</b> indicates the I3C mode, and <b>2</b> indicates transmission of the Common Command Code (CCC).
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
......@@ -211,11 +209,11 @@ int32_t ret;
uint8_t wbuff[2] = { 0x12, 0x13 };
uint8_t rbuff[2] = { 0 };
struct I3cMsg msgs[2]; /* Custom message array for transfer. */
msgs[0].buf = wbuff; /* Data to write */
msgs[0].buf = wbuff; /* Data to write. */
msgs[0].len = 2; /* Length of the data to write. */
msgs[0].addr = 0x3F; /* Address of the device to which the data is written. */
msgs[0].flags = 0; /* Transfer flag. An write operation is performed by default. */
msgs[1].buf = rbuff; /* Data to read */
msgs[0].flags = 0; /* Transfer flag. A write operation is performed by default. */
msgs[1].buf = rbuff; /* Data to read. */
msgs[1].len = 2; /* Length of the data to read. */
msgs[1].addr = 0x3F; /* Address of the device from which the data is read. */
msgs[1].flags = I3C_FLAG_READ /* I3C_FLAG_READ is set. */
......@@ -227,9 +225,10 @@ 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 parameters.
>- 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<a name="section7"></a>
......@@ -242,7 +241,7 @@ int32_t I3cGetConfig(DevHandle handle, struct I3cConfig *config);
<a name="table4"></a>
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p>
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</th>
......@@ -255,7 +254,7 @@ int32_t I3cGetConfig(DevHandle handle, struct I3cConfig *config);
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>config</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>I3C controller configuration.</p>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the I3C controller configuration.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
......@@ -286,7 +285,7 @@ int32_t I3cSetConfig(DevHandle handle, struct I3cConfig *config);
<a name="table5"></a>
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p>
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</th>
......@@ -299,7 +298,7 @@ int32_t I3cSetConfig(DevHandle handle, struct I3cConfig *config);
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>config</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>I3C controller configuration.</p>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the I3C controller configuration.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
......@@ -330,7 +329,7 @@ int32_t I3cRequestIbi(DevHandle handle, uint16_t addr, I3cIbiFunc func, uint32_t
<a name="table6"></a>
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p>
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</th>
......@@ -418,7 +417,7 @@ int32_t I3cFreeIbi(DevHandle handle, uint16_t addr);
<a name="table7"></a>
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p>
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</th>
......@@ -486,7 +485,7 @@ void I3cClose(DevHandle handle);
I3cClose(i3cHandle); /* Close an I3C controller. */
```
## Example<a name="section12"></a>
## Example<a name="section12""></a>
This following example shows how to use I3C APIs to manage an I3C device on a Hi3516D V300 development board.
......@@ -504,7 +503,7 @@ 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 CCCs */
#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 */
......
# Pin<a name="title_PinDevelop"></a>
## Overview<a name="section1_PinDevelop"></a>
The pin module controls the states and functionalities of system pins. In the Hardware Driver Foundation (HDF), the pin module uses the service-free mode for API adaptation. The service-free mode applies to devices that do not provide user-mode APIs or the OS system that does not distinguish the user mode and the kernel mode. In the service-free mode, DevHandle (a void pointer) directly points to the kernel-mode address of the device object.
Figure 1 Service-free mode
![image1](figures/service-free-mode.png "service-free-mode")
## Available APIs<a name="section2_PinDevelop"></a>
**PinCntlrMethod**:
```c
struct PinCntlrMethod {
int32_t (*SetPinPull)(struct PinCntlr *cntlr, uint32_t index, enum PinPullType pullType);
int32_t (*GetPinPull)(struct PinCntlr *cntlr, uint32_t index, enum PinPullType *pullType);
int32_t (*SetPinStrength)(struct PinCntlr *cntlr, uint32_t index, uint32_t strength);
int32_t (*GetPinStrength)(struct PinCntlr *cntlr, uint32_t index, uint32_t *strength);
int32_t (*SetPinFunc)(struct PinCntlr *cntlr, uint32_t index, const char *funcName);
int32_t (*GetPinFunc)(struct PinCntlr *cntlr, uint32_t index, const char **funcName);
};
```
**Table 1** APIs for the members in the PinCntlrMethod structure
| API | Input Parameter | Return Value| Description|
| ------------ | ------------------------------------------- | ------ | ---- |
| SetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**pullType**: pull type of the pin. It is an enum constant.|HDF_STATUS|Sets the pull type of a pin.|
| GetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**pullType**: pointer to the pull type of the pin.| HDF_STATUS| Obtains the pull type of a pin.|
| SetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**strength**: pull strength of the pin. It is a uint32_t variable.| HDF_STATUS| Sets the pull strength of a pin.|
| GetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**strength**: pointer to the pull strength of the pin.| HDF_STATUS| Obtains the pull strength of a pin.|
| SetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**funcName**: char pointer to the pin functionality.| HDF_STATUS| Sets the pin functionality.|
| GetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**funcName**: char double pointer to the pin functionality.| HDF_STATUS| Obtains the pin functionalities.|
## How to Develop<a name="section3_PinDevelop"></a>
The pin 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.
2. Configure attribute files.
- Add the **deviceNode** information to the **device_info.hcs** file.
- (Optional) Add the **pin_config.hcs** file.
3. Instantiate the pin controller object.
- Initialize the **PinCntlr** object.
- Instantiate **PinCntlrMethod** in the **PinCntlr** object.
>![](../public_sys-resources/icon-note.gif) **NOTE**
>For details, see [Available APIs](#section2_PINDevelop).
4. Debug the driver.
- (Optional) Verify basic functionalities of new drivers. For example, verify the information returned when the driver is loaded and whether data is successfully transmitted.
## Development Example<a name="section4_PinDevelop"></a>
The following uses **pin_hi35xx.c** as an example to present the content to be provided by the vendor to implement device functionalities.
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 are 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 the driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
Pin driver entry reference:
```c
static struct HdfDriverEntry g_hi35xxPinDriverEntry = {
.moduleVersion = 1,
.Bind = Hi35xxPinBind,
.Init = Hi35xxPinInit,
.Release = Hi35xxPinRelease,
.moduleName = "hi35xx_pin_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
// Call HDF_INIT to register the driver entry with the HDF.
HDF_INIT(g_hi35xxPinDriverEntry);
```
2. Add **deviceNode** to the **device\_info.hcs** file, and set the device attributes in the **pin\_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 **PinCntlr** members at the core layer.
>![](../public_sys-resources/icon-note.gif) **NOTE**
>If there are multiple devices, add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **pin\_config** file.
- **device\_info.hcs** reference:
```c
root {
device_info {
platform :: host {
hostName = "platform_host";
priority = 50;
device_pin :: device {
device0:: deviceNode { // Set an HDF device node for each pin controller.
policy = 0; // 2: visible in user mode; 1: visible in kernel mode; 0: no service required.
priority = 10; // Driver startup priority.
permission = 0644; // Permission to create device nodes for the driver.
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
moduleName = "hi35xx_Pin_driver";
/* (Mandatory) Set the controller private data, which must be same as that in Pin_config.hcs. */
deviceMatchAttr = "hisilicon_hi35xx_Pin_0";
}
device1 :: deviceNode {
policy = 0;
priority = 10;
permission = 0644;
moduleName = "hi35xx_Pin_driver";
deviceMatchAttr = "hisilicon_hi35xx_Pin_1";
}
...
}
}
}
}
```
- **Pin\_config.hcs** reference:
```c
root {
platform {
Pin_config_hi35xx {
template Pin_controller { // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes.
number = 0; // (Mandatory) Controller ID.
regStartBasePhy = 0; // (Mandatory) Start physical base address of the register.
regSize = 0; // (Mandatory) Register bit width.
PinCount = 0; // (Mandatory) Number of pins.
match_attr = "";
template Pin_desc {
PinName = ""; // (Mandatory) Pin name.
init = 0; // (Mandatory) Default value of the register.
F0 = ""; // (Mandatory) Functionality 0.
F1 = ""; // Functionality 1.
F2 = ""; // Functionality 2.
F3 = ""; // Functionality 3.
F4 = ""; // Functionality 4.
F5 = ""; // Functionality 5.
}
}
controller_0 :: Pin_controller {
number = 0;
regStartBasePhy = 0x10FF0000;
regSize = 0x48;
PinCount = 18;
match_attr = "hisilicon_hi35xx_Pin_0";
T1 :: Pin_desc {
PinName = "T1";
init = 0x0600;
F0 = "EMMC_CLK";
F1 = "SFC_CLK";
F2 = "SFC_BOOT_MODE";
}
...
}
...// Each pin controller corresponds to a controller node. If there are multiple pin controllers, add the corresponding controller nodes one by one.
}
}
}
```
3. Initialize the **PinCntlr** object at the core layer, including initializing the vendor custom structure (passing parameters and data), instantiating **PinCntlrMethod** (used to call underlying functions of the driver) in **PinCntlr**, and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**).
- Initializing the vendor custom structure
The **PinCntlr** structure holds parameters and data for the driver. The HDF obtains the values in **pin\_config.hcs** using **DeviceResourceIface**.
```c
// PinCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct PinCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct PinCntlrMethod *method;
struct DListHead node;
OsalSPinlock sPin;
uint16_t number;
uint16_t PinCount;
struct PinDesc *Pins;
void *priv;
};
struct PinDesc {
const char *PinName; // Pointer to the pin name.
void *priv;
};
```
- Instantiating **PinCntlrMethod** (other members are initialized by **Init**)
```c
// Example of Pin_hi35xx.c: Instantiate the hook.
static struct PinCntlrMethod g_method = {
.SetPinPull = Hi35xxPinSetPull,
.GetPinPull = Hi35xxPinGetPull,
.SetPinStrength = Hi35xxPinSetStrength,
.GetPinStrength = Hi35xxPinGetStrength,
.SetPinFunc = Hi35xxPinSetFunc,
.GetPinFunc = Hi35xxPinGetFunc,
};
```
- **Init** function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
Return value:
**HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.)
**Table 2** HDF\_STATUS
<table><thead align="left"><tr id="row31521027164144"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry1990732428164144p0"><a name="entry1990732428164144p0"></a><a name="entry1990732428164144p0"></a>State</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry2123581292164144p0"><a name="entry2123581292164144p0"></a><a name="entry2123581292164144p0"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row1749271383164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry202330388164144p0"><a name="entry202330388164144p0"></a><a name="entry202330388164144p0"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1717598064164144p0"><a name="entry1717598064164144p0"></a><a name="entry1717598064164144p0"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row1715354988164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry450625221164144p0"><a name="entry450625221164144p0"></a><a name="entry450625221164144p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry361497788164144p0"><a name="entry361497788164144p0"></a><a name="entry361497788164144p0"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row1202091366164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry370837906164144p0"><a name="entry370837906164144p0"></a><a name="entry370837906164144p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry353311523164144p0"><a name="entry353311523164144p0"></a><a name="entry353311523164144p0"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row602018308164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1984036607164144p0"><a name="entry1984036607164144p0"></a><a name="entry1984036607164144p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1221756048164144p0"><a name="entry1221756048164144p0"></a><a name="entry1221756048164144p0"></a>I/O error</p>
</td>
</tr>
<tr id="row47997479164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1220816374164144p0"><a name="entry1220816374164144p0"></a><a name="entry1220816374164144p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1903499126164144p0"><a name="entry1903499126164144p0"></a><a name="entry1903499126164144p0"></a>Initialization successful</p>
</td>
</tr>
<tr id="row2031856197164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry463793674164144p0"><a name="entry463793674164144p0"></a><a name="entry463793674164144p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry516362874164144p0"><a name="entry516362874164144p0"></a><a name="entry516362874164144p0"></a>Initialization failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Initializes the custom structure and **PinCntlr** members, and connects to the pin controller by calling the **PinCntlrAdd** function at the core layer.
```c
static int32_t Hi35xxPinInit(struct HdfDeviceObject *device)
{
...
struct Hi35xxPinCntlr *hi35xx = NULL;
...
ret = Hi35xxPinCntlrInit(device, hi35xx); // Obtain .hcs information.
...
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
ret = Hi35xxPinParsePinNode(childNode, hi35xx, index); // (Mandatory) The implementation is as follows:
...
}
hi35xx->cntlr.method = &g_method; // Instantiate OPS.
ret = PinCntlrAdd(&hi35xx->cntlr); // Connect to the controller.
...
}
static int32_t Hi35xxPinParsePinNode(const struct DeviceResourceNode *node,
struct Hi35xxPinCntlr *hi35xx,
int32_t index)
{
...
hi35xx->cntlr.Pins[index].PinName = hi35xx->desc[index].PinName; // Instantiate PinName.
hi35xx->cntlr.Pins[index].priv = (void *)node; // Instantiate nodes.
...
}
- **Release** function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
Return value:
Function description:
Releases memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
```c
static void Hi35xxPinRelease(struct HdfDeviceObject *device)
{
struct PinCntlr *cntlr = NULL;
...
PinCntlrRemove(cntlr);// (Mandatory) Call the function at the core layer to release pin controller devices and services.
...
}
```
# Regulator<a name="title_REGULATOR_des"></a>
## Overview<a name="section1_REGULATOR_des"></a>
The regulator module controls the voltage and current supplies of some devices in the system. In an embedded system (especially a mobile phone), it is important to control the power consumption, which directly affects the battery endurance. You can use a regulator to shut down the power supply to an idle module in the system or reduce the voltage and current for the module.
- The regulator APIs provide a set of functions for managing a regulator, including those for:
- Opening or closing a regulator device handle
- Setting the output voltage and current for a regulator
- Enabling or disabling a regulator
- Obtaining the voltage, current, and status of a regulator
## Available APIs<a name="section2_REGULATOR_des"></a>
**Table 1** Regulator APIs
<a name="table1_REGULATOR_des"></a>
<table border="0" cellpadding="0" cellspacing="0" width="600" style="border-collapse:
collapse;table-layout:fixed;width:855pt">
<colgroup><col width="183" style="mso-width-source:userset;mso-width-alt:5856;width:137pt">
<col width="159" style="mso-width-source:userset;mso-width-alt:5088;width:119pt">
<col width="213" style="mso-width-source:userset;mso-width-alt:6816;width:160pt">
</colgroup><tbody><tr height="19" style="height:14.25pt">
<td height="19" width="183" style="height:14.25pt;width:137pt">Category</td>
<td width="159" style="width:119pt">API</td>
<td width="213" style="width:160pt">Description</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">Operating a regulator device handle</td>
<td>RegulatorOpen</td>
<td>Opens a regulator device handle.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">RegulatorClose</td>
<td>Closes a regulator device handle.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="3" height="57" class="xl65" style="height:42.75pt">Enabling or disable a regulator</td>
<td>RegulatorEnable</td>
<td>Enables a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">RegulatorDisable</td>
<td>Disables a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">RegulatorForceDisable</td>
<td>Forcibly disables a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">Setting or obtaining the output voltage</td>
<td>RegulatorSetVoltage</td>
<td>Sets the output voltage for a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">RegulatorGetVoltage</td>
<td>Obtains the output voltage of a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">Setting or obtaining the output current</td>
<td>RegulatorSetCurrent</td>
<td>Sets the output current for a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">RegulatorGetCurrent</td>
<td>Obtains the output current of a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" class="xl66" style="height:14.25pt">Querying the regulator status</td>
<td>RegulatorGetStatus</td>
<td>Obtains the regulator status.</td>
</tr>
<!--[if supportMisalignedColumns]-->
<tr height="0" style="display:none">
<td width="183" style="width:137pt"></td>
<td width="159" style="width:119pt"></td>
<td width="213" style="width:160pt"></td>
</tr>
<!--[endif]-->
</tbody></table>
>![](../public_sys-resources/icon-note.gif) **NOTE**
>The regulator module can be used in kernel mode but not in user mode.
## Usage Guidelines<a name="section3_REGULATOR_des"></a>
### How to Use<a name="section3.1_REGULATOR_des"></a>
During the OS startup process, the driver management module loads the regulator driver based on the configuration file. Then, the regulator driver detects the regulator devices and initializes the driver.
The figure below shows the process of using a regulator.
**Figure 1** Process of using a regulator<a name="fig1_regulator_des"></a>
![](figures/process-of-using-regulator.png)
### Opening a Regulator Device Handle<a name="section3.2_REGULATOR_des"></a>
Before operating a regulator, call **RegulatorOpen** to open the device handle of the regulator. This function returns the device handle of the regulator.
```c
DevHandle RegulatorOpen(const char *name);
```
**Table 2** Description of RegulatorOpen
<a name="table2_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------------------- |
| name | Name of the target regulator. |
| **Return Value**| **Description** |
| handle | The regulator device handle is returned if the operation is successful.|
| NULL | The operation fails. |
```c
/* Regulator name. */
const char *name = "regulator_virtual_1";
DevHandle handle = NULL;
/* Open the regulator device handle. */
handle = RegulatorOpen(name);
if (handle == NULL) {
/* Error handling. */
}
```
### Closing a Regulator Device Handle<a name="section3.3_REGULATOR_des"></a>
Call **RegulatorClose** to close the regulator device handle to release resources.
```c
void RegulatorClose(DevHandle handle);
```
**Table 3** Description of RegulatorClose
<a name="table3_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ------ | ----------------- |
| handle | Regulator device handle to close.|
```c
/* Close the regulator device handle. */
RegulatorClose(handle);
```
### Enabling a Regulator<a name="section3.4_REGULATOR_des"></a>
Call **RegulatorEnable** to enable a regulator.
```c
int32_t RegulatorEnable(DevHandle handle);
```
**Table 4** Description of RegulatorEnable
<a name="table4_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------- |
| handle | Device handle of the regulator to enable.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
```c
int32_t ret;
/* Enable the regulator. */
ret = RegulatorEnable(handle);
if (ret != 0) {
/* Error handling. */
}
```
### Disabling a Regulator<a name="section3.5_REGULATOR_des"></a>
Call **RegulatorDisable** to disable a regulator. The operation will fail if the regulator status is set to always on or if a child node of the regulator is not disabled.
```c
int32_t RegulatorDisable(DevHandle handle);
```
**Table 5** Description of RegulatorDisable
<a name="table5_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------- |
| handle | Device handle of the regulator to disable.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
```c
int32_t ret;
/* Disable the regulator. */
ret = RegulatorDisable(handle);
if (ret != 0) {
/* Error handling. */
}
```
### Forcibly Disabling a Regulator<a name="section3.6_REGULATOR_des"></a>
Call **RegulatorForceDisable** to forcibly disable a regulator. The regulator will be disabled event if its status is set to always on or its child node is still enabled.
```c
int32_t RegulatorForceDisable(DevHandle handle);
```
**Table 6** Description of RegulatorForceDisable
<a name="table6_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------- |
| handle | Device handle of the target regulator.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
```c
int32_t ret;
/* Forcibly disable the regulator. */
ret = RegulatorForceDisable(handle);
if (ret != 0) {
/* Error handling. */
}
```
### Setting the Output Voltage Range for a Regulator<a name="section3.7_REGULATOR_des"></a>
Call **RegulatorSetVoltage** to set the output voltage range for a regulator.
```c
int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv);
```
**Table 7** Description of RegulatorSetVoltage
<a name="table7_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------- |
| handle | Device handle of the target regulator.|
| minUv | Minimum voltage to set. |
| maxUv | Maximum voltage to set. |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
```c
int32_t ret;
int32_t minUv = 0; // Set the minimum voltage to 0 µV.
int32_t maxUv = 20000; // Set the maximum voltage to 20000 µV.
/* Set the output voltage range for the regulator. */
ret = RegulatorSetVoltage(handle, minUv, maxUv);
if (ret != 0) {
/* Error handling. */
}
```
### Obtaining Regulator Voltage Information<a name="section3.8_REGULATOR_des"></a>
Call **RegulatorGetVoltage** to obtain voltage information of a regulator.
```c
int32_t RegulatorGetVoltage(DevHandle handle, uint32_t *voltage);
```
**Table 8** Description of RegulatorGetVoltage
<a name="table8_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------- |
| handle | Device handle of the target regulator.|
| *voltage | Pointer to the regulator voltage information. |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
```c
int32_t ret;
uint32_t voltage;
/* Obtain the regulator voltage information. */
ret = RegulatorGetVoltage(handle, &voltage);
if (ret != 0) {
/* Error handling. */
}
```
### Setting the Output Current Range for a Regulator<a name="section3.9_REGULATOR_des"></a>
Call **RegulatorSetCurrent** to set the output current range for a regulator.
```c
int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa);
```
**Table 9** Description of RegulatorSetCurrent
<a name="table9_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------- |
| handle | Device handle of the target regulator.|
| minUa | Minimum current to set. |
| maxUa | Maximum current to set. |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
```c
int32_t ret;
int32_t minUa = 0; // Set the minimum current to 0 μA.
int32_t maxUa = 200; // Set the maximum current to 200 μA.
/* Set the output current range for the regulator. */
ret = RegulatorSetCurrent(handle, minUa, maxUa);
if (ret != 0) {
/* Error handling. */
}
```
### Obtaining Regulator Current Information<a name="section3.10_REGULATOR_des"></a>
Call **RegulatorGetCurrent** to obtain current information of a regulator.
```c
int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent);
```
**Table 10** Description of RegulatorGetCurrent
<a name="table10_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ----------- | ----------------- |
| handle | Device handle of the target regulator.|
| *regCurrent | Pointer to the regulator current information. |
| **Return Value** | **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
```c
int32_t ret;
uint32_t regCurrent;
/* Obtain the regulator current information. */
ret = RegulatorGetCurrent(handle, &regCurrent);
if (ret != 0) {
/* Error handling. */
}
```
### Obtaining Regulator Status<a name="section3.11_REGULATOR_des"></a>
Call **RegulatorGetStatus** to obtain the regulator status.
```c
int32_t RegulatorGetStatus(DevHandle handle, uint32_t *status);
```
**Table 11** Description of RegulatorGetStatus
<a name="table11_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------- |
| handle | Device handle of the target regulator.|
| *status | Pointer to the regulator status information. |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
```c
int32_t ret;
uint32_t status;
/* Obtain the regulator status. */
ret = RegulatorGetStatus(handle, &status);
if (ret != 0) {
/* Error handling. */
}
```
## Development Example<a name="section4_REGULATOR_des"></a>
The following is an example of using a regulator.
```c
void RegulatorTestSample(void)
{
int32_t ret;
/* Regulator name. */
const char *name = "regulator_virtual_1";
DevHandle handle = NULL;
/* Open the regulator device handle. */
handle = RegulatorOpen(name);
if (handle == NULL) {
HDF_LOGE("RegulatorOpen: failed!\n");
return;
}
/* Enable the regulator. */
ret = RegulatorEnable(handle);
if (ret != 0) {
HDF_LOGE("RegulatorEnable: failed, ret %d\n", ret);
goto _ERR;
}
int32_t minUv = 0; // Set the minimum voltage to 0 µV.
int32_t maxUv = 20000; // Set the maximum voltage to 20000 µV.
/* Set the output voltage range for the regulator. */
ret = RegulatorSetVoltage(handle, minUv, maxUv);
if (ret != 0) {
HDF_LOGE("RegulatorSetVoltage: failed, ret %d\n", ret);
goto _ERR;
}
uint32_t voltage;
/* Obtain the regulator voltage information. */
ret = RegulatorGetVoltage(handle, &voltage);
if (ret != 0) {
HDF_LOGE("RegulatorGetVoltage: failed, ret %d\n", ret);
goto _ERR;
}
uint32_t status;
/* Obtain the regulator status. */
ret = RegulatorGetStatus(handle, &status);
if (ret != 0) {
HDF_LOGE("RegulatorGetStatus: failed, ret %d\n", ret);
goto _ERR;
}
/* Disable the regulator. */
ret = RegulatorDisable(handle);
if (ret != 0) {
HDF_LOGE("RegulatorDisable: failed, ret %d\n", ret);
goto _ERR;
}
_ERR:
/* Close the regulator device handle. */
RegulatorClose(handle);
}
```
# Regulator<a name="title_REGULATORDevelop"></a>
## Overview<a name="section1_REGULATORDevelop"></a>
The regulator module controls the voltage and current supplies of some devices in the system. In the Hardware Driver Foundation (HDF), the regulator module uses the unified service mode for API adaptation. In this mode, a device service is used as the regulator manager to handle external access requests in a unified manner, which is reflected in the configuration file. The unified service mode applies to the scenario where there are many device objects of the same type, for example, when the regulator has more than 10 controllers. If the independent service mode is used, more device nodes need to be configured and more memory resources will be consumed by services.
**Figure 1** Unified service mode
![image1](figures/unified-service-mode.png)
## Available APIs<a name="section2_REGULATORDevelop"></a>
**RegulatorMethod** structure:
```c
struct RegulatorMethod {
int32_t (*open)(struct RegulatorNode *node);
int32_t (*close)(struct RegulatorNode *node);
int32_t (*release)(struct RegulatorNode *node);
int32_t (*enable)(struct RegulatorNode *node);
int32_t (*disable)(struct RegulatorNode *node);
int32_t (*forceDisable)(struct RegulatorNode *node);
int32_t (*setVoltage)(struct RegulatorNode *node, uint32_t minUv, uint32_t maxUv);
int32_t (*getVoltage)(struct RegulatorNode *node, uint32_t *voltage);
int32_t (*setCurrent)(struct RegulatorNode *node, uint32_t minUa, uint32_t maxUa);
int32_t (*getCurrent)(struct RegulatorNode *node, uint32_t *regCurrent);
int32_t (*getStatus)(struct RegulatorNode *node, uint32_t *status);
};
```
**Table 1** APIs for the members in the RegulatorMethod structure
| Method | Input Parameter | Return Value| Description|
| ------------ | ------------------------------------------- | ------ | ---- |
| open | **node**: structure pointer to the regulator node at the core layer.|HDF_STATUS|Opens a device.|
| close | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Closes a device.|
| release | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Releases a device handle.|
| enable | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Enables a device.|
| disable | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Disables a device.|
| forceDisable | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Forcibly disables a device.|
| setVoltage | **node**: structure pointer to the regulator node at the core layer.<br>**minUv**: minimum voltage to set. It is a uint32_t variable.<br>**maxUv**: maximum voltage to set. It is a uint32_t variable.| HDF_STATUS| Sets the output voltage range.|
| getVoltage | **node**: structure pointer to the regulator node at the core layer.<br>**voltage**: pointer to the output voltage value.| HDF_STATUS| Obtains the voltage.|
| setCurrent | **node**: structure pointer to the regulator node at the core layer.<br>**minUa**: minimum current to set. It is a uint32_t variable.<br>**maxUa**: maximum current to set. It is a uint32_t variable.| HDF_STATUS| Sets the output current range.|
| getCurrent | **node**: structure pointer to the regulator node at the core layer.<br>**regCurrent**: pointer to the output current, which is of the uint32_t type.| HDF_STATUS| Obtains the current.|
| getStatus | **node**: structure pointer to the regulator node at the core layer.<br>**status**: pointer to the output status, which is of the uint32_t type.| HDF_STATUS| Obtains the device status.|
## How to Develop<a name="section3_REGULATORDevelop"></a>
The regulator 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.
2. Configure attribute files.
- Add the **deviceNode** information to the **device_info.hcs** file.
- (Optional) Add the **regulator_config.hcs** file.
3. Instantiate the regulator controller object.
- Initialize **RegulatorNode** members.
- Instantiate **RegulatorMethod**.
>![](../public_sys-resources/icon-note.gif) **NOTE**
>For details, see [Available APIs](#section2_REGULATORDevelop).
4. Debug the driver.
- (Optional) Verify basic functionalities of new drivers. For example, verify the information returned when the driver is loaded and whether data is successfully transmitted.
## Development Example<a name="section4_REGULATORDevelop"></a>
The following uses **regulator_virtual.c** as an example to present the content to be provided by the vendor to implement device functionalities.
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 are 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 the driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
Regulator driver entry reference:
```c
struct HdfDriverEntry g_regulatorDriverEntry = {
.moduleVersion = 1,
.moduleName = "virtual_regulator_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
.Init = VirtualRegulatorInit,
.Release = VirtualRegulatorRelease,
};
// Call HDF_INIT to register the driver entry with the HDF framework.
HDF_INIT(g_regulatorDriverEntry);
```
2. Add **deviceNode** to the **device\_info.hcs** file, and set the device attributes in the **regulator\_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 **RegulatorNode** members at the core layer.
>![](W:\doc\docs\en\device-dev\public_sys-resources\icon-note.gif) **NOTE**
>If there are multiple devices, add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **regulator\_config** file.
- **device\_info.hcs** reference:
```c
root {
device_info {
platform :: host {
hostName = "platform_host";
priority = 50;
device_regulator :: device {
device0 :: deviceNode { // Configure an HDF device node for each regulator controller.
policy = 1; // 2: visible in user mode; 1: visible in kernel mode; 0: no service required.
priority = 50; // Driver startup priority.
permission = 0644; // Permission to create device nodes of the driver.
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
moduleName = "HDF_PLATFORM_REGULATOR_MANAGER";
serviceName = "HDF_PLATFORM_REGULATOR_MANAGER"; // (Mandatory) Unique name of the service published by the driver.
/* (Mandatory) Set the controller private data, which must be same as that in regulator_config.hcs. */
deviceMatchAttr = "hdf_platform_regulator_manager";
}
device1 :: deviceNode {
policy = 0;
priority = 55;
permission = 0644;
moduleName = "linux_regulator_adapter";
deviceMatchAttr = "linux_regulator_adapter";
}
}
}
}
}
```
- **regulator\_config.hcs** reference:
```c
root {
platform {
regulator_config {
match_attr = "linux_regulator_adapter";
template regulator_controller { // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes.
device_num = 1;
name = "";
devName = "regulator_adapter_consumer01";
supplyName = "";
mode = 1;
minUv = 0;
maxUv = 20000;
minUa = 0;
maxUa = 0;
}
controller_0x130d0000 :: regulator_controller {
device_num = 1;
name = "regulator_adapter_1";
devName = "regulator_adapter_consumer01";
supplyName = "virtual-regulator-hdf-adapter";
mode = 1;
minUv = 1000;
maxUv = 50000;
minUa = 0;
maxUa = 0;
}
/* Each regulator controller corresponds to a controller node. If there are multiple regulator controllers, add the corresponding controller nodes one by one.*/
controller_0x130d0001 :: regulator_controller {
device_num = 1;
name = "regulator_adapter_2";
devName = "regulator_adapter_consumer01";
supplyName = "virtual2-regulator-hdf-adapter";
mode = 2;
minUv = 0;
maxUv = 0;
minUa = 1000;
maxUa = 50000;
}
}
}
}
```
3. Initialize the **RegulatorNode** object at the core layer, including initializing the vendor custom structure (passing parameters and data), instantiating **RegulatorMethod** (used to call underlying functions of the driver) in **PinCntlr**, and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**).
- Initializing the vendor custom structure
The **RegulatorNode** structure holds parameters and data for the driver. The HDF obtains the values in **regulator\_config.hcs** using **DeviceResourceIface**.
```c
// RegulatorNode is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct RegulatorNode {
struct RegulatorDesc regulatorInfo;
struct DListHead node;
struct RegulatorMethod *ops;
void *priv;
struct OsalMutex lock;
};
struct RegulatorDesc {
const char *name; /* Regulator name. */
const char *parentName; /* Regulator parent node name. */
struct RegulatorConstraints constraints; /* Regulator constraint information. */
uint32_t minUv; /* Minimum output voltage. */
uint32_t maxUv; /* Maximum output voltage. */
uint32_t minUa; /* Minimum output current. */
uint32_t maxUa; /* Maximum output current. */
uint32_t status; /* Regulator status, which can be on or off. */
int useCount;
int consumerRegNums; /* Number of regulator consumers. */
RegulatorStatusChangecb cb; /* Variable used to notify the regulator status changes. */
};
struct RegulatorConstraints {
uint8_t alwaysOn; /* Whether the regulator is always on. */
uint8_t mode; /* Voltage or current. */
uint32_t minUv; /* Minimum output voltage allowed. */
uint32_t maxUv; /* Maximum output voltage allowed. */
uint32_t minUa; /* Minimum output current allowed. */
uint32_t maxUa; /* Maximum output current allowed. */
};
```
- Instantiating **RegulatorMethod** (other members are initialized by **Init**)
```c
// Example of regulator_virtual.c: Instantiate the hook.
static struct RegulatorMethod g_method = {
.enable = VirtualRegulatorEnable,
.disable = VirtualRegulatorDisable,
.setVoltage = VirtualRegulatorSetVoltage,
.getVoltage = VirtualRegulatorGetVoltage,
.setCurrent = VirtualRegulatorSetCurrent,
.getCurrent = VirtualRegulatorGetCurrent,
.getStatus = VirtualRegulatorGetStatus,
};
```
- **Init** function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
Return value:
**HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.)
**Table 2** HDF\_STATUS
<table><thead align="left"><tr id="row31521027164144"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry1990732428164144p0"><a name="entry1990732428164144p0"></a><a name="entry1990732428164144p0"></a>State</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry2123581292164144p0"><a name="entry2123581292164144p0"></a><a name="entry2123581292164144p0"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row1749271383164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry202330388164144p0"><a name="entry202330388164144p0"></a><a name="entry202330388164144p0"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1717598064164144p0"><a name="entry1717598064164144p0"></a><a name="entry1717598064164144p0"></a>Invalid controller object.</p>
</td>
</tr>
<tr id="row1715354988164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry450625221164144p0"><a name="entry450625221164144p0"></a><a name="entry450625221164144p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry361497788164144p0"><a name="entry361497788164144p0"></a><a name="entry361497788164144p0"></a>Failed to allocate memory.</p>
</td>
</tr>
<tr id="row1202091366164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry370837906164144p0"><a name="entry370837906164144p0"></a><a name="entry370837906164144p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry353311523164144p0"><a name="entry353311523164144p0"></a><a name="entry353311523164144p0"></a>Invalid parameter.</p>
</td>
</tr>
<tr id="row602018308164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1984036607164144p0"><a name="entry1984036607164144p0"></a><a name="entry1984036607164144p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1221756048164144p0"><a name="entry1221756048164144p0"></a><a name="entry1221756048164144p0"></a>I/O error.</p>
</td>
</tr>
<tr id="row47997479164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1220816374164144p0"><a name="entry1220816374164144p0"></a><a name="entry1220816374164144p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1903499126164144p0"><a name="entry1903499126164144p0"></a><a name="entry1903499126164144p0"></a>Initialization successful.</p>
</td>
</tr>
<tr id="row2031856197164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry463793674164144p0"><a name="entry463793674164144p0"></a><a name="entry463793674164144p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry516362874164144p0"><a name="entry516362874164144p0"></a><a name="entry516362874164144p0"></a>Initialization failed.</p>
</td>
</tr>
</tbody>
</table>
Function description:
Initializes the custom structure and **RegulatorNode** members, and adds the regulator controller by calling the **RegulatorNodeAdd** function at the core layer.
```c
static int32_t VirtualRegulatorInit(struct HdfDeviceObject *device)
{
int32_t ret;
const struct DeviceResourceNode *childNode = NULL;
...
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
ret = VirtualRegulatorParseAndInit(device, childNode);// (Mandatory) The implementation is as follows:
...
}
...
}
static int32_t VirtualRegulatorParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
{
int32_t ret;
struct RegulatorNode *regNode = NULL;
(void)device;
regNode = (struct RegulatorNode *)OsalMemCalloc(sizeof(*regNode));// Load the .hcs file.
...
ret = VirtualRegulatorReadHcs(regNode, node);// Read .hcs information.
...
regNode->priv = (void *)node; // Instantiate the node.
regNode->ops = &g_method; // Instantiate OPS.
ret = RegulatorNodeAdd(regNode); // Add the node.
...
}
- **Release** function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
Return value:
Function description:
Releases memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
```c
static void VirtualRegulatorRelease(struct HdfDeviceObject *device)
{
...
RegulatorNodeRemoveAll();// (Mandatory) Call the function at the core layer to release regulator controller devices and services.
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册