| result | number | Yes | Authentication result obtained. For details, see [ResultCode](#resultcode8). |
| extraInfo | [AuthResult](#authresult8) | Yes | Extended information, which varies depending on the authentication result.<br>If the authentication is successful, the user authentication token will be returned in **extraInfo**.<br>If the authentication fails, the remaining number of authentication times will be returned in **extraInfo**.<br>If the authenticator is locked, the freeze time will be returned in **extraInfo**.|
| extraInfo | [AuthResult](#authresult8) | Yes | Extended information, which varies depending on the authentication result.<br>If the authentication is successful, the user authentication token will be returned in **extraInfo**.<br>If the authentication fails, the remaining number of authentication times will be returned in **extraInfo**.<br>If the authentication executor is locked, the freeze time will be returned in **extraInfo**.|
**Example**
...
...
@@ -477,8 +477,8 @@ Obtains the tip code information during authentication. This function is optiona
- The pin, also called pin controller, manages pin resources of system on a chip (SoC) vendors and provides the pin multiplexing function.
- The pin module defines a set of common methods for managing pins, including:
- Obtaining or releasing the pin description handle: The kernel compares the pin name passed in with the pin names of each controller in the linked list. If a match is found, a pin description handle is obtained. After the operation on the pin is complete, the pin description handle will be released.
- Setting or obtaining the pull type of a pin: The pull type can be pull-up, pull-down, or floating.
- Setting or obtaining the pull strength of a pin: You can set the pull strength as required.
- Setting or obtaining the functions of a pin to implement pin multiplexing
### Basic Concepts<a name="section3"></a>
Pin, as a software concept, provides APIs for uniformly managing the pins from different SoC vendors, providing the pin multiplexing function, and configuring the electrical features of pins.
- SoC
An SOC is a chip that integrates microprocessors, analog IP cores, digital IP cores, and memory for specific purposes.
- Pin multiplexing
When the number of pins of a chip cannot handle the increasing connection requests, you can set the software registers to make the pins to work in different states.
### Working Principles<a name="section4"></a>
In the HDF, the pin module does not support the user mode and therefore does not need to publish services. It uses the service-free mode in interface adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS that does not distinguish the user mode and the kernel mode. The **DevHandle**, a void pointer, directly points to the kernel mode address of the device object.
The pin module is divided into the following layers:
- Interface layer: provides APIs for obtaining a pin, setting or obtaining the pull type, pull strength, and functions of a pin, and releasing a pin.
- Core layer: provides the capabilities of matching pin resources and adding, removing, and managing pin controllers. The core layer interacts with the adaptation layer by using hooks.
- Adaptation layer: instantiates hooks to implement specific functions.
Currently, the pin module supports only the kernels (LiteOS) of mini and small systems.
## Usage Guidelines<aname="section6"></a>
### When to Use<aname="7"></a>
The pin module is a software concept and is used to manage pin resources. You can set the functions, pull type, and pull strength of pins to implement pin multiplexing.
### Available APIs<a name="section8"></a>
The table below describes the APIs of the pin module. For more details, see API Reference.
>All APIs described in this document can be called only in the kernel space.
### How to Develop<a name="section9"></a>
The figure below shows the process.
**Figure 2** Process of using the pin module<aname="fig2"></a>
![](figures/process-of-using-pin.png"Process of using the pin module")
#### Obtaining the Pin Description Handle
Before performing an operation on a pin, call **PinGet** to obtain the pin description handle. This API returns the pin description handle that matches the input pin name.
```
DevHandle PinGet(const char *pinName);
```
**Table 2** Description of PinGet
<aname="table2"></a>
| Parameter | Description |
| ---------- | ----------------------- |
| pinName | Pointer to the pin name. |
| **Return Value**| **Description** |
| NULL | Failed to obtain the pin description handle.|
| strength | Pointer to the pull strength obtained.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
Example: Obtain the pull strength of a pin.
```
int32_t ret;
uint32_t strengthNum;
/* Obtain the pull strength of the pin. */
ret = PinGetStrength(handle, &strengthNum);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinGetStrength: failed, ret %d\n", ret);
return ret;
}
```
#### Setting the Pin Function
The pin function refers to the pin multiplexing function. The function of each pin is different. For details about the pin functions, see [pin_config.hcs](https://gitee.com/openharmony/device_soc_hisilicon/blob/master/hi3516dv300/sdk_liteos/hdf_config/pin/pin_config.hcs).
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.
### Pin
The pin, also called pin controller, manages pin resources of system on a chip (SoC) vendors and provides the pin multiplexing function.
## Available APIs<a name="section2_PinDevelop"></a>
Pin, as a software concept, provides APIs for uniformly managing the pins from different SoC vendors, providing the pin multiplexing function, and configuring the electrical features of pins.
**PinCntlrMethod**:
- SoC
An SOC is a chip that integrates microprocessors, analog IP cores, digital IP cores, and memory for specific purposes.
- Pin multiplexing
When the number of pins of a chip cannot handle the increasing connection requests, you can set the software registers to make the pins to work in different states.
### Working Principles
In the HDF, the pin module does not support the user mode and therefore does not need to publish services. It uses the service-free mode in interface adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS that does not distinguish the user mode and the kernel mode. The **DevHandle**, a void pointer, directly points to the kernel mode address of the device object.
The pin module is divided into the following layers:
- Interface layer: provides APIs for obtaining a pin, setting or obtaining the pull type, pull strength, and functions of a pin, and releasing a pin.
- Core layer: provides the capabilities of matching pin resources and adding, removing, and managing pin controllers. The core layer interacts with the adaptation layer by using hooks. Adaptation layer: instantiates hooks to implement specific functions.
**Figure 1** Service-free mode
![](figures/service-free-mode.png)
### Constraints
Currently, the pin module supports only the kernels (LiteOS) of mini and small systems.
## Development Guidelines
### When to Use
The pin module is used to manage pin resources. When the devices from SoC vendors interconnect with the HDF, the pin driver needs to be adapted.
### Available APIs
The **PinCntlrMethod** APIs are used to call the functions of the pin driver.
**PinCntlrMethod** definition:
```c
structPinCntlrMethod{
...
...
@@ -25,290 +57,370 @@ struct PinCntlrMethod {
**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.|
| 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.| **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.| **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 function.| -| HDF_STATUS| Sets the pin function.|
| GetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.| **funcName**: char double pointer to the pin function.| HDF_STATUS| Obtains the pin function.|
### How to Develop
## How to Develop<a name="section3_PinDevelop"></a>
The pin module adaptation procedure is as follows:
The pin module adaptation involves the following steps:
- Instantiate the driver entry.
- Configure attribute files.
- Instantiate the core layer APIs.
- Debug the driver.
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
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**.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files.
Generally, the HDF calls the **Init()** function to load the driver. If **Init()** fails to be called, the HDF calls **Release()** to release driver resources and exit.
.moduleName = "hi35xx_pin_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
HDF_INIT(g_hi35xxPinDriverEntry);// Call HDF_INIT to register the driver entry with the HDF.
```
- Add the **deviceNode** information to the **device_info.hcs** file.
- (Optional) Add the **pin_config.hcs** file.
2. Configure attribute files.
- Add the device node description to the **vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
```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";
}
......
}
}
}
}
```
- Add the **pin_config.hcs** file.
Configure the device attributes in the **device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/pin/pin_config.hcs** file. The parameters are set as follows:
```c
root{
platform{
pin_config_hi35xx{
templatepin_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="";
templatepin_desc{
pinName="";// (Mandatory) Name of the pin.
init=0;// (Mandatory) Default value of the register.
F0="";// (Mandatory) Function 0.
F1="";// Function 1.
F2="";// Function 2.
F3="";// Function 3.
F4="";// Function 4.
F5="";// Function 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";
}
......// Correspond to the pins of the pin controller. Add pins according to actual situation.
}
...// Each pin controller corresponds to a controller node. If there are multiple pin controllers, add the corresponding controller nodes one by one.
}
}
}
```
3. Instantiate the pin controller object.
- Initialize the **PinCntlr** object.
- Instantiate **PinCntlrMethod** in the **PinCntlr** object.
Call **Hi35xxPinCntlrInit** to initialize the **PinCntlr** members.
```c
struct Hi35xxPinDesc {
// Pin name.
const char *pinName;
// Initial value.
uint32_t init;
// Index of the pin.
uint32_t index;
// Pull type of the pin.
int32_t pullType;
// Pull strength of the pin.
int32_t strength;
// Array of pin function names.
const char *func[HI35XX_PIN_FUNC_MAX];
};
>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.
struct Hi35xxPinCntlr {
// Pin controller.
struct PinCntlr cntlr;
// Pointer to the pin description structure.
struct Hi35xxPinDesc *desc;
// Register mapping address.
volatile unsigned char *regBase;
// ID of the pin controller.
uint16_t number;
// Start address of the register physical base addresses.
uint32_t regStartBasePhy;
// Register bit width.
uint32_t regSize;
// Number of pins.
uint32_t pinCount;
};
// 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; // Node in the linked list.
## Development Example<a name="section4_PinDevelop"></a>
- Instantiate the callback structure **PinCntlrMethod** in **PinCntlr**. Other members are initialized by using the **Init()** function.
The following uses **pin_hi35xx.c** as an example to present the content to be provided by the vendor to implement device functionalities.
```c
// The members of the PinCntlrMethod structure are all callbacks. Vendors need to implement the corresponding functions according to Table 1.
static struct PinCntlrMethod g_method = {
.SetPinPull = Hi35xxPinSetPull, // Set the pull type.
.GetPinPull = Hi35xxPinGetPull, // Obtains the pull type.
.SetPinStrength = Hi35xxPinSetStrength, // Set the pull strength.
.GetPinStrength = Hi35xxPinGetStrength, // Obtains the pull strength.
.SetPinFunc = Hi35xxPinSetFunc, // Set the pin functions.
.GetPinFunc = Hi35xxPinGetFunc, // Obtain the pin 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 are collected to form a segment address space similar to an array for the upper layer to invoke.
-**Init()** function
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.
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Pin driver entry reference:
Return value:
**HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.)
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.
>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.
staticstructPinCntlrMethodg_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**.)
<tdclass="cellrowborder"valign="top"width="50%"headers="mcps1.1.3.1.2 "><pid="entry361497788164144p0"><aname="entry361497788164144p0"></a><aname="entry361497788164144p0"></a>Failed to allocate memory</p>
Initializes the custom structure and **PinCntlr** members, and connects to the pin controller by calling the **PinCntlrAdd** function at the core layer.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
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.
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.
ret = drsOps->GetUint16(device->property, "number", &number, 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read cntlr number failed", __func__);
return;
}
cntlr = PinCntlrGetByNumber(number); // Obtain the pin controller based on the controller ID.
PinCntlrRemove(cntlr);
hi35xx = (struct Hi35xxPinCntlr *)cntlr;
if (hi35xx != NULL) {
if (hi35xx->regBase != NULL) {
OsalIoUnmap((void *)hi35xx->regBase);
}
OsalMemFree(hi35xx);
}
}
```
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.