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

!3830 【OpenHarmony开源贡献者计划2022】SDIO相关格式及表达问题

Merge pull request !3830 from king_he/sdio-1
......@@ -2,26 +2,27 @@
## Overview<a name="section1155271783811"></a>
- Secure Digital Input/Output \(SDIO\) is a peripheral interface evolved from the Secure Digital \(SD\) memory card interface. The SDIO interface is compatible with SD memory cards and can be connected to devices that support the SDIO interface.
- SDIO is widely used. Currently, many smartphones support SDIO, and many SDIO peripherals are developed for connections to smartphones. Common SDIO peripherals include WLAN, GPS, cameras, and Bluetooth.
- The SDIO bus has two ends, named host and device. All communication starts when the host sends a command. The device can communicate with the host as long as it can parse the command of the host. An SDIO host can connect to multiple devices, as shown in the figure below.
Secure Digital Input/Output \(SDIO\) is a peripheral interface evolved from the Secure Digital \(SD\) memory card interface. The SDIO interface is compatible with SD memory cards and can be connected to devices that support the SDIO interface.
- CLK signal: clock signal sent from the host to the device
- VDD signal: power signal
- VSS signal: ground signal
- D0-3 signal: four data lines. The DAT1 signal cable is multiplexed as the interrupt line. In 1-bit mode, DAT0 is used to transmit data. In 4-bit mode, DAT0 to DAT3 are used to transmit data.
- CMD signal: used by the host to send commands and the device to respond to commands.
SDIO is widely used. Currently, many smartphones support SDIO, and many SDIO peripherals are developed for connections to smartphones. Common SDIO peripherals include WLAN, GPS, cameras, and Bluetooth.
**Figure 1** Connections between the host and devices in SDIO<a name="fig1185316527498"></a>
The SDIO bus has two ends, named host and device. All communication starts when the host sends a command. The device can communicate with the host as long as it can parse the command of the host. An SDIO host can connect to multiple devices, as shown in the figure below.
- CLK signal: clock signal sent from the host to the device
- VDD signal: power signal
- VSS signal: ground signal
- D0-3 signal: four data lines. The DAT1 signal cable is multiplexed as the interrupt line. In 1-bit mode, DAT0 is used to transmit data. In 4-bit mode, DAT0 to DAT3 are used to transmit data.
- CMD signal: used by the host to send commands and the device to respond to commands.
**Figure 1** Connections between the host and devices in SDIO<a name="fig1185316527498"></a>
![](figures/en-us_image_0000001160971556.png)
![](figures/en-us_image_0000001160971556.png)
- The SDIO interface defines a set of common methods for operating an SDIO device, including opening and closing an SDIO controller, exclusively claiming and releasing the host, enabling and disabling devices, claiming and releasing an SDIO IRQ, reading and writing data based on SDIO, and obtaining and setting common information.
The SDIO interface defines a set of common methods for operating an SDIO device, including opening and closing an SDIO controller, exclusively claiming and releasing the host, enabling and disabling devices, claiming and releasing an SDIO IRQ, reading and writing data based on SDIO, and obtaining and setting common information.
## Available APIs<a name="section12601496259"></a>
**Table 1** APIs available for the SDIO driver
**Table 1** APIs available for the SDIO driver
<a name="table1731550155318"></a>
<table><thead align="left"><tr id="row1625342317507"><th class="cellrowborder" valign="top" width="21.07%" id="mcps1.2.4.1.1"><p id="p1779183435016"><a name="p1779183435016"></a><a name="p1779183435016"></a>Capability</p>
......@@ -141,7 +142,7 @@
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>![](../public_sys-resources/icon-note.gif) **NOTE:**<br>
>All functions provided in this document can be called only in kernel mode.
## Usage Guidelines<a name="section1878939192515"></a>
......@@ -150,18 +151,18 @@
[Figure 2](#fig1343742311264) illustrates the process of using an SDIO.
**Figure 2** Process of using an SDIO<a name="fig1343742311264"></a>
**Figure 2** Process of using an SDIO<a name="fig1343742311264"></a>
![](figures/en-us_image_0000001206291517.png)
### Opening an SDIO Controller<a name="section10782428132616"></a>
Before performing SDIO communication, obtain the device handle of an SDIO controller by calling **SdioOpen**. This function returns the device handle of the SDIO controller with a specified bus number.
Before performing SDIO communication, obtain the device handle of an SDIO controller by calling **SdioOpen**. This function returns the device handle of the SDIO controller with a specified bus number.
DevHandle SdioOpen\(int16\_t mmcBusNum, struct SdioFunctionConfig \*config\);
**Table 2** Parameters and return values of SdioOpen
**Table 2** Parameters and return values of SdioOpen
<a name="table1036944152712"></a>
<table><thead align="left"><tr id="row4370114192717"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p737074112720"><a name="p737074112720"></a><a name="p737074112720"></a>Parameter</p>
......@@ -219,7 +220,7 @@ After obtaining the device handle of an SDIO controller, exclusively claim the h
void SdioClaimHost\(DevHandle handle\);
**Table 3** Parameter description of SdioClaimHost
**Table 3** Parameter description of SdioClaimHost
<a name="table192822447271"></a>
<table><thead align="left"><tr id="row192829443279"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1128284452713"><a name="p1128284452713"></a><a name="p1128284452713"></a>Parameter</p>
......@@ -248,7 +249,7 @@ Before accessing a register, enable the SDIO device.
int32\_t SdioEnableFunc\(DevHandle handle\);
**Table 4** Parameters and return values of SdioEnableFunc
**Table 4** Parameters and return values of SdioEnableFunc
<a name="table144881047485"></a>
<table><thead align="left"><tr id="row8487204184815"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1648611415486"><a name="p1648611415486"></a><a name="p1648611415486"></a>Parameter</p>
......@@ -297,7 +298,7 @@ Before SDIO communication, claim an SDIO IRQ.
int32\_t SdioClaimIrq\(DevHandle handle, SdioIrqHandler \*handler\);
**Table 5** Parameters and return values of SdioClaimIrq
**Table 5** Parameters and return values of SdioClaimIrq
<a name="table1149014114815"></a>
<table><thead align="left"><tr id="row114891042488"><th class="cellrowborder" valign="top" width="49.980000000000004%" id="mcps1.2.3.1.1"><p id="p1348864164811"><a name="p1348864164811"></a><a name="p1348864164811"></a>Parameter</p>
......@@ -357,13 +358,13 @@ if (ret != 0) {
### Performing SDIO Communication<a name="section85661522153420"></a>
- Incrementally write a given length of data into the SDIO device.
- Incrementally write a given length of data into the SDIO device.
The corresponding function is as follows:
int32\_t SdioWriteBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**Table 6** Parameters and return values of SdioWriteBytes
**Table 6** Parameters and return values of SdioWriteBytes
<a name="table6887174174111"></a>
<table><thead align="left"><tr id="row10887144111419"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p181381751164113"><a name="p181381751164113"></a><a name="p181381751164113"></a>Parameter</p>
......@@ -423,13 +424,13 @@ if (ret != 0) {
}
```
- Incrementally read a given length of data from the SDIO device.
- Incrementally read a given length of data from the SDIO device.
The corresponding function is as follows:
int32\_t SdioReadBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**Table 7** Parameters and return values of SdioReadBytes
**Table 7** Parameters and return values of SdioReadBytes
<a name="table5783755152110"></a>
<table><thead align="left"><tr id="row19783355162116"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p635754142212"><a name="p635754142212"></a><a name="p635754142212"></a>Parameter</p>
......@@ -489,13 +490,13 @@ if (ret != 0) {
}
```
- Write a given length of data into the fixed address of an SDIO device.
- Write a given length of data into the fixed address of an SDIO device.
The corresponding function is as follows:
int32\_t SdioWriteBytesToFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\);
**Table 8** Parameters and return values of SdioWriteBytesToFixedAddr
**Table 8** Parameters and return values of SdioWriteBytesToFixedAddr
<a name="table1982918113010"></a>
<table><thead align="left"><tr id="row1582911114010"><th class="cellrowborder" valign="top" width="48.43%" id="mcps1.2.3.1.1"><p id="p28301411903"><a name="p28301411903"></a><a name="p28301411903"></a>Parameter</p>
......@@ -560,13 +561,13 @@ if (ret != 0) {
}
```
- Read a given length of data from the fixed address of an SDIO device.
- Read a given length of data from the fixed address of an SDIO device.
The corresponding function is as follows:
int32\_t SdioReadBytesFromFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\);
**Table 9** Parameters and return values of SdioReadBytesFromFixedAddr
**Table 9** Parameters and return values of SdioReadBytesFromFixedAddr
<a name="table2724132220115"></a>
<table><thead align="left"><tr id="row8724142214115"><th class="cellrowborder" valign="top" width="48.699999999999996%" id="mcps1.2.3.1.1"><p id="p16752055131112"><a name="p16752055131112"></a><a name="p16752055131112"></a>Parameter</p>
......@@ -632,13 +633,13 @@ if (ret != 0) {
```
- Writes a given length of data into the address space of SDIO function 0.
- Writes a given length of data into the address space of SDIO function 0.
Currently, only 1-byte data can be written. The corresponding function is as follows:
int32\_t SdioWriteBytesToFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**Table 10** Parameters and return values of SdioWriteBytesToFunc0
**Table 10** Parameters and return values of SdioWriteBytesToFunc0
<a name="table5339151811112"></a>
<table><thead align="left"><tr id="row2033991881120"><th class="cellrowborder" valign="top" width="49.94%" id="mcps1.2.3.1.1"><p id="p1116916499117"><a name="p1116916499117"></a><a name="p1116916499117"></a>Parameter</p>
......@@ -697,13 +698,13 @@ if (ret != 0) {
}
```
- Reads a given length of data from the address space of SDIO function 0.
- Reads a given length of data from the address space of SDIO function 0.
Currently, only 1-byte data can be read. The corresponding function is as follows:
int32\_t SdioReadBytesFromFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**Table 11** Parameters and return values of SdioReadBytesFromFunc0
**Table 11** Parameters and return values of SdioReadBytesFromFunc0
<a name="table1071931161814"></a>
<table><thead align="left"><tr id="row771918171819"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p71291418171813"><a name="p71291418171813"></a><a name="p71291418171813"></a>Parameter</p>
......@@ -768,7 +769,7 @@ After the SDIO communication, release the SDIO IRQ.
int32\_t SdioReleaseIrq\(DevHandle handle\);
**Table 12** Parameters and return values of SdioReleaseIrq
**Table 12** Parameters and return values of SdioReleaseIrq
<a name="table165006412481"></a>
<table><thead align="left"><tr id="row15499849482"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1549964114814"><a name="p1549964114814"></a><a name="p1549964114814"></a>Parameter</p>
......@@ -817,7 +818,7 @@ After the SDIO communication, disable the SDIO device.
int32\_t SdioDisableFunc\(DevHandle handle\);
**Table 13** Parameters and return values of SdioDisableFunc
**Table 13** Parameters and return values of SdioDisableFunc
<a name="table25012415481"></a>
<table><thead align="left"><tr id="row1050010474810"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p05002419488"><a name="p05002419488"></a><a name="p05002419488"></a>Parameter</p>
......@@ -866,7 +867,7 @@ After the SDIO communication, release the exclusively claimed host.
void SdioReleaseHost\(DevHandle handle\);
**Table 14** Parameter description of SdioReleaseHost
**Table 14** Parameter description of SdioReleaseHost
<a name="table1350214164813"></a>
<table><thead align="left"><tr id="row6502134194814"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p18501945486"><a name="p18501945486"></a><a name="p18501945486"></a>Parameter</p>
......@@ -897,7 +898,7 @@ void SdioClose\(DevHandle handle\);
This function releases the resources requested.
**Table 15** Parameter description of SdioClose
**Table 15** Parameter description of SdioClose
<a name="table950324124815"></a>
<table><thead align="left"><tr id="row1050213424819"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p18502134194818"><a name="p18502134194818"></a><a name="p18502134194818"></a>Parameter</p>
......@@ -1047,5 +1048,4 @@ ENABLE_ERR:
/* Close an SDIO controller. */
SdioClose(handle);
}
```
```
\ No newline at end of file
......@@ -3,9 +3,9 @@
## Overview<a name="section1347805272150053"></a>
A Secure Digital Input Output \(SDIO\) card is an extension of the SD specification to cover I/O functions. SD and SDIO are called multimedia card \(MMCs\). In the Hardware Driver Foundation \(HDF\) framework, the SDIO module 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.
A Secure Digital Input Output \(SDIO\) card is an extension of the SD specification to cover I/O functions. SD and SDIO cards are called multimedia cards \(MMCs\). In the Hardware Driver Foundation \(HDF\) framework, the SDIO module 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.
**Figure 1** Independent service mode<a name="fig124181331222"></a>
**Figure 1** Independent service mode<a name="fig124181331222"></a>
![](figures/independent-service-mode.png "independent-service-mode-12")
## Available APIs<a name="section752964871810"></a>
......@@ -35,7 +35,7 @@ struct SdioDeviceOps {
};
```
**Table 1** Callbacks for the members in the SdioDeviceOps structure
**Table 1** Callbacks for the members in the SdioDeviceOps structure
<a name="table878215448417"></a>
<table><thead align="left"><tr id="row17784344241"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p67842444414"><a name="p67842444414"></a><a name="p67842444414"></a>Callback</p>
......@@ -263,35 +263,33 @@ struct SdioDeviceOps {
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **NOTE**
>![](../public_sys-resources/icon-note.gif) **NOTE**<br>
>CommonInfo includes the following information:
>- **maxBlockNum**: specifies the maximum number of blocks in a request.
>- **maxBlockSize**: specifies the maximum number of bytes in a block.
>- **maxRequestSize**: specifies the maximum number of bytes in a request.
>- **enTimeout**: specifies the maximum timeout period, in milliseconds.
>- **funcNum**: specifies the function number, which ranges from **1** to **7**.
>- **irqCap**: specifies the interrupt request \(IRQ\) capabilities.
>- **\(void \*\)data**
>- **maxBlockNum**: specifies the maximum number of blocks in a request.
>- **maxBlockSize**: specifies the maximum number of bytes in a block.
>- **maxRequestSize**: specifies the maximum number of bytes in a request.
>- **enTimeout**: specifies the maximum timeout period, in milliseconds.
>- **funcNum**: specifies the function number, which ranges from **1** to **7**.
>- **irqCap**: specifies the interrupt request \(IRQ\) capabilities.
>- **\(void \*\)data**
## How to Develop<a name="section581179475150053"></a>
The SDIO 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.
- 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 **sdio\_config.hcs** file.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **sdio\_config.hcs** file.
3. Instantiate the SDIO controller object.
- Initialize **SdioDevice**.
- Instantiate **SdioDeviceOps** in the **SdioDevice** object.
>![](../public_sys-resources/icon-note.gif) **NOTE**
- Initialize **SdioDevice**.
- Instantiate **SdioDeviceOps** in the **SdioDevice** object.
>![](../public_sys-resources/icon-note.gif) **NOTE**<br>
>For details, see [Available APIs](#available-apis).
......@@ -301,11 +299,11 @@ The SDIO module adaptation involves the following steps:
## Development Example<a name="section2112250242150053"></a>
The following uses **sdio\_adapter.c** as an example to present the contents that need to be provided by the vendor to implement device functions.
The following uses **sdio\_adapter.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, 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.
1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, 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.
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.
- SDIO driver entry reference
......@@ -315,17 +313,17 @@ The following uses **sdio\_adapter.c** as an example to present the contents t
.Bind = Hi35xxLinuxSdioBind, // See the Bind function.
.Init = Hi35xxLinuxSdioInit, // See the Init function.
.Release = Hi35xxLinuxSdioRelease// See the Release function.
.moduleName = "HDF_PLATFORM_SDIO",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
.moduleName = "HDF_PLATFORM_SDIO",// (Mandatory) The value must be the same as that of moduleName in the **.hcs** file.
};
// Call HDF_INIT to register the driver entry with the HDF.
HDF_INIT(g_sdioDriverEntry);
```
2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **sdio\_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 **SdioDevice** members at the core layer.
2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **sdio\_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 **SdioDevice** members at the core layer.
In this example, there is only one SDIO controller. If there are multiple SDIO controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **sdio\_config** file.
In this example, there is only one SDIO controller. If there are multiple SDIO controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **sdio\_config** file.
- **device\_info.hcs** configuration reference
- **device\_info.hcs** configuration reference
```
root {
......@@ -349,7 +347,7 @@ The following uses **sdio\_adapter.c** as an example to present the contents t
}
```
- **sdio\_config.hcs** configuration reference
- **sdio\_config.hcs** configuration reference
```
root {
......@@ -357,8 +355,8 @@ The following uses **sdio\_adapter.c** as an example to present the contents t
sdio_config {
template sdio_controller {
match_attr = "";
hostId = 2; // (Mandatory) It is set to 2. For details, see mmc_config.hcs.
devType = 2; // (Mandatory) It is set to 2. For details, see mmc_config.hcs.
hostId = 2; // (Mandatory) Set the value to 2. For details, see mmc_config.hcs.
devType = 2; // (Mandatory) Set the value to 2. For details, see mmc_config.hcs.
}
controller_0x2dd1 :: sdio_controller {
match_attr = "hisilicon_hi35xx_sdio_0";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
......@@ -367,11 +365,11 @@ The following uses **sdio\_adapter.c** as an example to present the contents t
}
```
3. Initialize the **SdioDevice** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **SdioDeviceOps** \(used to call underlying functions of the driver\) in **SdioDevice**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\).
3. Initialize the **SdioDevice** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **SdioDeviceOps** \(used to call underlying functions of the driver\) in **SdioDevice**, 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 **sdio\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values are also passed to the objects at the core layer.
To the driver, the custom structure carries parameters and data. The values in the **sdio\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values are also passed to the objects at the core layer.
```
typedef struct {
......@@ -399,7 +397,7 @@ The following uses **sdio\_adapter.c** as an example to present the contents t
};
```
- Instantiate the callback function structure **SdioDeviceOps** in **SdioDevice**. Other members are initialized by using the **Init** function.
- Instantiate the callback function structure **SdioDeviceOps** in **SdioDevice**. Other members are initialized by using the **Init** function.
```
static struct SdioDeviceOps g_sdioDeviceOps = {
......@@ -427,13 +425,13 @@ The following uses **sdio\_adapter.c** as an example to present the contents t
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
**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.\)
HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\)
**Table 2** Input parameters and return values of the Bind function
**Table 2** Input parameters and return values of the Bind function
<a name="table297118388199"></a>
<table><thead align="left"><tr id="row197133831916"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1972138191917"><a name="p1972138191917"></a><a name="p1972138191917"></a>Status (Value)</p>
......@@ -477,7 +475,7 @@ The following uses **sdio\_adapter.c** as an example to present the contents t
Function description:
Initializes the custom structure object and **SdioCntlr**, calls the **SdioCntlrAdd** function at the core layer, and performs other initialization operations customized by the vendor.
Initializes the custom structure object and **SdioCntlr**, calls the **SdioCntlrAdd** function at the core layer, and performs other initialization operations customized by the vendor.
```
static int32_t Hi35xxLinuxSdioBind(struct HdfDeviceObject *obj)
......@@ -513,7 +511,7 @@ The following uses **sdio\_adapter.c** as an example to present the contents t
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the **.hcs** configuration file information.
Return values:
......@@ -536,7 +534,7 @@ The following uses **sdio\_adapter.c** as an example to present the contents t
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the **.hcs** configuration file information.
Return values:
......@@ -544,7 +542,7 @@ The following uses **sdio\_adapter.c** as an example to present the contents t
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 **Bind** function has the corresponding value assignment operations.
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 **Bind** function has the corresponding value assignment operations.
```
......@@ -555,6 +553,4 @@ The following uses **sdio\_adapter.c** as an example to present the contents t
}
Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);// (Mandatory) Custom function for releasing memory. A forced conversion from HdfDeviceObject to MmcCntlr is involved.
}
```
```
\ No newline at end of file
......@@ -3,22 +3,22 @@
## 概述
- SDIO是安全数字输入输出接口(Secure Digital Input and Output)的缩写,是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD内存卡,并且可以连接支持SDIO接口的设备。
SDIO是安全数字输入输出接口(Secure Digital Input and Output)的缩写,是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD内存卡,并且可以连接支持SDIO接口的设备。
- SDIO的应用比较广泛,目前,有许多手机都支持SDIO功能,并且很多SDIO外设也被开发出来,使得手机外接外设更加容易。常见的SDIO外设有WLAN、GPS、CAMERA、蓝牙等。
SDIO的应用比较广泛,目前,有许多手机都支持SDIO功能,并且很多SDIO外设也被开发出来,使得手机外接外设更加容易。常见的SDIO外设有WLAN、GPS、CAMERA、蓝牙等。
- SDIO总线有两端,其中一端是主机端(HOST),另一端是设备端(DEVICE)。所有的通信都是由HOST端发出命令开始的,在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信了。SDIO的HOST可以连接多个DEVICE,如下图所示:
- CLK信号:HOST给DEVICE的时钟信号。
- VDD信号:电源信号。
- VSS信号:Ground信号。
- D0-3信号:4条数据线,其中,DAT1信号线复用为中断线,在1BIT模式下DAT0用来传输数据,在4BIT模式下DAT0-DAT3用来传输数据。
- CMD信号:用于HOST发送命令和DEVICE回复响应。
SDIO总线有两端,其中一端是主机端(HOST),另一端是设备端(DEVICE)。所有的通信都是由HOST端发出命令开始的,在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信了。SDIO的HOST可以连接多个DEVICE,如下图所示:
- CLK信号:HOST给DEVICE的时钟信号。
- VDD信号:电源信号。
- VSS信号:Ground信号。
- D0-3信号:4条数据线,其中,DAT1信号线复用为中断线,在1BIT模式下DAT0用来传输数据,在4BIT模式下DAT0-DAT3用来传输数据。
- CMD信号:用于HOST发送命令和DEVICE回复响应。
**图1** SDIO的HOST-DEVICE连接示意图
**图1** SDIO的HOST-DEVICE连接示意图
![image](figures/SDIO的HOST-DEVICE连接示意图.png "SDIO的HOST-DEVICE连接示意图")
![image](figures/SDIO的HOST-DEVICE连接示意图.png "SDIO的HOST-DEVICE连接示意图")
- SDIO接口定义了操作SDIO的通用方法集合,包括打开/关闭SDIO控制器、独占/释放HOST、使能/去使能设备、申请/释放中断、读写、获取/设置公共信息等。
SDIO接口定义了操作SDIO的通用方法集合,包括打开/关闭SDIO控制器、独占/释放HOST、使能/去使能设备、申请/释放中断、读写、获取/设置公共信息等。
## 接口说明
......@@ -36,7 +36,7 @@
| SDIO使能/去使能功能设备接口 | -&nbsp;SdioEnableFunc:使能SDIO功能设备<br/>-&nbsp;SdioDisableFunc:去使能SDIO功能设备 |
| SDIO申请/释放中断接口 | -&nbsp;SdioClaimIrq:申请中断<br/>-&nbsp;SdioReleaseIrq:释放中断 |
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**<br>
> 本文涉及的所有接口,目前只支持在内核态使用,不支持在用户态使用。
......
......@@ -3,7 +3,7 @@
## 概述
SDIO由SD卡发展而来,被统称为mmc(MultiMediaCard),相关技术差别不大,在HDF框架中,SDIO的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
SDIO由SD卡发展而来,被统称为mmc(MultiMediaCard),相关技术差别不大。在HDF框架中,SDIO的接口适配模式采用独立服务模式。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
**图1** SDIO独立服务模式结构图
......@@ -42,26 +42,26 @@ struct SdioDeviceOps {
| 函数 | 入参 | 出参 | 返回值 | 功能 |
| -------- | -------- | -------- | -------- | -------- |
| incrAddrReadBytes | dev:&nbsp;结构体指针,SDIO设备控制器;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小 | data:&nbsp;uint8_t指针,传出值; | HDF_STATUS相关状态 | 从指定的SDIO地址增量读取给定长度的数据 |
| incrAddrWriteBytes | dev:&nbsp;结构体指针,SDIO设备控制器;data:&nbsp;uint8_t指针,传入值;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小 | 无 | HDF_STATUS相关状态 | 将给定长度的数据增量写入指定的SDIO地址 |
| fixedAddrReadBytes | dev:&nbsp;结构体指针,SDIO设备控制器;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小;scatterLen:&nbsp;uint32_t,数据长度; | data:&nbsp;uint8_t指针,传出值; | HDF_STATUS相关状态 | 从固定SDIO地址读取给定长度的数据。 |
| fixedAddrWriteBytes | dev:&nbsp;结构体指针,SDIO设备控制器;data:&nbsp;uint8_t指针,传入值;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小;scatterLen:&nbsp;uint32_t,数据长度; | 无 | HDF_STATUS相关状态 | 将给定长度的数据写入固定SDIO地址 |
| func0ReadBytes | dev:&nbsp;结构体指针,SDIO设备控制器;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小; | data:&nbsp;uint8_t指针,传出值; | HDF_STATUS相关状态 | 从SDIO函数0的地址空间读取给定长度的数据。 |
| func0WriteBytes | dev:&nbsp;结构体指针,SDIO设备控制器;data:&nbsp;uint8_t指针,传入值;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小; | 无 | HDF_STATUS相关状态 | 将给定长度的数据写入SDIO函数0的地址空间。 |
| setBlockSize | dev:&nbsp;结构体指针,SDIO设备控制器;blockSize:&nbsp;uint32_t,Block大小 | 无 | HDF_STATUS相关状态 | 设置block大小 |
| getCommonInfo | dev:&nbsp;联合体指针,SDIO设备控制器;infoType:&nbsp;uint32_t,info类型; | info:&nbsp;结构体指针,传出SdioFuncInfo信息; | HDF_STATUS相关状态 | 获取CommonInfo,说明见下 |
| setCommonInfo | dev:&nbsp;结构体指针,SDIO设备控制器;info:&nbsp;联合体指针,SdioFuncInfo信息传入;infoType:&nbsp;uint32_t,info类型; | 无 | HDF_STATUS相关状态 | 设置CommonInfo,说明见下 |
| flushData | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 当SDIO需要重新初始化或发生意外错误时调用的函数 |
| enableFunc | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 使能SDIO设备 |
| disableFunc | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 去使能SDIO设备 |
| claimIrq | dev:&nbsp;结构体指针,SDIO设备控制器;irqHandler:&nbsp;void函数指针; | 无 | HDF_STATUS相关状态 | 注册SDIO中断 |
| releaseIrq | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 释放SDIO中断 |
| findFunc | dev:&nbsp;结构体指针,SDIO设备控制器;configData:&nbsp;结构体指针,&nbsp;SDIO函数关键信息 | 无 | HDF_STATUS相关状态 | 寻找匹配的funcNum |
| claimHost | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 独占HOST |
| releaseHost | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 释放HOST |
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> CommonInfo包括maxBlockNum(单个request中最大block数), maxBlockSize(单个block最大字节数), maxRequestSize(单个Request最大字节数), enTimeout(最大超时时间,毫秒), funcNum(功能编号1~7), irqCap(IRQ capabilities), (void \*)data.
| incrAddrReadBytes | dev:结构体指针,SDIO设备控制器<br>addr:uint32_t,地址值<br>size:uint32_t,大小 | data:uint8_t指针,传出值 | HDF_STATUS相关状态 | 从指定的SDIO地址增量读取给定长度的数据 |
| incrAddrWriteBytes | dev:结构体指针,SDIO设备控制器<br>data:uint8_t指针,传入值<br>addr:uint32_t,地址值<br>size:uint32_t,大小 | 无 | HDF_STATUS相关状态 | 将给定长度的数据增量写入指定的SDIO地址 |
| fixedAddrReadBytes | dev:结构体指针,SDIO设备控制器<br>addr:uint32_t,地址值<br>size:uint32_t,大小<br>scatterLen:uint32_t,数据长度 | data:uint8_t指针,传出值 | HDF_STATUS相关状态 | 从固定SDIO地址读取给定长度的数据。 |
| fixedAddrWriteBytes | dev:结构体指针,SDIO设备控制器<br>data:uint8_t指针,传入值<br>addr:uint32_t,地址值<br>size:uint32_t,大小<br>scatterLen:uint32_t,数据长度 | 无 | HDF_STATUS相关状态 | 将给定长度的数据写入固定SDIO地址 |
| func0ReadBytes | dev:结构体指针,SDIO设备控制器<br>addr:uint32_t,地址值<br>size:uint32_t,大小 | data:uint8_t指针,传出值 | HDF_STATUS相关状态 | 从SDIO函数0的地址空间读取给定长度的数据。 |
| func0WriteBytes | dev:结构体指针,SDIO设备控制器<br>data:uint8_t指针,传入值<br>addr:uint32_t,地址值<br>size:uint32_t,大小 | 无 | HDF_STATUS相关状态 | 将给定长度的数据写入SDIO函数0的地址空间。 |
| setBlockSize | dev:结构体指针,SDIO设备控制器<br>blockSize:uint32_t,Block大小 | 无 | HDF_STATUS相关状态 | 设置block大小 |
| getCommonInfo | dev:联合体指针,SDIO设备控制器<br>infoType:uint32_t,info类型 | info:结构体指针,传出SdioFuncInfo信息 | HDF_STATUS相关状态 | 获取CommonInfo,说明见下 |
| setCommonInfo | dev:结构体指针,SDIO设备控制器<br>info:联合体指针,SdioFuncInfo信息传入<br>infoType:uint32_t,info类型 | 无 | HDF_STATUS相关状态 | 设置CommonInfo,说明见下 |
| flushData | dev:结构体指针,SDIO设备控制器 | 无 | HDF_STATUS相关状态 | 当SDIO需要重新初始化或发生意外错误时调用的函数 |
| enableFunc | dev:结构体指针,SDIO设备控制器 | 无 | HDF_STATUS相关状态 | 使能SDIO设备 |
| disableFunc | dev:结构体指针,SDIO设备控制器 | 无 | HDF_STATUS相关状态 | 去使能SDIO设备 |
| claimIrq | dev:结构体指针,SDIO设备控制器<br>irqHandler:void函数指针 | 无 | HDF_STATUS相关状态 | 注册SDIO中断 |
| releaseIrq | dev:结构体指针,SDIO设备控制器 | 无 | HDF_STATUS相关状态 | 释放SDIO中断 |
| findFunc | dev:结构体指针,SDIO设备控制器<br>configData:结构体指针,SDIO函数关键信息 | 无 | HDF_STATUS相关状态 | 寻找匹配的funcNum |
| claimHost | dev:结构体指针,SDIO设备控制器 | 无 | HDF_STATUS相关状态 | 独占HOST |
| releaseHost | dev:结构体指针,SDIO设备控制器 | 无 | HDF_STATUS相关状态 | 释放HOST |
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**<br>
> CommonInfo包括maxBlockNum(单个request中最大block数), maxBlockSize(单个block最大字节数), maxRequestSize(单个Request最大字节数), enTimeout(最大超时时间,毫秒), funcNum(功能编号1~7), irqCap(IRQ capabilities), (void \*)data.
## 开发步骤
......@@ -79,7 +79,7 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
3. **实例化SDIO控制器对象:**
- 初始化SdioDevice成员。
- 实例化SdioDevice成员SdioDeviceOps。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**<br>
> 实例化SdioDevice成员SdioDeviceOps,其定义和成员说明见[接口说明](#接口说明)。
4. **驱动调试:**
......@@ -98,12 +98,12 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
```
struct HdfDriverEntry g_sdioDriverEntry = {
.moduleVersion = 1,
.Bind = Hi35xxLinuxSdioBind, //见Bind参考
.Init = Hi35xxLinuxSdioInit, //见Init参考
.Release = Hi35xxLinuxSdioRelease,//见Release参考
.moduleName = "HDF_PLATFORM_SDIO",//【必要 且与 HCS文件中里面的moduleName匹配】
.Bind = Hi35xxLinuxSdioBind, // 见Bind参考
.Init = Hi35xxLinuxSdioInit, // 见Init参考
.Release = Hi35xxLinuxSdioRelease,// 见Release参考
.moduleName = "HDF_PLATFORM_SDIO",// 【必要,且与HCS文件中里面的moduleName匹配】
};
//调用HDF_INIT将驱动入口注册到HDF框架中
// 调用HDF_INIT将驱动入口注册到HDF框架中
HDF_INIT(g_sdioDriverEntry);
```
......@@ -124,9 +124,9 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
policy = 1;
priority = 70;
permission = 0644;
moduleName = "HDF_PLATFORM_SDIO"; //【必要】用于指定驱动名称,需要与驱动Entry中的moduleName一致;
serviceName = "HDF_PLATFORM_MMC_2"; //【必要】驱动对外发布服务的名称,必须唯一
deviceMatchAttr = "hisilicon_hi35xx_sdio_0";//【必要】用于配置控制器私有数据,要与sdio_config.hcs中对应控制器保持一致
moduleName = "HDF_PLATFORM_SDIO"; // 【必要】用于指定驱动名称,需要与驱动Entry中的moduleName一致;
serviceName = "HDF_PLATFORM_MMC_2"; // 【必要】驱动对外发布服务的名称,必须唯一
deviceMatchAttr = "hisilicon_hi35xx_sdio_0";// 【必要】用于配置控制器私有数据,要与sdio_config.hcs中对应控制器保持一致
}
}
}
......@@ -143,11 +143,11 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
sdio_config {
template sdio_controller {
match_attr = "";
hostId = 2; //【必要】模式固定为2,在mmc_config.hcs有介绍
devType = 2; //【必要】模式固定为2,在mmc_config.hcs有介绍
hostId = 2; // 【必要】模式固定为2,在mmc_config.hcs有介绍
devType = 2; // 【必要】模式固定为2,在mmc_config.hcs有介绍
}
controller_0x2dd1 :: sdio_controller {
match_attr = "hisilicon_hi35xx_sdio_0";//【必要】需要和device_info.hcs中的deviceMatchAttr值一致
match_attr = "hisilicon_hi35xx_sdio_0";// 【必要】需要和device_info.hcs中的deviceMatchAttr值一致
}
}
}
......@@ -170,7 +170,7 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
void *data; // 私有数据
} SdioFuncInfo;
//SdioDevice是核心层控制器结构体,其中的成员在Bind函数中会被赋值
// SdioDevice是核心层控制器结构体,其中的成员在Bind函数中会被赋值
struct SdioDevice {
struct SdDevice sd;
struct SdioDeviceOps *sdioOps;
......@@ -212,11 +212,11 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
入参:
HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。
HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。
返回值:
HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
**表2** Bind函数入参及返回值
| 状态(值) | 问题描述 |
......@@ -241,18 +241,18 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
...
cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));// 分配内存
...
cntlr->ops = &g_sdioCntlrOps; //【必要】struct MmcCntlrOps g_sdioCntlrOps={
cntlr->ops = &g_sdioCntlrOps; // 【必要】struct MmcCntlrOps g_sdioCntlrOps={
// .rescanSdioDev = Hi35xxLinuxSdioRescan,};
cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提
obj->service = &cntlr->service;//【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提
cntlr->hdfDevObj = obj; // 【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提
obj->service = &cntlr->service;// 【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提
ret = Hi35xxLinuxSdioCntlrParse(cntlr, obj);//【必要】初始化cntlr 的 index, devType, 失败则 goto _ERR;
...
ret = MmcCntlrAdd(cntlr); //【必要】调用核心层mmc_core.c的函数, 失败则 goto _ERR;
ret = MmcCntlrAdd(cntlr); // 【必要】调用核心层mmc_core.c的函数, 失败则 goto _ERR;
...
ret = MmcCntlrAllocDev(cntlr, (enum MmcDevType)cntlr->devType);//【必要】调用核心层mmc_core.c的函数, 失败则 goto _ERR;
ret = MmcCntlrAllocDev(cntlr, (enum MmcDevType)cntlr->devType);// 【必要】调用核心层mmc_core.c的函数, 失败则 goto _ERR;
...
MmcDeviceAddOps(cntlr->curDev, &g_sdioDeviceOps);//【必要】调用核心层mmc_core.c的函数, 钩子函数挂载
MmcDeviceAddOps(cntlr->curDev, &g_sdioDeviceOps);// 【必要】调用核心层mmc_core.c的函数, 钩子函数挂载
HDF_LOGD("Hi35xxLinuxSdioBind: Success!");
return HDF_SUCCESS;
......@@ -267,7 +267,7 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
入参:
HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。
HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。
返回值:
......@@ -281,7 +281,7 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
```
static int32_t Hi35xxLinuxSdioInit(struct HdfDeviceObject *obj)
{
(void)obj;//无操作,可根据厂商需要添加
(void)obj;// 无操作,可根据厂商需要添加
HDF_LOGD("Hi35xxLinuxSdioInit: Success!");
return HDF_SUCCESS;
}
......@@ -290,7 +290,7 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
入参:
HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。
HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。
返回值:
......@@ -298,7 +298,7 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
函数说明:
释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作前提是在Bind函数中具备对应赋值的操作。
释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。所有强制转换获取相应对象的操作前提是在Bind函数中具备对应赋值的操作。
```
......@@ -307,6 +307,6 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
if (obj == NULL) {
return;
}
Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);//【必要】自定义的内存释放函数,这里有HdfDeviceObject到MmcCntlr的强制转化
Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);// 【必要】自定义的内存释放函数,这里有HdfDeviceObject到MmcCntlr的强制转化
}
```
```
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册