# Pin
## Overview
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
**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.
**index**: pin index, which is a uint32_t variable.
**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.
**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.
**index**: pin index, which is a uint32_t variable.
**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.
**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.
**index**: pin index, which is a uint32_t variable.
**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.
**index**: pin index, which is a uint32_t variable.
**funcName**: char double pointer to the pin functionality.| HDF_STATUS| Obtains the pin functionalities.|
## How to Develop
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
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