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

!5181 【翻译完成】#I57QRA

Merge pull request !5181 from Annie_wang/PR3940A
......@@ -28,7 +28,7 @@ struct GpioMethod {
int32_t (*unsetIrq)(struct GpioCntlr *cntlr, uint16_t local);
int32_t (*enableIrq)(struct GpioCntlr *cntlr, uint16_t local);
int32_t (*disableIrq)(struct GpioCntlr *cntlr, uint16_t local);
}
};
```
**Table 1** Description of the callback functions in GpioMethod
......@@ -63,7 +63,7 @@ The GPIO module adaptation involves the following steps:
- Initialize **GpioCntlr**.
- Instantiate **GpioMethod** in the **GpioCntlr** object.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/> For details about the callbacks in **GpioMethod**, see [Available APIs](#available-apis).
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/> For details about the functions in **GpioMethod**, see [Available APIs](#available-apis).
4. Debug the driver.
......@@ -72,7 +72,7 @@ The GPIO module adaptation involves the following steps:
## Development Example
The following uses **gpio_hi35xx.c** as an example to present the information to be provided by the vendor for implementing device functions.
The following uses **gpio_hi35xx.c** as an example to present the information required for implementing device functions.
1. Instantiate the driver entry.
......@@ -143,7 +143,7 @@ The following uses **gpio_hi35xx.c** as an example to present the information to
3. Initialize the **GpioCntlr** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Init** and **Release**) to instantiate **GpioMethod** in **GpioCntlr** (so that the underlying driver functions can be called).
- Defining a custom structure
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **gpio_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the GPIO group number and the number of pins, to the **GpioCntlr** object at the core layer.
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **gpio_config.hcs** file to initialize the members in the custom structure and pass important parameters, such as the GPIO group number and the number of pins, to the **GpioCntlr** object at the core layer.
```
......
......@@ -235,7 +235,7 @@ The HDMI module adaptation involves the following steps:
> ![](../public_sys-resources/icon-note.gif) **NOTE**
>
>
> To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **hdmi_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the device number and bus number, to the **HdmiCntlr** object at the core layer.
> To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **hdmi_config.hcs** file to initialize the members in the custom structure and pass important parameters, such as the device number and bus number, to the **HdmiCntlr** object at the core layer.
```c
struct HdmiAdapterHost {
......
# MIPI CSI<a name="title_MIPI_CSIDes"></a>
# MIPI CSI
## Overview<a name="section1_MIPI_CSIDes"></a>
## Overview
Defined by the Mobile Industry Processor Interface (MIPI) Alliance, the Camera Serial Interface (CSI) is a specification that allows data to be transmitted from the camera to the host processor on mobile platforms. As the second release, the MIPI CSI-2 consists of the application layer, protocol layer, and physical layer. It supports a maximum of four-lane data transmission and a single-lane transmission rate of 1 Gbit/s.
The physical layer supports the high speed (HS) and low power (LP) modes. Using low-voltage differential signaling (LVDS), the HS mode delivers 80 Mbit/s to 1 Gbit/s transmission speed but high power consumption. The unidirectional LP mode provides lower power consumption but lower transmission speed (< 10 Mbit/s). The blend of the two modes ensures high-speed transmission of massive data (such as images) and minimized power consumption when less data is transmitted.
The physical layer supports the high speed (HS) and low speed (LS) modes. Using low-voltage differential signaling (LVDS), the HS mode delivers 80 Mbit/s to 1 Gbit/s transmission speed but high power consumption. The unidirectional LS mode provides lower power consumption but lower transmission speed (< 10 Mbit/s). The blend of the two modes ensures high-speed transmission of massive data (such as images) and minimized power consumption when less data is transmitted.
The figure below shows a simplified CSI. The D-PHY transmits data by using one pair of source-synchronized differential clocks and one to four pairs of differential data lanes. Data is transmitted in Double Data Rate (DDR) mode, that is, data is transmitted on both the rising and falling edges of the clock.
**Figure 1** CSI TX and RX interfaces<a name="fig1_MIPI_CSIDes"></a>
![](figures/CSI_TX-RX_interface.png)
**Figure 1** CSI TX and RX interfaces
![](figures/CSI_TX-RX_interface.png)
### ComboDevAttr Structure<a name="section1.1_MIPI_CSIDes"></a>
### ComboDevAttr Structure
**Table 1** ComboDevAttr structure
......@@ -26,7 +27,7 @@ The figure below shows a simplified CSI. The D-PHY transmits data by using one p
| MIPIAttr | Attributes of the MIPI device. |
| lvdsAttr | Attributes of the LVDS, sub-LVDS, or HiSPi device. |
### ExtDataType Structure<a name="section1.2_MIPI_CSIDes"></a>
### ExtDataType Structure
**Table 2** ExtDataType structure
......@@ -39,33 +40,34 @@ The figure below shows a simplified CSI. The D-PHY transmits data by using one p
| extDataBitWidth | Bit depth of an image. |
| extDataType | Pointer to the YUV, raw data format, and bit depth.|
### Available APIs<a name="section1.3_MIPI_CSIDes"></a>
### Available APIs
**Table 3** MIPI CSI APIs
<a name="table3_MIPI_CSIDes"></a>
| Category| API|
| Category| API|
| -------- | -------- |
| Opening or closing the MIPI CSI controller operation handle| **MipiCsiOpen**: opens the MIPI CSI controller operation handle.<br>**MipiCsiClose**: closes the MIPI CSI controller operation handle.|
| Setting MIPI CSI parameters| **MipiCsiSetComboDevAttr**: sets parameters of the MIPI, CMOS, or LVDS camera to the controller. The parameters include the working mode, image area, image depth, data rate, and physical channel.<br>**MipiCsiSetExtDataType** (optional): sets the YUV and RAW data formats and bit depths.<br>**MipiCsiSetHsMode**: sets the MIPI RX lane distribution. Set the mode based on the hardware connection.<br>**MipiCsiSetPhyCmvmode**: sets the common-mode voltage (CMV) mode.|
| Resetting a sensor or deasserting the reset of a sensor| **MipiCsiResetSensor**: resets a sensor.<br>**MipiCsiUnresetSensor**: deasserts the reset of a sensor.|
| Resetting the MIPI RX or deasserting the reset of the MIPI RX| **MipiCsiResetRx**: resets the MIPI&amp;nbsp;RX. The value of **enSnsType** varies depending on the value of **s32WorkingViNum**.<br>**MipiCsiUnresetRx**: deasserts the reset on the MIPI&amp;nbsp;RX.|
| Enabling or disabling the MIPI clock| **MipiCsiEnableClock**: enables the MIPI clock. The **enSnsType** passed by the upper-layer function during electrophoresis determines whether MIPI or LVDS is used.<br>**MipiCsiDisableClock**: disables the MIPI clock.|
| Enabling or disabling the MIPI sensor clock| **MipiCsiEnableSensorClock**: enables the MIPI sensor clock.<br>**MipiCsiDisableSensorClock**: disables the MIPI sensor clock.|
| Opening or closing the MIPI CSI controller operation handle| **MipiCsiOpen**: opens the MIPI CSI controller operation handle.<br>**MipiCsiClose**: closes the MIPI CSI controller operation handle.|
| Setting MIPI CSI attributes | **MipiCsiSetComboDevAttr**: sets attributes of the MIPI, CMOS, or LVDS camera to the controller. The attributes include the working mode, image area, image depth, data rate, and physical channel.<br>**MipiCsiSetExtDataType** (optional): sets the YUV and RAW data formats and bit depths.<br>**MipiCsiSetHsMode**: sets the MIPI RX lane distribution. Set the mode based on the hardware connection.<br>**MipiCsiSetPhyCmvmode**: sets the common-mode voltage (CMV) mode. |
| Resetting a sensor or deasserting the reset of a sensor| **MipiCsiResetSensor**: resets a sensor.<br>**MipiCsiUnresetSensor**: deasserts the reset of a sensor.|
| Resetting the MIPI RX or deasserting the reset of the MIPI RX| **MipiCsiResetRx**: resets the MIPI&amp;nbsp;RX. The value of **enSnsType** varies depending on the value of **s32WorkingViNum**.<br>**MipiCsiUnresetRx**: deasserts the reset on the MIPI&amp;nbsp;RX.|
| Enabling or disabling the MIPI clock| **MipiCsiEnableClock**: enables the MIPI clock. The **enSnsType** passed by the upper-layer function during electrophoresis determines whether MIPI or LVDS is used.<br>**MipiCsiDisableClock**: disables the MIPI clock.|
| Enabling or disabling the MIPI sensor clock| **MipiCsiEnableSensorClock**: enables the MIPI sensor clock.<br>**MipiCsiDisableSensorClock**: disables the MIPI sensor clock.|
## Usage Guidelines<a name="section2_MIPI_CSIDes"></a>
## Usage Guidelines
### How to Use<a name="section2.1_MIPI_CSIDes"></a>
### How to Use
The figure below illustrates how to use the APIs.
The figure below illustrates the general development process.
**Figure 2** Using MIPI CSI driver APIs
![](figures/using-MIPI-CSI-process.png)
### Opening the MIPI CSI Controller Operation Handle<a name="section2.2_MIPI_CSIDes"></a>
### Opening a MIPI CSI Controller Operation Handle
Before starting MIPI CSI communication, call **MipiCsiOpen** to open the MIPI CSI device handle. This function returns the MIPI CSI device handle with the specified lane ID.
......@@ -81,10 +83,10 @@ DevHandle MipiCsiOpen(uint8_t id);
| ---------- | ----------------------------------------------- |
| id | MIPI CSI lane ID. |
| **Return Value**| **Description** |
| NULL | The operation fails. |
| Device handle | MIPI CSI device handle with the specified lane ID. The data type is **DevHandle**.|
| NULL | The operation failed. |
| Device handle | The operation is successful. The MIPI CSI device handle with the specified lane ID is returned. The data type is **DevHandle**. |
For example, open the controller operation handle for MIPI CSI lane 0:
For example, open the controller operation handle of MIPI CSI lane 0:
```c
DevHandle mipiCsiHandle = NULL; /* Device handle */
......@@ -98,9 +100,9 @@ if (MipiCsiHandle == NULL) {
}
```
### Setting MIPI CSI Parameters<a name="section2.3_MIPI_CSIDes"></a>
### Setting MIPI CSI Attributes
- Set MIPI CSI parameters.
- Set MIPI CSI attributes.
```c
int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr *pAttr);
......@@ -116,7 +118,7 @@ if (MipiCsiHandle == NULL) {
| pAttr | Pointer to the MIPI CSI structure.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -155,7 +157,7 @@ if (MipiCsiHandle == NULL) {
| dataType | Pointer to the YUV, raw data format, and bit depth.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -195,7 +197,7 @@ if (MipiCsiHandle == NULL) {
| laneDivideMode | Lane mode. |
| **Return Value** | **Description**|
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -228,7 +230,7 @@ if (MipiCsiHandle == NULL) {
| devno | Device number. |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -247,7 +249,7 @@ if (MipiCsiHandle == NULL) {
}
```
### Resetting a Sensor or Deasserting the Reset of a Sensor<a name="section2.4_MIPI_CSIDes"></a>
### Resetting a Sensor or Deasserting the Reset of a Sensor
- Reset a sensor.
......@@ -262,10 +264,10 @@ if (MipiCsiHandle == NULL) {
| Parameter | Description |
| -------------- | ------------------------------------------------ |
| handle | Controller operation handle. |
| snsResetSource | Sensor's reset signal cable number, which is called reset source of the sensor in software.|
| snsResetSource | Sensor's reset signal cable number, which is called "sensor reset source" in software. |
| **Return Value** | **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -294,10 +296,10 @@ if (MipiCsiHandle == NULL) {
| Parameter | Description |
| -------------- | ------------------------------------------------ |
| handle | Controller operation handle. |
| snsResetSource | Sensor's reset signal cable number, which is called reset source of the sensor in software.|
| snsResetSource | Sensor's reset signal cable number, which is called "sensor reset source" in software. |
| **Return Value** | **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -313,7 +315,7 @@ if (MipiCsiHandle == NULL) {
}
```
### Resetting the MIPI RX or Deasserting the Reset of the MIPI RX<a name="section2.5_MIPI_CSIDes"></a>
### Resetting the MIPI RX or Deasserting the Reset of the MIPI RX
- Reset the MIPI RX.
......@@ -331,7 +333,7 @@ if (MipiCsiHandle == NULL) {
| comboDev | MIPI RX or LVDS channel number.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -363,7 +365,7 @@ if (MipiCsiHandle == NULL) {
| comboDev | MIPI RX or LVDS channel number.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -379,7 +381,7 @@ if (MipiCsiHandle == NULL) {
}
```
### Enabling or Disabling the MIPI Clock<a name="section2.6_MIPI_CSIDes"></a>
### Enabling or Disabling the MIPI Clock
- Enable the MIPI clock.
......@@ -397,7 +399,7 @@ if (MipiCsiHandle == NULL) {
| comboDev | Channel number. |
| **Return Value**| **Description**|
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -429,7 +431,7 @@ if (MipiCsiHandle == NULL) {
| comboDev | Channel number. |
| **Return Value**| **Description**|
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -445,7 +447,7 @@ if (MipiCsiHandle == NULL) {
}
```
### Enabling or Disabling the MIPI Sensor Clock<a name="section2.7_MIPI_CSIDes"></a>
### Enabling or Disabling the MIPI Sensor Clock
- Enable the MIPI sensor clock.
......@@ -463,7 +465,7 @@ if (MipiCsiHandle == NULL) {
| snsClkSource | Sensor's clock signal cable number, which is called clock source of the sensor in software.|
| **Return Value** | **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -495,7 +497,7 @@ if (MipiCsiHandle == NULL) {
| snsClkSource | Sensor's clock signal cable number, which is called clock source of the sensor in software.|
| **Return Value** | **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
| Negative value | The operation failed. |
```c
int32_t ret;
......@@ -511,9 +513,9 @@ if (MipiCsiHandle == NULL) {
}
```
### Closing a MIPI CSI Controller Operation Handle<a name="section2.8_MIPI_CSIDes"></a>
### Closing a MIPI CSI Controller Operation Handle
After the MIPI CSI communication, close the MIPI CSI controller handle by calling the following function:
Call **MipiCsiClose()** to close the MIPI CSI controller handle after the MIPI CSI communication is complete.
```c
void MipiCsiClose(DevHandle handle);
......@@ -533,7 +535,7 @@ This function releases the resources requested by **MipiCsiOpen**.
MipiCsiClose(MIPIHandle); /* Close the operation handle of the MIPI CSI controller. */
```
## Development Example<a name="section3_MIPI_CSIDes"></a>
## Example
The sample code is as follows:
......
# MIPI CSI<a name="EN-US_TOPIC_0000001198067744"></a>
# MIPI CSI
## Overview<a name="section72226945170128"></a>
## Overview
Defined by the Mobile Industry Processor Interface \(MIPI\) Alliance, the Camera Serial Interface \(CSI\) is a specification that allows data to be transmitted from the camera to the host processor on mobile platforms. In the Hardware Driver Foundation \(HDF\), the MIPI CSI module uses the service-free mode for API 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. In the service-free mode, DevHandle \(a void pointer\) directly points to the kernel-mode address of the device object.
The Camera Serial Interface (CSI), defined by the Mobile Industry Processor Interface (MIPI) Alliance, allows data to be transmitted from the camera to the host processor on mobile platforms. In the Hardware Driver Foundation (HDF), the MIPI CSI module uses the service-free mode for API adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the operating system (OS) 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<a name="fig260692723120"></a>
**Figure 1** Service-free mode
![](figures/service-free-mode.png "Service-free mode")
![image1](figures/service-free-mode.png "service-free-mode")
## Available APIs<a name="section735525713405"></a>
## Available APIs
MipiCsiCntlrMethod:
**MipiCsiCntlrMethod**:
```
```c
struct MipiCsiCntlrMethod {
int32_t (*setComboDevAttr)(struct MipiCsiCntlr *cntlr, ComboDevAttr *pAttr);
int32_t (*setPhyCmvmode)(struct MipiCsiCntlr *cntlr, uint8_t devno, PhyCmvMode cmvMode);
......@@ -28,466 +28,294 @@ struct MipiCsiCntlrMethod {
int32_t (*unresetSensor)(struct MipiCsiCntlr *cntlr, uint8_t snsResetSource);
};
```
**Table 1** Callbacks for the members in the MipiCsiCntlrMethod structure
<a name="table1233500677170128"></a>
<table><thead align="left"><tr id="row1000451054170128"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="entry1111988081170128p0"><a name="entry1111988081170128p0"></a><a name="entry1111988081170128p0"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="entry1314377643170128p0"><a name="entry1314377643170128p0"></a><a name="entry1314377643170128p0"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="entry102571833170128p0"><a name="entry102571833170128p0"></a><a name="entry102571833170128p0"></a>Output Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="entry259883708170128p0"><a name="entry259883708170128p0"></a><a name="entry259883708170128p0"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="entry1719007141170128p0"><a name="entry1719007141170128p0"></a><a name="entry1719007141170128p0"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row893348241170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry2092857420170128p0"><a name="entry2092857420170128p0"></a><a name="entry2092857420170128p0"></a>setComboDevAttr</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p155578927170128"><a name="p155578927170128"></a><a name="p155578927170128"></a><strong id="b2983104693117"><a name="b2983104693117"></a><a name="b2983104693117"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p534134719170128"><a name="p534134719170128"></a><a name="p534134719170128"></a><strong id="b717683263220"><a name="b717683263220"></a><a name="b717683263220"></a>pAttr</strong>: structure pointer to the configuration structure of the MIPI CSI.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry1300850044170128p0"><a name="entry1300850044170128p0"></a><a name="entry1300850044170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry1079550609170128p0"><a name="entry1079550609170128p0"></a><a name="entry1079550609170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1104973652170128p0"><a name="entry1104973652170128p0"></a><a name="entry1104973652170128p0"></a>Sets the MIPI-CSI configuration.</p>
</td>
</tr>
<tr id="row1236584443170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry1263277119170128p0"><a name="entry1263277119170128p0"></a><a name="entry1263277119170128p0"></a>setPhyCmvmode</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p548503413170128"><a name="p548503413170128"></a><a name="p548503413170128"></a><strong id="b33316314348"><a name="b33316314348"></a><a name="b33316314348"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p1389106408170128"><a name="p1389106408170128"></a><a name="p1389106408170128"></a><strong id="b7288183093611"><a name="b7288183093611"></a><a name="b7288183093611"></a>devno</strong>: Device ID, which is of the uint8_t type.</p>
<p id="p118314402170128"><a name="p118314402170128"></a><a name="p118314402170128"></a><strong id="b1347113393714"><a name="b1347113393714"></a><a name="b1347113393714"></a>cmvMode</strong>: common-mode voltage (CMV) mode.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry886884421170128p0"><a name="entry886884421170128p0"></a><a name="entry886884421170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry1542733203170128p0"><a name="entry1542733203170128p0"></a><a name="entry1542733203170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1506663070170128p0"><a name="entry1506663070170128p0"></a><a name="entry1506663070170128p0"></a>Sets the CMV mode.</p>
</td>
</tr>
<tr id="row1486148936170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry1589217404170128p0"><a name="entry1589217404170128p0"></a><a name="entry1589217404170128p0"></a>setExtDataType</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p114389566170128"><a name="p114389566170128"></a><a name="p114389566170128"></a><strong id="b34053117344"><a name="b34053117344"></a><a name="b34053117344"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p996608377170128"><a name="p996608377170128"></a><a name="p996608377170128"></a><strong id="b784685684412"><a name="b784685684412"></a><a name="b784685684412"></a>dataType</strong>: structure pointer to the data that defines the YUV, original data formats, and bit depth.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry378080489170128p0"><a name="entry378080489170128p0"></a><a name="entry378080489170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry851136224170128p0"><a name="entry851136224170128p0"></a><a name="entry851136224170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1309676064170128p0"><a name="entry1309676064170128p0"></a><a name="entry1309676064170128p0"></a>Sets the YUV, RAW data format, and bit depth.</p>
</td>
</tr>
<tr id="row692364909170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry1017488702170128p0"><a name="entry1017488702170128p0"></a><a name="entry1017488702170128p0"></a>setHsMode</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1054266120170128"><a name="p1054266120170128"></a><a name="p1054266120170128"></a><strong id="b144183117349"><a name="b144183117349"></a><a name="b144183117349"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p1574674418170128"><a name="p1574674418170128"></a><a name="p1574674418170128"></a><strong id="b18748194155516"><a name="b18748194155516"></a><a name="b18748194155516"></a>laneDivideMode</strong>: lane mode.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry1749069145170128p0"><a name="entry1749069145170128p0"></a><a name="entry1749069145170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry1237801346170128p0"><a name="entry1237801346170128p0"></a><a name="entry1237801346170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1643965522170128p0"><a name="entry1643965522170128p0"></a><a name="entry1643965522170128p0"></a>Sets the MIPI RX lane distribution.</p>
</td>
</tr>
<tr id="row1437392211170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry80806261170128p0"><a name="entry80806261170128p0"></a><a name="entry80806261170128p0"></a>enableClock</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p867235167170128"><a name="p867235167170128"></a><a name="p867235167170128"></a><strong id="b94263116342"><a name="b94263116342"></a><a name="b94263116342"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p1770663973170128"><a name="p1770663973170128"></a><a name="p1770663973170128"></a><strong id="b1342116531004"><a name="b1342116531004"></a><a name="b1342116531004"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry836736200170128p0"><a name="entry836736200170128p0"></a><a name="entry836736200170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry918324954170128p0"><a name="entry918324954170128p0"></a><a name="entry918324954170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry373275246170128p0"><a name="entry373275246170128p0"></a><a name="entry373275246170128p0"></a>Enables the MIPI clock.</p>
</td>
</tr>
<tr id="row1944617165170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry1879109927170128p0"><a name="entry1879109927170128p0"></a><a name="entry1879109927170128p0"></a>disableClock</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p252627163170128"><a name="p252627163170128"></a><a name="p252627163170128"></a><strong id="b343103114343"><a name="b343103114343"></a><a name="b343103114343"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p573650189170128"><a name="p573650189170128"></a><a name="p573650189170128"></a><strong id="b1747970172618"><a name="b1747970172618"></a><a name="b1747970172618"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry8107921170128p0"><a name="entry8107921170128p0"></a><a name="entry8107921170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry349207958170128p0"><a name="entry349207958170128p0"></a><a name="entry349207958170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry693552037170128p0"><a name="entry693552037170128p0"></a><a name="entry693552037170128p0"></a>Disables the MIPI clock.</p>
</td>
</tr>
<tr id="row168452313170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry536818735170128p0"><a name="entry536818735170128p0"></a><a name="entry536818735170128p0"></a>resetRx</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1214231503170128"><a name="p1214231503170128"></a><a name="p1214231503170128"></a><strong id="b1043031153417"><a name="b1043031153417"></a><a name="b1043031153417"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p104793304170128"><a name="p104793304170128"></a><a name="p104793304170128"></a><strong id="b597920533269"><a name="b597920533269"></a><a name="b597920533269"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry349755171170128p0"><a name="entry349755171170128p0"></a><a name="entry349755171170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry608378681170128p0"><a name="entry608378681170128p0"></a><a name="entry608378681170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1692819512170128p0"><a name="entry1692819512170128p0"></a><a name="entry1692819512170128p0"></a>Resets the MIPI RX.</p>
</td>
</tr>
<tr id="row812174477170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry677771062170128p0"><a name="entry677771062170128p0"></a><a name="entry677771062170128p0"></a>unresetRx</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1883220887170128"><a name="p1883220887170128"></a><a name="p1883220887170128"></a><strong id="b1202156153016"><a name="b1202156153016"></a><a name="b1202156153016"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p114324757170128"><a name="p114324757170128"></a><a name="p114324757170128"></a><strong id="b105520153110"><a name="b105520153110"></a><a name="b105520153110"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry2088687179170128p0"><a name="entry2088687179170128p0"></a><a name="entry2088687179170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry250678538170128p0"><a name="entry250678538170128p0"></a><a name="entry250678538170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1714667992170128p0"><a name="entry1714667992170128p0"></a><a name="entry1714667992170128p0"></a>Deasserts the reset of the MIPI RX.</p>
</td>
</tr>
<tr id="row1282919412170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry204916079170128p0"><a name="entry204916079170128p0"></a><a name="entry204916079170128p0"></a>enableSensorClock</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p217879421170128"><a name="p217879421170128"></a><a name="p217879421170128"></a><strong id="b197181237203211"><a name="b197181237203211"></a><a name="b197181237203211"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p2098908158170128"><a name="p2098908158170128"></a><a name="p2098908158170128"></a><strong id="b12861154993218"><a name="b12861154993218"></a><a name="b12861154993218"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry1290595383170128p0"><a name="entry1290595383170128p0"></a><a name="entry1290595383170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry1313850176170128p0"><a name="entry1313850176170128p0"></a><a name="entry1313850176170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry384362703170128p0"><a name="entry384362703170128p0"></a><a name="entry384362703170128p0"></a>Enables the MIPI sensor clock.</p>
</td>
</tr>
<tr id="row1992432516170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry980444503170128p0"><a name="entry980444503170128p0"></a><a name="entry980444503170128p0"></a>disableSensorClock</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1996780281170128"><a name="p1996780281170128"></a><a name="p1996780281170128"></a><strong id="b4445316347"><a name="b4445316347"></a><a name="b4445316347"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p2021170726170128"><a name="p2021170726170128"></a><a name="p2021170726170128"></a><strong id="b17971423820"><a name="b17971423820"></a><a name="b17971423820"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry1694413990170128p0"><a name="entry1694413990170128p0"></a><a name="entry1694413990170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry1647081928170128p0"><a name="entry1647081928170128p0"></a><a name="entry1647081928170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry2011696236170128p0"><a name="entry2011696236170128p0"></a><a name="entry2011696236170128p0"></a>Disables the MIPI sensor clock.</p>
</td>
</tr>
<tr id="row1739370133170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry386036597170128p0"><a name="entry386036597170128p0"></a><a name="entry386036597170128p0"></a>resetSensor</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1065048089170128"><a name="p1065048089170128"></a><a name="p1065048089170128"></a><strong id="b19451631183417"><a name="b19451631183417"></a><a name="b19451631183417"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p998202090170128"><a name="p998202090170128"></a><a name="p998202090170128"></a><strong id="b10443111911384"><a name="b10443111911384"></a><a name="b10443111911384"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry173182567170128p0"><a name="entry173182567170128p0"></a><a name="entry173182567170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry879245456170128p0"><a name="entry879245456170128p0"></a><a name="entry879245456170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry944835652170128p0"><a name="entry944835652170128p0"></a><a name="entry944835652170128p0"></a>Resets the sensor.</p>
</td>
</tr>
<tr id="row1197566339170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry363281016170128p0"><a name="entry363281016170128p0"></a><a name="entry363281016170128p0"></a>unresetSensor</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p416483731170128"><a name="p416483731170128"></a><a name="p416483731170128"></a><strong id="b178488417385"><a name="b178488417385"></a><a name="b178488417385"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p1988272362170128"><a name="p1988272362170128"></a><a name="p1988272362170128"></a><strong id="b6353246183818"><a name="b6353246183818"></a><a name="b6353246183818"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry1658055665170128p0"><a name="entry1658055665170128p0"></a><a name="entry1658055665170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry2142771023170128p0"><a name="entry2142771023170128p0"></a><a name="entry2142771023170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry791107803170128p0"><a name="entry791107803170128p0"></a><a name="entry791107803170128p0"></a>Deasserts the reset of a sensor.</p>
</td>
</tr>
</tbody>
</table>
## How to Develop<a name="section378858277170128"></a>
**Table 1** Description of the callback functions in the MipiCsiCntlrMethod structure
| Function | Input Parameter | Output Parameter| Return Value | Description |
| ------------------ | ------------------------------------------------------------ | ---- | ------------------ | -------------------------- |
| setComboDevAttr | **cntlr**: structure pointer to the MIPI CSI controller.<br>**pAttr**: structure pointer to the MIPI CSI configuration.| – | HDF_STATUS| Sets MIPI CSI attributes. |
| setPhyCmvmode | **cntlr**: structure pointer to the MIPI CSI controller.<br>**devno**: Device number, which is of the uint8_t type.<br>**cmvMode**: common-mode voltage (CMV) mode to set.| – | HDF_STATUS| Sets the CMV mode. |
| setExtDataType | **cntlr**: structure pointer to the MIPI CSI controller.<br>**dataType**: structure pointer to the data that defines the YUV, original data formats, and bit depth.| – | HDF_STATUS| Sets the YUV, RAW data format, and bit depth.|
| setHsMode | **cntlr**: structure pointer to the MIPI CSI controller.<br>**laneDivideMode**: lane mode.| – | HDF_STATUS| Sets the MIPI RX lane distribution. |
| enableClock | **cntlr**: structure pointer to the MIPI CSI controller.<br>**comboDev**: channel number, which is of the uint8_t type.| – | HDF_STATUS| Enables the MIPI clock. |
| disableClock | **cntlr**: structure pointer to the MIPI CSI controller.<br>**comboDev**: channel number, which is of the uint8_t type.| – | HDF_STATUS| Disables the MIPI clock. |
| resetRx | **cntlr**: structure pointer to the MIPI CSI controller.<br>**comboDev**: channel number, which is of the uint8_t type.| – | HDF_STATUS| Resets the MIPI RX. |
| unresetRx | **cntlr**: structure pointer to the MIPI CSI controller.<br>**comboDev**: channel number, which is of the uint8_t type.| – | HDF_STATUS| Deasserts the reset of the MIPI RX. |
| enableSensorClock | **cntlr**: structure pointer to the MIPI CSI controller.<br>**snsClkSource**: number of the clock signal cable of the sensor, which is of the uint8_t type.| – | HDF_STATUS| Enables the MIPI sensor clock. |
| disableSensorClock | **cntlr**: structure pointer to the MIPI CSI controller.<br>**snsClkSource**: number of the clock signal cable of the sensor, which is of the uint8_t type.| – | HDF_STATUS| Disables the MIPI sensor clock. |
| resetSensor | **cntlr**: structure pointer to the MIPI CSI controller.<br>**snsClkSource**: number of the clock signal cable of the sensor, which is of the uint8_t type.| – | HDF_STATUS| Resets a sensor. |
| unresetSensor | **cntlr**: structure pointer to the MIPI CSI controller.<br>**snsClkSource**: number of the clock signal cable of the sensor, which is of the uint8_t type.| – | HDF_STATUS| Deasserts the reset of a sensor. |
## How to Develop
The MIPI CSI 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 **mipicsi\_config.hcs** file.
3. Instantiate the MIPI CSI controller object.
- Initialize **MipiCsiCntlr**.
- Instantiate **MipiCsiCntlrMethod** in the **MipiCsiCntlr** object.
For details, see [Available APIs](#available-apis).
4. \(Optional\) Debug the driver.
For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether data is successfully transmitted.
## Development Example<a name="section2049027816170128"></a>
The following uses **mipi\_rx\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions.
1. Generally, you need to configure the device attributes in **busxx\_config.hcs** and add the **deviceNode** information to the **device\_info.hcs** file. The device attribute values are closely related to the default values or value range of the **MipiCsiCntlr** members at the core layer. The **deviceNode** information is related to the driver entry registration.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>In this example, the MIPI controller attributes are defined in the source file. If required, add the **deviceMatchAttr** information to **deviceNode** in the **device\_info** file and add the** mipicsi\_config.hcs** file.
**device\_info.hcs** configuration reference:
```
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_mipi_csi:: device {
device0 :: deviceNode {
policy = 0;
priority = 160;
permission = 0644;
moduleName = "HDF_MIPI_RX"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry.
serviceName = "HDF_MIPI_RX";// (Mandatory) Unique name of the service published by the driver.
}
}
}
}
}
```
2. 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**. The function pointer members of the **HdfDriverEntry** structure are filled by the vendors' operation functions. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
MIPI CSI driver entry reference:
```
struct HdfDriverEntry g_mipiCsiDriverEntry = {
.moduleVersion = 1,
.Init = Hi35xxMipiCsiInit, // See the Init function.
.Release = Hi35xxMipiCsiRelease, //See the Release function.
.moduleName = "HDF_MIPI_RX", // (Mandatory) The value must be the same as that in the device_info.hcs file.
};
HDF_INIT(g_mipiCsiDriverEntry); // Call HDF_INIT to register the driver entry with the HDF.
```
3. Initialize the **MipiCsiCntlr** object at the core layer, including initializing the vendor custom structure \(passing parameters and data\), instantiating **MipiCsiCntlrMethod** \(used to call underlying functions of the driver\) in **MipiCsiCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\).
- Custom structure reference:
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>To the driver, the custom structure carries parameters and data. The values in the **config** file are used to initialize the structure members. In this example, the MIPI CSI attributes are defined in the source file. Therefore, the basic member structure is similar to that of **MipiCsiCntlr**.
```
typedef struct {
/** Data type: 8-bit, 10-bit, 12-bit, 14-bit, or 16-bit */
DataType inputDataType;
/** MIPI WDM mode */
MipiWdrMode wdrMode;
/** laneId: -1 - disabled */
short laneId[MIPI_LANE_NUM];
union {
/** Used for HI_MIPI_WDR_MODE_DT */
short dataType[WDR_VC_NUM];
};
} MipiDevAttr;
typedef struct {
/** Device number. */
uint8_t devno;
/** Input mode, which can be MIPI, LVDS, sub-LVDS, HiSPi, or DC. */
InputMode inputMode;
MipiDataRate dataRate;
/** Crop area of the MIPI RX device (same as the size of the input image of the sensor). */
ImgRect imgRect;
union {
MipiDevAttr mipiAttr;
LvdsDevAttr lvdsAttr;
};
} ComboDevAttr;
// MipiCsiCntlr is the core layer controller structure. Its members are assigned with values by using the Init function.
struct MipiCsiCntlr {
/** Send the service provided by this controller when the driver is bound to the HDF. */
struct IDeviceIoService service;
/** Pass the pointer to the device when the driver is bound to the HDF. */
struct HdfDeviceObject *device;
/** Device number */
unsigned int devNo;
/** All APIs provided by the controller */
struct MipiCsiCntlrMethod *ops;
/** All APIs for controller debugging. Set it to null if the driver is not implemented. */
struct MipiCsiCntlrDebugMethod *debugs;
/** Controller context variable. */
MipiDevCtx ctx;
/** Spinlock used when the controller context variable is accessed. */
OsalSpinlock ctxLock;
/** Lock method when the controller is managed */
struct OsalMutex lock;
/** Pointer to anonymous data, which is used to store the CSI device structure */
void *priv;
};
```
- **\(Important\)** Instantiate the callback function structure **MipiCsiCntlrMethod** in **MipiCsiCntlr**. Other members are initialized by using the **Init** function.
```
static struct MipiCsiCntlrMethod g_method = {
.setComboDevAttr = Hi35xxSetComboDevAttr,
.setPhyCmvmode = Hi35xxSetPhyCmvmode,
.setExtDataType = Hi35xxSetExtDataType,
.setHsMode = Hi35xxSetHsMode,
.enableClock = Hi35xxEnableClock,
.disableClock = Hi35xxDisableClock,
.resetRx = Hi35xxResetRx,
.unresetRx = Hi35xxUnresetRx,
.enableSensorClock = Hi35xxEnableSensorClock,
.disableSensorClock = Hi35xxDisableSensorClock,
.resetSensor = Hi35xxResetSensor,
.unresetSensor = Hi35xxUnresetSensor
};
```
- Init function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **/drivers/framework/include/utils/hdf\_base.h** file.\)
<a name="table683892652170128"></a>
<table><thead align="left"><tr id="row466801181170128"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry433041536170128p0"><a name="entry433041536170128p0"></a><a name="entry433041536170128p0"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry1260647143170128p0"><a name="entry1260647143170128p0"></a><a name="entry1260647143170128p0"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row2053721693170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry772353853170128p0"><a name="entry772353853170128p0"></a><a name="entry772353853170128p0"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry891453569170128p0"><a name="entry891453569170128p0"></a><a name="entry891453569170128p0"></a>Invalid object</p>
</td>
</tr>
<tr id="row1654561941170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1037876509170128p0"><a name="entry1037876509170128p0"></a><a name="entry1037876509170128p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1354763041170128p0"><a name="entry1354763041170128p0"></a><a name="entry1354763041170128p0"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row515913237170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1517991694170128p0"><a name="entry1517991694170128p0"></a><a name="entry1517991694170128p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry784824354170128p0"><a name="entry784824354170128p0"></a><a name="entry784824354170128p0"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row1055228061170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry771111180170128p0"><a name="entry771111180170128p0"></a><a name="entry771111180170128p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1302592910170128p0"><a name="entry1302592910170128p0"></a><a name="entry1302592910170128p0"></a>I/O error</p>
</td>
</tr>
<tr id="row1131544928170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1360197988170128p0"><a name="entry1360197988170128p0"></a><a name="entry1360197988170128p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1609403118170128p0"><a name="entry1609403118170128p0"></a><a name="entry1609403118170128p0"></a>Operation successful</p>
</td>
</tr>
<tr id="row1247344727170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry816278864170128p0"><a name="entry816278864170128p0"></a><a name="entry816278864170128p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry814861870170128p0"><a name="entry814861870170128p0"></a><a name="entry814861870170128p0"></a>Operation failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Connects to the **MipiCsiCntlrMethod** instance, calls **MipiCsiRegisterCntlr**, and performs other vendor-defined initialization operations.
```
static int32_t Hi35xxMipiCsiInit(struct HdfDeviceObject *device)
{
int32_t ret;
HDF_LOGI("%s: enter!", __func__);
g_mipiCsi.priv = NULL; // g_mipiTx is a global variable defined.
// static struct MipiCsiCntlr g_mipiCsi = {
// .devNo = 0
// };
g_mipiCsi.ops = &g_method; // Connect to the MipiCsiCntlrMethod instance.
#ifdef CONFIG_HI_PROC_SHOW_SUPPORT
g_mipiCsi.debugs = &g_debugMethod;
#endif
ret = MipiCsiRegisterCntlr(&g_mipiCsi, device); // (Mandatory) Call the function at the core layer and g_mipiTx to initialize global variables at the core layer.
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: [MipiCsiRegisterCntlr] failed!", __func__);
return ret;
}
ret = MipiRxDrvInit(); // (Mandatory) Device initialization customized by the vendor.
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: [MipiRxDrvInit] failed.", __func__);
return ret;
}
#ifdef MIPICSI_VFS_SUPPORT
ret = MipiCsiDevModuleInit(g_mipiCsi.devNo);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: [MipiCsiDevModuleInit] failed!", __func__);
return ret;
}
#endif
OsalSpinInit(&g_mipiCsi.ctxLock);
HDF_LOGI("%s: load mipi csi driver success!", __func__);
return ret;
}
// mipi_csi_core.c, core layer file.
int32_t MipiCsiRegisterCntlr(struct MipiCsiCntlr *cntlr, struct HdfDeviceObject *device)
{
...
// Define the global variable static struct MipiCsiHandle g_mipiCsihandle[MAX_CNTLR_CNT];
if (g_mipiCsihandle[cntlr->devNo].cntlr == NULL) {
(void)OsalMutexInit(&g_mipiCsihandle[cntlr->devNo].lock);
(void)OsalMutexInit(&(cntlr->lock));
g_mipiCsihandle[cntlr->devNo].cntlr = cntlr; // Initialize MipiCsiHandle.
g_mipiCsihandle[cntlr->devNo].priv = NULL;
cntlr->device = device; // Enable conversion between HdfDeviceObject and MipiCsiHandle.
device->service = &(cntlr->service); // Enable conversion between HdfDeviceObject and MipiCsiHandle.
cntlr->priv = NULL;
HDF_LOGI("%s: success.", __func__);
return HDF_SUCCESS;
}
HDF_LOGE("%s: cntlr already exists.", __func__);
return HDF_FAILURE;
}
```
- Release function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
Function description:
Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations.
```
static void Hi35xxMipiCsiRelease(struct HdfDeviceObject *device)
{
struct MipiCsiCntlr *cntlr = NULL;
...
cntlr = MipiCsiCntlrFromDevice(device); // A forced conversion from HdfDeviceObject to MipiCsiCntlr is involved.
// return (device == NULL) ? NULL : (struct MipiCsiCntlr *)device->service;
...
OsalSpinDestroy(&cntlr->ctxLock);
#ifdef MIPICSI_VFS_SUPPORT
MipiCsiDevModuleExit(cntlr->devNo);
#endif
MipiRxDrvExit(); // (Mandatory) Release the resources occupied by the vendor's devices.
MipiCsiUnregisterCntlr(&g_mipiCsi); // Null function
g_mipiCsi.priv = NULL;
HDF_LOGI("%s: unload mipi csi driver success!", __func__);
}
```
\ No newline at end of file
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 **mipicsi_config.hcs** file.
3. Instantiate the MIPI CSI controller object.
- Initialize **MipiCsiCntlr**.
- Instantiate **MipiCsiCntlrMethod** in the **MipiCsiCntlr** object.
>![](../public_sys-resources/icon-note.gif) **NOTE**<br>
>For details about the functions in **MipiCsiCntlrMethod**, see [Available APIs](#available-apis).
4. Debug the driver.
- (Optional) For new drivers, verify the basic functions, for example, the data transmission and the information returned after the **MipiCsiCntlrMethod** instance is attached.
## Development Example
The following uses **mipi_rx_hi35xx.c** as an example to present the information required for implementing device functions.
1. Configure the device attributes in **busxx_config.hcs** and add the **deviceNode** information to the **device_info.hcs** file.
The device attribute values are closely related to the default values or value range of the **MipiCsiCntlr** members at the core layer. The **deviceNode** information is related to the driver entry registration.
In this example, the MIPI controller attributes are defined in the source file. If required, add the **deviceMatchAttr** information to **deviceNode** in the **device_info** file and add the **mipicsi_config.hcs** file.
- **device_info.hcs** configuration example
```c
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_mipi_csi:: device {
device0 :: deviceNode {
policy = 0;
priority = 160;
permission = 0644;
moduleName = "HDF_MIPI_RX"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
serviceName = "HDF_MIPI_RX"; // (Mandatory) Unique name of the service published by the driver.
}
}
}
}
}
```
2. Instantiate the driver entry.<br/>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**. The function pointer members in the **HdfDriverEntry** structure are filled by the vendors' operation functions. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
- MIPI CSI driver entry example
```c
struct HdfDriverEntry g_mipiCsiDriverEntry = {
.moduleVersion = 1,
.Init = Hi35xxMipiCsiInit, // See the Init function.
.Release = Hi35xxMipiCsiRelease, //See the Release function.
.moduleName = "HDF_MIPI_RX", // (Mandatory) The value must be the same as that in the device_info.hcs file.
};
HDF_INIT(g_mipiCsiDriverEntry); // Call HDF_INIT to register the driver entry with the HDF.
```
3. Initialize the **MipiCsiCntlr** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**) to instantiate **MipiCsiCntlrMethod** in **MipiCsiCntlr** (so that the underlying driver functions can be called).
- Defining a custom structure
To the driver, the custom structure hols parameters and data. The values in the **config** file are used to initialize the structure members. In this example, the MIPI CSI attributes are defined in the source file. Therefore, the basic member structure is similar to that of **MipiCsiCntlr**.
```c
typedef struct {
/** The data type can be 8-, 10-, 12-, 14-, or 16-bit. */
DataType inputDataType;
/** MIPI WDM mode */
MipiWdrMode wdrMode;
/** laneId: -1 - disabled */
short laneId[MIPI_LANE_NUM];
union {
/** Used for HI_MIPI_WDR_MODE_DT */
short dataType[WDR_VC_NUM];
};
} MipiDevAttr;
typedef struct {
/** Device number */
uint8_t devno;
/** Input mode, which can be MIPI, LVDS, sub-LVDS, HiSPi, or DC. */
InputMode inputMode;
MipiDataRate dataRate;
/** Crop area of the MIPI RX device (same as the size of the sensor input image) */
ImgRect imgRect;
union {
MipiDevAttr mipiAttr;
LvdsDevAttr lvdsAttr;
};
} ComboDevAttr;
// MipiCsiCntlr is the core layer controller structure. The Init function assigns values to the members of MipiCsiCntlr.
struct MipiCsiCntlr {
/** Send the service provided by this controller when the driver is bound to the HDF. */
struct IDeviceIoService service;
/** Pass the pointer to the device when the driver is bound to the HDF. */
struct HdfDeviceObject *device;
/** Device number */
unsigned int devNo;
/** All APIs provided by the controller */
struct MipiCsiCntlrMethod *ops;
/** All APIs for controller debugging. Set it to null if the driver is not implemented. */
struct MipiCsiCntlrDebugMethod *debugs;
/** Controller context variable. */
MipiDevCtx ctx;
/** Spinlock used when the controller context variable is accessed. */
OsalSpinlock ctxLock;
/** Lock method when the controller is managed */
struct OsalMutex lock;
/** Pointer to the anonymous structure that holds the CSI device data */
void *priv;
};
```
- Instantiating **MipiCsiCntlrMethod** in **MipiCsiCntlr** (other members are initialized by **Init**)
```c
static struct MipiCsiCntlrMethod g_method = {
.setComboDevAttr = Hi35xxSetComboDevAttr,
.setPhyCmvmode = Hi35xxSetPhyCmvmode,
.setExtDataType = Hi35xxSetExtDataType,
.setHsMode = Hi35xxSetHsMode,
.enableClock = Hi35xxEnableClock,
.disableClock = Hi35xxDisableClock,
.resetRx = Hi35xxResetRx,
.unresetRx = Hi35xxUnresetRx,
.enableSensorClock = Hi35xxEnableSensorClock,
.disableSensorClock = Hi35xxDisableSensorClock,
.resetSensor = Hi35xxResetSensor,
.unresetSensor = Hi35xxUnresetSensor
};
```
- Init function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
HDF_STATUS<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
| Status | Description |
| :--------------------- | :----------: |
| HDF_ERR_INVALID_OBJECT | Invalid object. |
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory.|
| HDF_ERR_INVALID_PARAM | Invalid parameter. |
| HDF_ERR_IO | I/O error. |
| HDF_SUCCESS | Operation successful. |
| HDF_FAILURE | Operation failed. |
**Function description**:
Attaches the **MipiCsiCntlrMethod** instance, calls **MipiCsiRegisterCntlr**, and initializes the custom structure.
```c
static int32_t Hi35xxMipiCsiInit(struct HdfDeviceObject *device)
{
int32_t ret;
HDF_LOGI("%s: enter!", __func__);
g_mipiCsi.priv = NULL; // g_mipiTx is a global variable defined.
// static struct MipiCsiCntlr g_mipiCsi = {
// .devNo = 0
//};
g_mipiCsi.ops = &g_method; // Attach the MipiCsiCntlrMethod instance.
#ifdef CONFIG_HI_PROC_SHOW_SUPPORT
g_mipiCsi.debugs = &g_debugMethod;
#endif
ret = MipiCsiRegisterCntlr(&g_mipiCsi, device); // (Mandatory) Call the function at the core layer and g_mipiTx to initialize global variables at the core layer.
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: [MipiCsiRegisterCntlr] failed!", __func__);
return ret;
}
ret = MipiRxDrvInit(); // (Mandatory) Device initialization customized by the vendor.
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: [MipiRxDrvInit] failed.", __func__);
return ret;
}
#ifdef MIPICSI_VFS_SUPPORT
ret = MipiCsiDevModuleInit(g_mipiCsi.devNo);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: [MipiCsiDevModuleInit] failed!", __func__);
return ret;
}
#endif
OsalSpinInit(&g_mipiCsi.ctxLock);
HDF_LOGI("%s: load mipi csi driver success!", __func__);
return ret;
}
// mipi_csi_core.c file
int32_t MipiCsiRegisterCntlr(struct MipiCsiCntlr *cntlr, struct HdfDeviceObject *device)
{
...
// Global variable static struct MipiCsiHandle g_mipiCsihandle[MAX_CNTLR_CNT];
if (g_mipiCsihandle[cntlr->devNo].cntlr == NULL) {
(void)OsalMutexInit(&g_mipiCsihandle[cntlr->devNo].lock);
(void)OsalMutexInit(&(cntlr->lock));
g_mipiCsihandle[cntlr->devNo].cntlr = cntlr; // Initialize MipiCsiHandle.
g_mipiCsihandle[cntlr->devNo].priv = NULL;
cntlr->device = device; // Prerequisites for conversion between HdfDeviceObject and MipiCsiHandle
device->service = &(cntlr->service); // Prerequisites for conversion between HdfDeviceObject and MipiCsiHandle.
cntlr->priv = NULL;
HDF_LOGI("%s: success.", __func__);
return HDF_SUCCESS;
}
HDF_LOGE("%s: cntlr already exists.", __func__);
return HDF_FAILURE;
}
```
- Release function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
No value is returned.
**Function description**:
Releases the memory and deletes the controller. This function assigns values to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the value assignment operations.
```c
static void Hi35xxMipiCsiRelease(struct HdfDeviceObject *device)
{
struct MipiCsiCntlr *cntlr = NULL;
...
cntlr = MipiCsiCntlrFromDevice(device); // A forced conversion from HdfDeviceObject to MipiCsiCntlr is involved.
// return (device == NULL) ? NULL : (struct MipiCsiCntlr *)device->service;
...
OsalSpinDestroy(&cntlr->ctxLock);
#ifdef MIPICSI_VFS_SUPPORT
MipiCsiDevModuleExit(cntlr->devNo);
#endif
MipiRxDrvExit(); // (Mandatory) Release the resources occupied by vendor devices.
MipiCsiUnregisterCntlr(&g_mipiCsi); // Null function
g_mipiCsi.priv = NULL;
HDF_LOGI("%s: unload mipi csi driver success!", __func__);
}
```
# MMC<a name="EN-US_TOPIC_0000001153669000"></a>
# MMC
## Overview<a name="section1846388309162704"></a>
In the Hardware Driver Foundation \(HDF\) framework, the MultiMedia Card \(MMC\) uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to handle external access requests. After receiving an access request from an API, the device manager extracts the parameters in the request to call the internal method of the target device. In the independent service mode, the service management capabilities of the HDFDeviceManager can be directly used. However, you need to configure a device node for each device, which increases the memory usage.
## Overview
**Figure 1** Independent service mode<a name="fig19517114132810"></a>
![](figures/independent-service-mode.png "independent-service-mode")
In the Hardware Driver Foundation (HDF), the MultiMedia Card (MMC) uses the independent service mode for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device to increase memory resources.
## Available APIs<a name="section752964871810"></a>
**Figure 1** Independent service mode
![image](figures/independent-service-mode.png "MMC independent service mode")
## Available APIs
**MmcCntlrOps**:
MmcCntlrOps
```
struct MmcCntlrOps {
......@@ -31,520 +35,356 @@ struct MmcCntlrOps {
};
```
**Table 1** Callbacks for the members in the MmcCntlrOps structure
<a name="table99129433019"></a>
<table><thead align="left"><tr id="row1891214163012"><th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.1"><p id="p79129483017"><a name="p79129483017"></a><a name="p79129483017"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.2"><p id="p1591213403019"><a name="p1591213403019"></a><a name="p1591213403019"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.3"><p id="p491312483012"><a name="p491312483012"></a><a name="p491312483012"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.4"><p id="p8913144203017"><a name="p8913144203017"></a><a name="p8913144203017"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row4913844307"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p17913149309"><a name="p17913149309"></a><a name="p17913149309"></a>doRequest</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p359655512340"><a name="p359655512340"></a><a name="p359655512340"></a><strong id="b1596155533411"><a name="b1596155533411"></a><a name="b1596155533411"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p159131449308"><a name="p159131449308"></a><a name="p159131449308"></a><strong id="b71781053113715"><a name="b71781053113715"></a><a name="b71781053113715"></a>cmd</strong>: structure pointer to the input command.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1291519413308"><a name="p1291519413308"></a><a name="p1291519413308"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p3915048309"><a name="p3915048309"></a><a name="p3915048309"></a>Processes the request.</p>
</td>
</tr>
<tr id="row17915124113014"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p69152416307"><a name="p69152416307"></a><a name="p69152416307"></a>setClock</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p12397758163416"><a name="p12397758163416"></a><a name="p12397758163416"></a><strong id="b2397155816345"><a name="b2397155816345"></a><a name="b2397155816345"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p119153413013"><a name="p119153413013"></a><a name="p119153413013"></a><strong id="b13651101617393"><a name="b13651101617393"></a><a name="b13651101617393"></a>clock</strong>: input clock value.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p79153417302"><a name="p79153417302"></a><a name="p79153417302"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1291614183010"><a name="p1291614183010"></a><a name="p1291614183010"></a>Sets the clock frequency.</p>
</td>
</tr>
<tr id="row19168433011"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1391614416305"><a name="p1391614416305"></a><a name="p1391614416305"></a>setPowerMode</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p349710303139"><a name="p349710303139"></a><a name="p349710303139"></a><strong id="b749713013132"><a name="b749713013132"></a><a name="b749713013132"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p99161341305"><a name="p99161341305"></a><a name="p99161341305"></a><strong id="b1355614134405"><a name="b1355614134405"></a><a name="b1355614134405"></a>mode</strong>: power consumption mode. It is an enumerated value (see MmcPowerMode).</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1091674183020"><a name="p1091674183020"></a><a name="p1091674183020"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1191617420307"><a name="p1191617420307"></a><a name="p1191617420307"></a>Sets the power consumption mode.</p>
</td>
</tr>
<tr id="row291620463018"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p291612453018"><a name="p291612453018"></a><a name="p291612453018"></a>setBusWidth</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p52591598350"><a name="p52591598350"></a><a name="p52591598350"></a><strong id="b225999203512"><a name="b225999203512"></a><a name="b225999203512"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p11916245309"><a name="p11916245309"></a><a name="p11916245309"></a><strong id="b24742024134111"><a name="b24742024134111"></a><a name="b24742024134111"></a>width</strong>: bus width. It is an enumerated value (see MmcBusWidth).</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1491610415305"><a name="p1491610415305"></a><a name="p1491610415305"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p19916147304"><a name="p19916147304"></a><a name="p19916147304"></a>Sets the bus width.</p>
</td>
</tr>
<tr id="row1916742301"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p3916104143014"><a name="p3916104143014"></a><a name="p3916104143014"></a>setBusTiming</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p109861912123517"><a name="p109861912123517"></a><a name="p109861912123517"></a><strong id="b39864125357"><a name="b39864125357"></a><a name="b39864125357"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p591710419302"><a name="p591710419302"></a><a name="p591710419302"></a><strong id="b1067164920426"><a name="b1067164920426"></a><a name="b1067164920426"></a>timing</strong>: bus timing. It is an enumerated value (see MmcBusTiming).</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p14917154123017"><a name="p14917154123017"></a><a name="p14917154123017"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1991814443016"><a name="p1991814443016"></a><a name="p1991814443016"></a>Sets the bus timing.</p>
</td>
</tr>
<tr id="row199186423012"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p991810414305"><a name="p991810414305"></a><a name="p991810414305"></a>setSdioIrq</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p207324169351"><a name="p207324169351"></a><a name="p207324169351"></a><strong id="b11731716183510"><a name="b11731716183510"></a><a name="b11731716183510"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p16918844305"><a name="p16918844305"></a><a name="p16918844305"></a><strong id="b49304428454"><a name="b49304428454"></a><a name="b49304428454"></a>enable</strong>: specifies whether to enable interrupt.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p17918204193011"><a name="p17918204193011"></a><a name="p17918204193011"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1191813416305"><a name="p1191813416305"></a><a name="p1191813416305"></a>Enables or disables Secure Digital Input Output (SDIO) interrupt.</p>
</td>
</tr>
<tr id="row139181453012"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p491874193011"><a name="p491874193011"></a><a name="p491874193011"></a>hardwareReset</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p12918114163011"><a name="p12918114163011"></a><a name="p12918114163011"></a><strong id="b127774583476"><a name="b127774583476"></a><a name="b127774583476"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p4918244309"><a name="p4918244309"></a><a name="p4918244309"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p11919243306"><a name="p11919243306"></a><a name="p11919243306"></a>Resets hardware.</p>
</td>
</tr>
<tr id="row169195410309"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p89191746303"><a name="p89191746303"></a><a name="p89191746303"></a>systemInit</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p8919441302"><a name="p8919441302"></a><a name="p8919441302"></a><strong id="b296543474814"><a name="b296543474814"></a><a name="b296543474814"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p199191941307"><a name="p199191941307"></a><a name="p199191941307"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p391919473014"><a name="p391919473014"></a><a name="p391919473014"></a>Performs system initialization.</p>
</td>
</tr>
<tr id="row159191423012"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p189194417307"><a name="p189194417307"></a><a name="p189194417307"></a>setEnhanceSrobe</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p684922173510"><a name="p684922173510"></a><a name="p684922173510"></a><strong id="b1184122212354"><a name="b1184122212354"></a><a name="b1184122212354"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p1191910419304"><a name="p1191910419304"></a><a name="p1191910419304"></a><strong id="b17674159184914"><a name="b17674159184914"></a><a name="b17674159184914"></a>enable</strong>: specifies whether to enable the enhanced strobe feature.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p69194473011"><a name="p69194473011"></a><a name="p69194473011"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p091904143019"><a name="p091904143019"></a><a name="p091904143019"></a>Sets the enhanced strobe feature.</p>
</td>
</tr>
<tr id="row109197416305"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p791917443010"><a name="p791917443010"></a><a name="p791917443010"></a>switchVoltage</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p180311317351"><a name="p180311317351"></a><a name="p180311317351"></a><strong id="b2803231173514"><a name="b2803231173514"></a><a name="b2803231173514"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p1591912415304"><a name="p1591912415304"></a><a name="p1591912415304"></a><strong id="b5411538185218"><a name="b5411538185218"></a><a name="b5411538185218"></a>volt</strong>: voltage, which can be 3.3 V, 1.8 V, or 1.2 V. It is an enumerated value.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p59196416307"><a name="p59196416307"></a><a name="p59196416307"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p169207416301"><a name="p169207416301"></a><a name="p169207416301"></a>Sets the voltage.</p>
</td>
</tr>
<tr id="row1992015417301"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1892014463010"><a name="p1892014463010"></a><a name="p1892014463010"></a>devReadOnly</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1392011411309"><a name="p1392011411309"></a><a name="p1392011411309"></a><strong id="b20848102414403"><a name="b20848102414403"></a><a name="b20848102414403"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p89207418304"><a name="p89207418304"></a><a name="p89207418304"></a>Boolean</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p7920847301"><a name="p7920847301"></a><a name="p7920847301"></a>Checks whether the device is read-only.</p>
</td>
</tr>
<tr id="row1092019483018"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1092034103011"><a name="p1092034103011"></a><a name="p1092034103011"></a>cardPluged</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p2920144123010"><a name="p2920144123010"></a><a name="p2920144123010"></a><strong id="b1685142434016"><a name="b1685142434016"></a><a name="b1685142434016"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p2092014411305"><a name="p2092014411305"></a><a name="p2092014411305"></a>Boolean</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1892094153017"><a name="p1892094153017"></a><a name="p1892094153017"></a>Checks whether the device is removed.</p>
</td>
</tr>
<tr id="row892018413013"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p39201146309"><a name="p39201146309"></a><a name="p39201146309"></a>devBusy</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p9920124193013"><a name="p9920124193013"></a><a name="p9920124193013"></a><strong id="b1885213240408"><a name="b1885213240408"></a><a name="b1885213240408"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1992112419305"><a name="p1992112419305"></a><a name="p1992112419305"></a>Boolean</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p69211417302"><a name="p69211417302"></a><a name="p69211417302"></a>Checks whether the device is engaged.</p>
</td>
</tr>
<tr id="row71064053613"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1511114015361"><a name="p1511114015361"></a><a name="p1511114015361"></a>tune</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p4972240153511"><a name="p4972240153511"></a><a name="p4972240153511"></a><strong id="b1997244017354"><a name="b1997244017354"></a><a name="b1997244017354"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p5116409364"><a name="p5116409364"></a><a name="p5116409364"></a><strong id="b2286168195617"><a name="b2286168195617"></a><a name="b2286168195617"></a>cmdCode</strong>: command code of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p711440123610"><a name="p711440123610"></a><a name="p711440123610"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1411184011368"><a name="p1411184011368"></a><a name="p1411184011368"></a>Tunes</p>
</td>
</tr>
<tr id="row1559214410366"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1559364493618"><a name="p1559364493618"></a><a name="p1559364493618"></a>rescanSdioDev</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p165931944133618"><a name="p165931944133618"></a><a name="p165931944133618"></a><strong id="b0854424164010"><a name="b0854424164010"></a><a name="b0854424164010"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p15593184493610"><a name="p15593184493610"></a><a name="p15593184493610"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p359384473615"><a name="p359384473615"></a><a name="p359384473615"></a>Scans and adds an SDIO device.</p>
</td>
</tr>
</tbody>
</table>
## How to Develop<a name="section1617495117162704"></a>
**Table 1** Description of callback functions in MmcCntlrOps
| Function| Input Parameter| Return Value| Description|
| -------- | -------- | -------- | -------- |
| doRequest | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**cmd**: structure pointer to the command to execute.| HDF_STATUS| Processes the request.|
| setClock | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**clock**: clock frequency to set.| HDF_STATUS| Sets the clock frequency.|
| setPowerMode | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**mode**: power consumption mode, which is an enumerated value.| HDF_STATUS| Sets the power consumption mode.|
| setBusWidth | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**width**: bus width, which is an enumerated value.| HDF_STATUS| Sets the bus width.|
| setBusTiming | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**timing**: bus timing, which is an enumerated value.| HDF_STATUS| Sets the bus timing.|
| setSdioIrq | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**enable**: whether to enable Secure Digital Input Output (SDIO) interrupts.| HDF_STATUS| Enables or disables SDIO interrupts.|
| hardwareReset | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Resets hardware.|
| systemInit | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Performs system initialization.|
| setEnhanceSrobe | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**enable**: whether to enable the enhanced strobe feature.| HDF_STATUS| Sets the enhanced strobe feature.|
| switchVoltage | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**volt**: voltage to set, which can be 3.3 V, 1.8 V, or 1.2 V.| HDF_STATUS| Sets the voltage.|
| devReadOnly | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is read-only.|
| cardPluged | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is removed.|
| devBusy | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is being used.|
| tune | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**cmdCode**: command code of the uint32_t type.| HDF_STATUS| Tunes the oscillator circuit frequency. |
| rescanSdioDev | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Scans and adds an SDIO device.|
## How to Develop
The MMC 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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **mmc\_config.hcs** file.
3. Instantiate the MMC controller object.
- Initialize **MmcCntlr**.
- Instantiate **MmcCntlrOps** in the **MmcCntlr** object.
For details, see [Available APIs](#available-apis).
4. \(Optional\) Debug the driver.
For new drivers, verify basic functions, for example, verify the information returned after the mount operation and whether the device starts successfully.
## Development Example<a name="section1220893490162704"></a>
The following uses **himci.c** as an example to present the contents that need to be provided by the vendor to implement device functions.
1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit.
- MMC driver entry reference
```
struct HdfDriverEntry g_mmcDriverEntry = {
.moduleVersion = 1,
.Bind = HimciMmcBind, // See the Bind function.
.Init = HimciMmcInit, // See the Init function.
.Release = HimciMmcRelease, //See the Release function.
.moduleName = "hi3516_mmc_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
HDF_INIT(g_mmcDriverEntry); // Call HDF_INIT to register the driver entry with the HDF framework.
```
2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **mmc\_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 **MmcCntlr** members at the core layer.
If there are multiple devices, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **mmc\_config** file.
- **device\_info.hcs** configuration reference
```
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_mmc:: device {
device0 :: deviceNode {
policy = 2;
priority = 10;
permission = 0644;
moduleName = "hi3516_mmc_driver"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry.
serviceName = "HDF_PLATFORM_MMC_0"; // (Mandatory) Unique name of the service published by the driver
deviceMatchAttr = "hi3516_mmc_emmc";// (Mandatory) Used to configure the private data of the controller. The value must be the same as the controller in mmc_config.hcs.
}
device1 :: deviceNode {
policy = 1;
priority = 20;
permission = 0644;
moduleName = "hi3516_mmc_driver";
serviceName = "HDF_PLATFORM_MMC_1";
deviceMatchAttr = "hi3516_mmc_sd"; // Indicates an SD.
}
device2 :: deviceNode {
policy = 1;
priority = 30;
permission = 0644;
moduleName = "hi3516_mmc_driver";
serviceName = "HDF_PLATFORM_MMC_2";
deviceMatchAttr = "hi3516_mmc_sdio";// Indicates an SDIO.
}
}
}
}
}
```
- **mmc\_config.hcs** configuration reference
```
root {
platform {
mmc_config {
template mmc_controller {// Template configuration. In the template, you can configure the common parameters shared by service nodes.
match_attr = "";
voltDef = 0; // 3.3V
freqMin = 50000; // (Mandatory) Minimum frequency
freqMax = 100000000; // (Mandatory) Maximum frequency
freqDef = 400000; // (Mandatory) Default frequency
maxBlkNum = 2048; // (Mandatory) Maximum block number
maxBlkSize = 512; // (Mandatory) Maximum number of blocks
ocrDef = 0x300000; // (Mandatory) Working voltage.
caps2 = 0; // (Mandatory) Attribute register. For details, see MmcCaps2 in mmc_caps.h.
regSize = 0x118; // (Mandatory) Register bit width
hostId = 0; // (Mandatory) Host ID
regBasePhy = 0x10020000;// (Mandatory) Physical base address of the register
irqNum = 63; // (Mandatory) Interrupt number
devType = 2; // (Mandatory) Device mode, which can be eMMC, SD, SDIO, or COMBO
caps = 0x0001e045; // (Mandatory) Attribute register. For details, see MmcCaps in mmc_caps.h.
}
controller_0x10100000 :: mmc_controller {
match_attr = "hi3516_mmc_emmc";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
hostId = 0;
regBasePhy = 0x10100000;
irqNum = 96;
devType = 0; // The value 0 indicates an eMMC.
caps = 0xd001e045;
caps2 = 0x60;
}
controller_0x100f0000 :: mmc_controller {
match_attr = "hi3516_mmc_sd";
hostId = 1;
regBasePhy = 0x100f0000;
irqNum = 62;
devType = 1; // The value 1 indicates an SD card.
caps = 0xd001e005;
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 **mmc_config.hcs** file.
3. Instantiate the MMC controller object.
- Initialize **MmcCntlr**.
- Instantiate **MmcCntlrOps** in the **MmcCntlr** object.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> For details about the functions in **MmcCntlrOps**, see [Available APIs](#available-apis).
4. Debug the driver.
(Optional) For new drivers, verify the basic functions, for example, verify the information returned after the **MmcCntlrOps** instance is attached and whether the device starts successfully.
## Development Example
The following uses **himci.c** as an example to present the information required for implementing device functions.
1. Instantiate the driver entry.<br/>The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
MMC driver entry example:
```
struct HdfDriverEntry g_mmcDriverEntry = {
.moduleVersion = 1,
.Bind = HimciMmcBind, // See the Bind function.
.Init = HimciMmcInit, // See the Init function.
.Release = HimciMmcRelease, // See the Release function.
.moduleName = "hi3516_mmc_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
HDF_INIT(g_mmcDriverEntry); // Call HDF_INIT to register the driver entry with the HDF.
```
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **mmc_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 **MmcCntlr** members at the core layer. If there are multiple devices, you need to add the **deviceNode** information to the **device_info** file and add the device attributes to the **mmc_config** file for each device.
- **device_info.hcs** configuration example
```
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_mmc:: device {
device0 :: deviceNode {
policy = 2;
priority = 10;
permission = 0644;
moduleName = "hi3516_mmc_driver"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
serviceName = "HDF_PLATFORM_MMC_0"; // (Mandatory) Unique name of the service published by the driver.
deviceMatchAttr = "hi3516_mmc_emmc";// (Mandatory) Private data of the controller. The value must be the same as the controller information in mmc_config.hcs.
}
device1 :: deviceNode {
policy = 1;
priority = 20;
permission = 0644;
moduleName = "hi3516_mmc_driver";
serviceName = "HDF_PLATFORM_MMC_1";
deviceMatchAttr = "hi3516_mmc_sd"; // The MMC is an SD card.
}
device2 :: deviceNode {
policy = 1;
priority = 30;
permission = 0644;
moduleName = "hi3516_mmc_driver";
serviceName = "HDF_PLATFORM_MMC_2";
deviceMatchAttr = "hi3516_mmc_sdio";// The MMC is an SDIO card.
}
}
}
}
}
```
- **mmc_config.hcs** configuration example
```
root {
platform {
mmc_config {
template mmc_controller { // Template configuration. In the template, you can configure the common parameters shared by device nodes.
match_attr = "";
voltDef = 0; // 3.3V
freqMin = 50000; // (Mandatory) Minimum frequency
freqMax = 100000000; // (Mandatory) Maximum frequency
freqDef = 400000; // (Mandatory) Default frequency
maxBlkNum = 2048; // (Mandatory) Maximum block number
maxBlkSize = 512; // (Mandatory) Maximum number of blocks
ocrDef = 0x300000; // (Mandatory) Working voltage.
caps2 = 0; // (Mandatory) Attribute register. For details, see MmcCaps2 in mmc_caps.h.
regSize = 0x118; // (Mandatory) Register bit width
hostId = 0; // (Mandatory) Host ID
regBasePhy = 0x10020000;// (Mandatory) Physical base address of the register
irqNum = 63; // (Mandatory) Interrupt number
devType = 2; // (Mandatory) Device type, which can be eMMC, SD, SDIO, or COMBO
caps = 0x0001e045; // (Mandatory) Attribute register. For details, see MmcCaps in mmc_caps.h.
}
controller_0x10100000 :: mmc_controller {
match_attr = "hi3516_mmc_emmc";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
hostId = 0;
regBasePhy = 0x10100000;
irqNum = 96;
devType = 0; // The MMC is an eMMC card.
caps = 0xd001e045;
caps2 = 0x60;
}
controller_0x100f0000 :: mmc_controller {
match_attr = "hi3516_mmc_sd";
hostId = 1;
regBasePhy = 0x100f0000;
irqNum = 62;
devType = 1; // The MMC is an SD card.
caps = 0xd001e005;
}
controller_0x10020000 :: mmc_controller {
match_attr = "hi3516_mmc_sdio";
hostId = 2;
regBasePhy = 0x10020000;
irqNum = 63;
devType = 2; // The MMC is an SDIO card.
caps = 0x0001e04d;
}
}
}
}
```
3. Initialize the **MmcCntlr** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**) to instantiate **MmcCntlrOps** in **MmcCntlr** (so that the underlying driver functions can be called).
- Defining a custom structure
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **mmc_config.hcs** file to initialize the members in the custom structure and pass important parameters to the **MmcCntlr** object at the core layer.
```
struct HimciHost {
struct MmcCntlr *mmc;// (Mandatory) Core layer structure
struct MmcCmd *cmd; // (Mandatory) Core layer structure used to pass commands. For details about related commands, see MmcCmdCode.
//(Optional) Set parameters based on actual requirements.
void *base;
enum HimciPowerStatus powerStatus;
uint8_t *alignedBuff;
uint32_t buffLen;
struct scatterlist dmaSg;
struct scatterlist *sg;
uint32_t dmaSgNum;
DMA_ADDR_T dmaPaddr;
uint32_t *dmaVaddr;
uint32_t irqNum;
bool isTuning;
uint32_t id;
struct OsalMutex mutex;
bool waitForEvent;
HIMCI_EVENT himciEvent;
};
// MmcCntlr is the core layer controller structure. The bind function assigns values to the members of MmcCntlr.
struct MmcCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *hdfDevObj;
struct PlatformDevice device;
struct OsalMutex mutex;
struct OsalSem released;
uint32_t devType;
struct MmcDevice *curDev;
struct MmcCntlrOps *ops;
struct PlatformQueue *msgQueue;
uint16_t index;
uint16_t voltDef;
uint32_t vddBit;
uint32_t freqMin;
uint32_t freqMax;
uint32_t freqDef;
union MmcOcr ocrDef;
union MmcCaps caps;
union MmcCaps2 caps2;
uint32_t maxBlkNum;
uint32_t maxBlkSize;
uint32_t maxReqSize;
bool devPluged;
bool detecting;
void *priv;
};
```
- Instantiating **MmcCntlrOps** in **MmcCntlr** (other members are initialized by **Bind**)
```
static struct MmcCntlrOps g_himciHostOps = {
.request = HimciDoRequest,
.setClock = HimciSetClock,
.setPowerMode = HimciSetPowerMode,
.setBusWidth = HimciSetBusWidth,
.setBusTiming = HimciSetBusTiming,
.setSdioIrq = HimciSetSdioIrq,
.hardwareReset = HimciHardwareReset,
.systemInit = HimciSystemInit,
.setEnhanceSrobe= HimciSetEnhanceSrobe,
.switchVoltage = HimciSwitchVoltage,
.devReadOnly = HimciDevReadOnly,
.devPluged = HimciCardPluged,
.devBusy = HimciDevBusy,
.tune = HimciTune,
.rescanSdioDev = HimciRescanSdioDev,
};
```
- **Bind** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
HDF_STATUS<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
| Status| Description|
| -------- | -------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory.|
| HDF_ERR_INVALID_PARAM | Invalid parameter.|
| HDF_ERR_IO | I/O error.|
| HDF_SUCCESS | Initialization successful.|
| HDF_FAILURE | Initialization failed.|
**Function description**:
Initializes the custom structure **HimciHost** object and **MmcCntlr**, and calls the **MmcCntlrAdd** function at the core layer. **MmcCntlr**, **HimciHost**, and **HdfDeviceObject** assign values with each other so that other functions can be converted successfully.
```
static int32_t HimciMmcBind(struct HdfDeviceObject *obj)
{
struct MmcCntlr *cntlr = NULL;
struct HimciHost *host = NULL;
int32_t ret;
cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));
host = (struct HimciHost *)OsalMemCalloc(sizeof(struct HimciHost));
host->mmc = cntlr; // (Mandatory) Prerequisites for conversion between HimciHost and MmcCntlr.
cntlr->priv = (void *)host; // (Mandatory) Prerequisites for conversion between HimciHost and MmcCntlr.
cntlr->ops = &g_himciHostOps; // (Mandatory) Attach the MmcCntlrOps instance.
cntlr->hdfDevObj = obj; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
obj->service = &cntlr->service; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
ret = MmcCntlrParse(cntlr, obj); // (Mandatory) Initialize MmcCntlr. If the initialization fails, execute goto _ERR.
...
ret = HimciHostParse(host, obj); // (Mandatory) Initialize HimciHost. If the initialization fails, execute goto _ERR.
...
ret = HimciHostInit(host, cntlr);// Customized initialization. If the initialization fails, execute goto _ERR.
...
ret = MmcCntlrAdd(cntlr); // Call the functions at the core layer. If the operation fails, execute goto _ERR.
...
(void)MmcCntlrAddDetectMsgToQueue(cntlr);// Add the card detection message to the queue.
HDF_LOGD("HimciMmcBind: success.");
return HDF_SUCCESS;
_ERR:
HimciDeleteHost(host);
HDF_LOGD("HimciMmcBind: fail, err = %d.", ret);
return ret;
}
```
- **Init** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
HDF_STATUS
**Function description**:
Implements **ProcMciInit**.
```
static int32_t HimciMmcInit(struct HdfDeviceObject *obj)
{
static bool procInit = false;
(void)obj;
if (procInit == false) {
if (ProcMciInit() == HDF_SUCCESS) {
procInit = true;
HDF_LOGD("HimciMmcInit: proc init success.");
}
controller_0x10020000 :: mmc_controller {
match_attr = "hi3516_mmc_sdio";
hostId = 2;
regBasePhy = 0x10020000;
irqNum = 63;
devType = 2; // The value 2 indicates an SDIO device.
caps = 0x0001e04d;
}
}
}
}
```
3. Initialize the **MmcCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **MmcCntlrOps** \(used to call underlying functions of the driver\) in **MmcCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\).
- Custom structure reference
To the driver, the custom structure carries parameters and data. The values in the **mmc\_config.hcs** file are read by the HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values are also transferred to the objects at the core layer.
```
struct HimciHost {
struct MmcCntlr *mmc;// (Mandatory) Core layer structure
struct MmcCmd *cmd; // (Mandatory) Core layer structure used to transfer commands. For details about related commands, see MmcCmdCode.
//(Optional) Set parameters based on the vendor's requirements.
void *base;
enum HimciPowerStatus powerStatus;
uint8_t *alignedBuff;
uint32_t buffLen;
struct scatterlist dmaSg;
struct scatterlist *sg;
uint32_t dmaSgNum;
DMA_ADDR_T dmaPaddr;
uint32_t *dmaVaddr;
uint32_t irqNum;
bool isTuning;
uint32_t id;
struct OsalMutex mutex;
bool waitForEvent;
HIMCI_EVENT himciEvent;
};
// MmcCntlr is the core layer controller structure. Its members are assigned with values by using the bind function.
struct MmcCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *hdfDevObj;
struct PlatformDevice device;
struct OsalMutex mutex;
struct OsalSem released;
uint32_t devType;
struct MmcDevice *curDev;
struct MmcCntlrOps *ops;
struct PlatformQueue *msgQueue;
uint16_t index;
uint16_t voltDef;
uint32_t vddBit;
uint32_t freqMin;
uint32_t freqMax;
uint32_t freqDef;
union MmcOcr ocrDef;
union MmcCaps caps;
union MmcCaps2 caps2;
uint32_t maxBlkNum;
uint32_t maxBlkSize;
uint32_t maxReqSize;
bool devPluged;
bool detecting;
void *priv;
};
```
- Instantiate the callback function structure **MmcCntlrOps** in **MmcCntlr**. Other members are initialized by using the **Bind** function.
```
static struct MmcCntlrOps g_himciHostOps = {
.request = HimciDoRequest,
.setClock = HimciSetClock,
.setPowerMode = HimciSetPowerMode,
.setBusWidth = HimciSetBusWidth,
.setBusTiming = HimciSetBusTiming,
.setSdioIrq = HimciSetSdioIrq,
.hardwareReset = HimciHardwareReset,
.systemInit = HimciSystemInit,
.setEnhanceSrobe= HimciSetEnhanceSrobe,
.switchVoltage = HimciSwitchVoltage,
.devReadOnly = HimciDevReadOnly,
.devPluged = HimciCardPluged,
.devBusy = HimciDevBusy,
.tune = HimciTune,
.rescanSdioDev = HimciRescanSdioDev,
};
```
- Bind function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\)
<a name="table1428218958162704"></a>
<table><thead align="left"><tr id="row1723943104162704"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry136979408162704p0"><a name="entry136979408162704p0"></a><a name="entry136979408162704p0"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry1590766658162704p0"><a name="entry1590766658162704p0"></a><a name="entry1590766658162704p0"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row408410040162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1337150412162704p0"><a name="entry1337150412162704p0"></a><a name="entry1337150412162704p0"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry2061632106162704p0"><a name="entry2061632106162704p0"></a><a name="entry2061632106162704p0"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row160841211162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1173668571162704p0"><a name="entry1173668571162704p0"></a><a name="entry1173668571162704p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry74350097162704p0"><a name="entry74350097162704p0"></a><a name="entry74350097162704p0"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row1596857798162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry190784255162704p0"><a name="entry190784255162704p0"></a><a name="entry190784255162704p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1070501269162704p0"><a name="entry1070501269162704p0"></a><a name="entry1070501269162704p0"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row1645995958162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry741922133162704p0"><a name="entry741922133162704p0"></a><a name="entry741922133162704p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry2094504256162704p0"><a name="entry2094504256162704p0"></a><a name="entry2094504256162704p0"></a>I/O error</p>
</td>
</tr>
<tr id="row733220922162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1177794681162704p0"><a name="entry1177794681162704p0"></a><a name="entry1177794681162704p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry540896959162704p0"><a name="entry540896959162704p0"></a><a name="entry540896959162704p0"></a>Initialization successful</p>
</td>
</tr>
<tr id="row1890064939162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry118676812162704p0"><a name="entry118676812162704p0"></a><a name="entry118676812162704p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry2078272728162704p0"><a name="entry2078272728162704p0"></a><a name="entry2078272728162704p0"></a>Initialization failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Initializes the custom structure **HimciHost** object and **MmcCntlr**, and calls the **MmcCntlrAdd** function at the core layer. **MmcCntlr**, **HimciHost**, and **HdfDeviceObject** assign values with each other so that other functions can be converted successfully.
```
static int32_t HimciMmcBind(struct HdfDeviceObject *obj)
{
struct MmcCntlr *cntlr = NULL;
struct HimciHost *host = NULL;
int32_t ret;
cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));
host = (struct HimciHost *)OsalMemCalloc(sizeof(struct HimciHost));
host->mmc = cntlr; // (Mandatory) Enable conversion between HimciHost and MmcCntlr.
cntlr->priv = (void *)host; // (Mandatory) Enable conversion between HimciHost and MmcCntlr.
cntlr->ops = &g_himciHostOps; // (Mandatory) Connect to the MmcCntlrOps instance.
cntlr->hdfDevObj = obj; // (Mandatory) Enable conversion between HdfDeviceObject and MmcCntlr.
obj->service = &cntlr->service; // (Mandatory) Enable conversion between HdfDeviceObject and MmcCntlr.
ret = MmcCntlrParse(cntlr, obj); // (Mandatory) Initialize cntlr. If the initialization fails, execute goto _ERR.
...
ret = HimciHostParse(host, obj); // (Mandatory) Initialize the attributes of the host. If the initialization fails, execute goto _ERR.
...
ret = HimciHostInit(host, cntlr);// Initialization defined by the vendor. If the initialization fails, execute goto _ERR.
...
ret = MmcCntlrAdd(cntlr); // Call the function at the core layer. If the function fails to be called, execute goto _ERR.
...
(void)MmcCntlrAddDetectMsgToQueue(cntlr);// Add the card detection message to the queue.
HDF_LOGD("HimciMmcBind: success.");
return HDF_SUCCESS;
_ERR:
HimciDeleteHost(host);
HDF_LOGD("HimciMmcBind: fail, err = %d.", ret);
return ret;
}
```
- Init function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
HDF\_STATUS
Function description:
Implements ProcMciInit.
```
static int32_t HimciMmcInit(struct HdfDeviceObject *obj)
{
static bool procInit = false;
(void)obj;
if (procInit == false) {
if (ProcMciInit() == HDF_SUCCESS) {
procInit = true;
HDF_LOGD("HimciMmcInit: proc init success.");
}
}
HDF_LOGD("HimciMmcInit: success.");
return HDF_SUCCESS;
}
```
- Release function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
Function description:
Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF framework fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations.
```
static void HimciMmcRelease(struct HdfDeviceObject *obj)
{
struct MmcCntlr *cntlr = NULL;
...
cntlr = (struct MmcCntlr *)obj->service;// Forcibly convert HdfDeviceObject to MmcCntlr by using service. For details about the value assignment, see the Bind function.
...
HimciDeleteHost((struct HimciHost *)cntlr->priv);// Memory release function customized by the vendor. A forced conversion from MmcCntlr to HimciHost is involved in the process.
}
```
\ No newline at end of file
HDF_LOGD("HimciMmcInit: success.");
return HDF_SUCCESS;
}
```
- **Release** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
No value is returned.
**Function description**:
Releases the memory and deletes the controller. This function assigns values to the **Release** function 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. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the value assignment operations.
```
static void HimciMmcRelease(struct HdfDeviceObject *obj)
{
struct MmcCntlr *cntlr = NULL;
...
cntlr = (struct MmcCntlr *)obj->service;// Forcibly convert HdfDeviceObject to MmcCntlr by using service. For details about the value assignment, see the Bind function.
...
HimciDeleteHost((struct HimciHost *)cntlr->priv);// Customized memory release function. A forced conversion from MmcCntlr to HimciHost is involved in the process.
}
```
......@@ -3,7 +3,7 @@
## Overview
The real-time clock (RTC) is a real-time clock device in the operating system. In the HDF, the RTC uses the independent service mode for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device to increase memory resources.
The real-time clock (RTC) is a real-time clock device in the operating system. In the Hardware Driver Foundation (HDF), the RTC uses the independent service mode for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device to increase memory resources.
**Figure 1** Independent service mode
......@@ -14,7 +14,7 @@ The real-time clock (RTC) is a real-time clock device in the operating system. I
**RtcMethod**:
```
struct RtcMethod {
int32_t (*ReadTime)(struct RtcHost *host, struct RtcTime *time);
......@@ -64,7 +64,7 @@ The RTC module adaptation involves the following steps:
- Initialize **RtcHost**.
- Instantiate **RtcMethod** in the **RtcHost** object.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> For details about the functions in **RtcMethod**, see [API APIs](#available-apis).
> For details about the functions in **RtcMethod**, see [Available APIs](#available-apis).
4. Debug the driver.
(Optional) For new drivers, verify the basic functions, such as the RTC status control and response to interrupts.
......@@ -72,13 +72,13 @@ The RTC module adaptation involves the following steps:
## Development Example
The following uses **rtc_hi35xx.c** as an example to present the information to be provided by the vendor to implement device functions.
The following uses **rtc_hi35xx.c** as an example to present the information required for implementing device functions.
1. Instantiate the driver entry.<br/>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 framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
RTC driver entry example:
```
struct HdfDriverEntry g_rtcDriverEntry = {
.moduleVersion = 1,
......@@ -91,11 +91,14 @@ The following uses **rtc_hi35xx.c** as an example to present the information to
HDF_INIT(g_rtcDriverEntry);
```
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **rtc_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 **RtcHost** members at the core layer.
In this example, there is only one RTC controller. If there are multiple RTC controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **rtc_config** file for each controller.
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **rtc_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 **RtcHost** members at the core layer.
In this example, there is only one RTC controller. If there are multiple RTC controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **rtc_config** file for each controller.
- **device_info.hcs** configuration example
```
root {
device_info {
......@@ -117,7 +120,7 @@ The following uses **rtc_hi35xx.c** as an example to present the information to
- **rtc_config.hcs** configuration example
```
root {
platform {
......@@ -136,16 +139,16 @@ The following uses **rtc_hi35xx.c** as an example to present the information to
lock3Addr = 0xff;
}
}
}
}
}
```
```
3. Initialize the **RtcHost** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init** and **Release**) to instantiate **RtcMethod** in **RtcHost** (so that the underlying driver functions can be called).
- Defining a custom structure
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **rtc_config.hcs** file to initialize the members in the custom structure.
```
struct RtcConfigInfo {
uint32_t spiBaseAddr; // Used for address mapping.
......@@ -171,7 +174,7 @@ The following uses **rtc_hi35xx.c** as an example to present the information to
```
- Instantiating **RtcMethod** in **RtcHost** (other members are initialized by **Init**)
```
// Example in rtc_hi35xx.c: instantiate the hook.
static struct RtcMethod g_method = {
......@@ -214,7 +217,7 @@ The following uses **rtc_hi35xx.c** as an example to present the information to
Binds the **HdfDeviceObject** object and **RtcHost**.
```
static int32_t HiRtcBind(struct HdfDeviceObject *device)
{
......@@ -242,7 +245,7 @@ The following uses **rtc_hi35xx.c** as an example to present the information to
Initializes the custom structure object and **RtcHost**.
```
static int32_t HiRtcInit(struct HdfDeviceObject *device)
{
......@@ -284,7 +287,7 @@ The following uses **rtc_hi35xx.c** as an example to present the information to
Releases the memory and deletes the controller. This function assigns values to the **Release** function 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. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** or **Bind** function has the corresponding value assignment operations.
```
static void HiRtcRelease(struct HdfDeviceObject *device)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册