1# 器件驱动移植
2
3
4本章节讲解如何移植各类器件驱动。
5
6
7## LCD驱动移植
8
9移植LCD驱动的主要工作是编写一个驱动,在驱动中生成模型的实例,并完成注册。
10
11这些LCD的驱动被放置在源码目录`//drivers/hdf_core/framework/model/display/driver/panel`中。
12
131. 创建Panel驱动
14
15   创建HDF驱动,在驱动初始化中调用RegisterPanel接口注册模型实例。如:
16
17
18   ```
19   int32_t LCDxxEntryInit(struct HdfDeviceObject *object)
20   {
21       struct PanelData *panel = CreateYourPanel();
22       // 注册模型实例
23       if (RegisterPanel(panel) != HDF_SUCCESS) {
24           HDF_LOGE("%s: RegisterPanel failed", __func__);
25           return HDF_FAILURE;
26       }
27       return HDF_SUCCESS;
28   }
29
30   struct HdfDriverEntry g_xxxxDevEntry = {
31       .moduleVersion = 1,
32       .moduleName = "LCD_XXXX",
33       .Init = LCDxxEntryInit,
34   };
35
36   HDF_INIT(g_xxxxDevEntry);
37   ```
38
392. 配置加载panel驱动
40
41   产品的所有设备信息被定义在源码文件`//vendor/vendor_name/product_name/config/device_info/device_info.hcs`中。修改该文件,在display的host中,名为device_lcd的device中增加配置。
42
43   > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**
44   > moduleName 要与panel驱动中的moduleName相同。
45
46
47   ```
48   root {
49       ...
50       display :: host {
51           device_lcd :: device {
52                   deviceN :: deviceNode {
53                       policy = 0;
54                       priority = 100;
55                       preload = 2;
56                       moduleName = "LCD_XXXX";
57                   }
58           }
59       }
60   }
61   ```
62
63
64## TP驱动移植
65
66本节描述如何移植触摸屏驱动。触摸屏的器件驱动被放置在源码目录`//drivers/hdf_core/framework/model/input/driver/touchscreen`中。 移植触摸屏驱动主要工作是向系统注册ChipDevice模型实例。
67
68详细的驱动开发指导,请参考 [TOUCHSCREEN开发指导](../driver/driver-peripherals-touch-des.md)。
69
701. 创建触摸屏器件驱动
71
72   在上述touchscreen目录中创建名为`touch_ic_name.c`的文件。编写如下内容
73
74
75   ```
76   #include "hdf_touch.h"
77
78   static int32_t HdfXXXXChipInit(struct HdfDeviceObject *device)
79   {
80       ChipDevice *tpImpl = CreateXXXXTpImpl();
81       if(RegisterChipDevice(tpImpl) != HDF_SUCCESS) { // 注册ChipDevice模型
82           ReleaseXXXXTpImpl(tpImpl);
83           return HDF_FAILURE;
84       }
85       return HDF_SUCCESS;
86   }
87
88   struct HdfDriverEntry g_touchXXXXChipEntry = {
89       .moduleVersion = 1,
90       .moduleName = "HDF_TOUCH_XXXX", // 注意这里的moduleName要与后续的配置完全一致
91       .Init = HdfXXXXChipInit,
92   };
93
94   HDF_INIT(g_touchXXXXChipEntry);
95   ```
96
97   其中ChipDevice中要实现如下方法:
98
99     | 方法 | 实现说明 |
100   | -------- | -------- |
101   | int32_t (\*Init)(ChipDevice \*device) | 实现器件初始化 |
102   | int32_t (\*Detect)(ChipDevice \*device) | 实现器件探测 |
103   | int32_t (\*Suspend)(ChipDevice \*device) | 实现器件休眠 |
104   | int32_t (\*Resume)(ChipDevice \*device) | 实现器件唤醒 |
105   | int32_t (\*DataHandle)(ChipDevice \*device) | 需要实现从器件读取数据,将触摸点数据填写入device->driver->frameData中 |
106   | int32_t (\*UpdateFirmware)(ChipDevice \*device) | 实现固件升级 |
107
1082. 配置产品,加载器件驱动
109
110   产品的所有设备信息被定义在源码文件`//vendor/vendor_name/product_name/config/device_info/device_info.hcs`中。修改该文件,在名为input的host中,名为device_touch_chip的device中增加配置。
111
112   > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
113   > moduleName 要与触摸屏驱动中的moduleName相同。
114
115
116   ```
117   deviceN :: deviceNode {
118       policy = 0;
119       priority = 130;
120       preload = 0;
121       permission = 0660;
122       moduleName = "HDF_TOUCH_XXXX";
123       deviceMatchAttr = "touch_XXXX_configs";
124   }
125   ```
126
127
128## WLAN驱动移植
129
130WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负责处理WLAN流量。
131
132  **图1** OpenHarmony WLAN结构示意图
133
134  ![zh-cn_image_0000001207756867](figures/zh-cn_image_0000001207756867.png)
135
136如图1,左半部分负责管理WLAN设备,右半部分负责WLAN流量。HDF WLAN分别为这两部分做了抽象,驱动的移植过程可以看做分别实现这两部分所需接口。这些接口有:
137
138| 接口 | 定义头文件 | 接口说明 |
139| -------- | -------- | -------- |
140| HdfChipDriverFactory | drivers\hdf_core\framework\include\wifi\hdf_wlan_chipdriver_manager.h | ChipDriver的Factory,用于支持一个芯片多个WLAN端口 |
141| HdfChipDriver | drivers\hdf_core\framework\include\wifi\wifi_module.h | 每个WLAN端口对应一个HdfChipDriver,用来管理一个特定端口 |
142| NetDeviceInterFace | drivers\hdf_core\framework\include\wifi\net_device.h | 与协议栈之间的接口,如发送数据、设置网络接口状态等 |
143
144> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
145> 详细的接口开发指导,请参考[WLAN开发](../driver/driver-peripherals-external-des.md)。
146
147具体的移植步骤如下:
148
1491. 创建HDF WLAN芯片驱动
150
151   在目录`/device/vendor_name/peripheral/wifi/chip_name/`创建文件`hdf_wlan_chip_name.c`。内容模板如下:
152
153
154   ```
155   static int32_t HdfWlanXXXChipDriverInit(struct HdfDeviceObject *device) {
156       static struct HdfChipDriverFactory factory = CreateChipDriverFactory(); // 需要移植者实现的方法
157       struct HdfChipDriverManager *driverMgr = HdfWlanGetChipDriverMgr();
158       if (driverMgr->RegChipDriver(&factory) != HDF_SUCCESS) { // 注册驱动工厂
159           HDF_LOGE("%s fail: driverMgr is NULL!", __func__);
160           return HDF_FAILURE;
161       }
162       return HDF_SUCCESS;
163   }
164
165   struct HdfDriverEntry g_hdfXXXChipEntry = {
166       .moduleVersion = 1,
167       .Init = HdfWlanXXXChipDriverInit,
168       .Release = HdfWlanXXXChipRelease,
169       .moduleName = "HDF_WIFI_CHIP_XXX" // 注意:这个名字要与配置一致
170   };
171
172   HDF_INIT(g_hdfXXXChipEntry);
173   ```
174
175   在上述代码的CreateChipDriverFactory方法中,需要创建一个HdfChipDriverFactory类型的对象。该对象提供如下方法:
176
177     | 接口 | 说明 |
178   | -------- | -------- |
179   | const char \*driverName | 当前driverName |
180   | int32_t (\*InitChip)(struct HdfWlanDevice \*device) | 初始化芯片 |
181   | int32_t (\*DeinitChip)(struct HdfWlanDevice \*device) | 去初始化芯片 |
182   | void (\*ReleaseFactory)(struct HdfChipDriverFactory \*factory) | 释放HdfChipDriverFactory对象 |
183   | struct HdfChipDriver \*(\*Build)(struct HdfWlanDevice \*device, uint8_t ifIndex) | 创建一个HdfChipDriver;输入参数中,device是设备信息,ifIndex是当前创建的接口在这个芯片中的序号 |
184   | void (\*Release)(struct HdfChipDriver \*chipDriver) | 释放chipDriver |
185   | uint8_t (\*GetMaxIFCount)(struct HdfChipDriverFactory \*factory) | 获取当前芯片支持的最大接口数 |
186
187   其中Build方法负责创建一个管理指定网络接口的对象HdfChipDriver。该对象需要提供方法:
188
189     | 接口 | 说明 |
190   | -------- | -------- |
191   | int32_t (\*init)(struct HdfChipDriver \*chipDriver, NetDevice \*netDev) | 初始化当前网络接口,这里需要向netDev提供接口NetDeviceInterFace |
192   | int32_t (\*deinit)(struct HdfChipDriver \*chipDriver, NetDevice \*netDev) | 去初始化当前网络接口 |
193   | struct HdfMac80211BaseOps \*ops | WLAN基础能力接口集 |
194   | struct HdfMac80211STAOps \*staOps | 支持STA模式所需的接口集 |
195   | struct HdfMac80211APOps \*apOps | 支持AP模式所需要的接口集 |
196
1972. 编写配置文件描述驱动支持的芯片
198
199   在产品配置目录下创建芯片的配置文件,保存至源码路径`//vendor/vendor_name/product_name/config/wifi/wlan_chip_chip_name.hcs`
200
201   该文件模板如下:
202
203
204   ```
205   root {
206       wlan_config {
207           chip_name :& chipList {
208               chip_name :: chipInst {
209                   match_attr = "hdf_wlan_chips_chip_name"; /* 这是配置匹配属性,用于提供驱动的配置根 */
210                   driverName = "driverName"; /* 需要与HdfChipDriverFactory中的driverName相同*/
211                   sdio {
212                       vendorId = 0xXXXX; /* your vendor id */
213                       deviceId = [0xXXXX]; /*your supported devices */
214                   }
215               }
216           }
217       }
218   }
219   ```
220
221   > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
222   >
223   > 路径和文件中的vendor_name、product_name、chip_name请替换成实际名称。
224   >
225   > vendorId 和 deviceId需要根据实际芯片的识别码进行填写。
226
2273. 编写配置文件,加载驱动
228
229   产品的所有设备信息被定义在源码文件`//vendor/vendor_name/product_name/config/device_info/device_info.hcs`中。修改该文件,在名为network的host中,名为device_wlan_chips的device中增加配置。模板如下:
230
231
232   ```
233   deviceN :: deviceNode {
234       policy = 0;
235       preload = 2;
236       moduleName = "HDF_WLAN_CHIPS";
237       deviceMatchAttr = "hdf_wlan_chips_chip_name";
238       serviceName = "driverName";
239   }
240   ```
241
242   > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
243   > moduleName 要与HDF WLAN 芯片驱动中的moduleName相同。
244
2454. 修改Kconfig文件,让移植的WLAN模组出现再内核配置中
246
247   在`device/vendor_name/drivers/Kconfig`中增加配置菜单,模板如下
248
249
250   ```
251   config DRIVERS_HDF_WIFI_chip_name
252       bool "Enable chip_name Host driver"
253       default n
254       depends on DRIVERS_HDF_WLAN   help
255         Answer Y to enable chip_name Host driver.
256   ```
257
258   > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
259   > 请替换模板中的chip_name为实际的芯片名称。
260
2615. 修改构建脚本,让驱动参与内核构建
262
263   在源码文件`//device/vendor_name/drivers/lite.mk`末尾追加如下内容。
264
265
266   ```
267   ifeq ($(LOSCFG_DRIVERS_HDF_WIFI_chip_name), y)
268       # 构建完成要链接一个叫hdf_wlan_chipdriver_chip_name的对象,建议按这个命名,防止冲突
269       LITEOS_BASELIB += -lhdf_wlan_chipdriver_chip_name
270       # 增加构建目录gpio
271       LIB_SUBDIRS    += ../peripheral/wifi/chip_name
272   endif
273   ```
274
275   > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
276   > 请替换模板中的chip_name为实际的芯片名称。
277