最近在调试openharmony3.0小型系统的wifi模块,把过程记录下,防止以后忘记。 首先这是官方给的开发说明步骤: WLAN驱动基于HDF框架和PLATFORM框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。
1、通过wifi_config.hcs文件,配置硬件参数:module(不同feature),芯片等。 2、 解析配置文件, 生成全量配置的结构体对象。 3 、Module初始化,创建Module。 4、 挂接chip,初始化chip。 5 、总线初始化。 6.、上层wpa业务挂接。 具体可查看网址 https://docs.openharmony.cn/pages/zh-cn/device/%E8%AE%BE%E5%A4%87%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/%E5%AD%90%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91/%E9%A9%B1%E5%8A%A8/%E5%A4%96%E8%AE%BE%E9%A9%B1%E5%8A%A8%E4%BD%BF%E7%94%A8/WLAN/ 说明。可以说非常简明扼要了。 我这里使用的wifi芯片模组为RTL8189FTV,现基于此wifi芯片在openharmony3.0小型系统上的调试过程记录于此。 首先在文件 vendor/xingyun/t113_nand/hdf_config/device_info/device_info.hcs中添加对应的wifi配置项。
diff --git a/vendor/xingyun/t113_nand/hdf_config/device_info/device_info.hcs b/vendor/xingyun/t113_nand/hdf_config/device_info/device_info.hcs
index 7acc319ff2..df34a72ded 100755
--- a/vendor/xingyun/t113_nand/hdf_config/device_info/device_info.hcs
+++ b/vendor/xingyun/t113_nand/hdf_config/device_info/device_info.hcs
@@ -86,5 +86,30 @@ root {
}
}
+ network :: host {
+ hostName = "network_host";
+ device_wifi :: device {
+ device0 :: deviceNode {
+ policy = 2;
+ priority = 100;
+ preload = 0;
+ permission = 0664;
+ moduleName = "HDF_WIFI";
+ deviceMatchAttr = "hdf_wlan_driver";
+ serviceName = "hdfwifi";
+ }
+ }
+ device_wlan_chips :: device {
+ device0 :: deviceNode {
+ policy = 0;
+ preload = 0; //注意,此处官方使用的是2,我们调试的话先使用0,系统启动就加载
+ moduleName = "HDF_WLAN_CHIPS";
+ deviceMatchAttr = "hdf_wlan_chips_hi3881";
+ serviceName = "hisi";
+ }
+ }
+ }
+
+
}
}
然后需要做的是添加我们自己的驱动文件,目前是先仿照海思目录,在device/xingyunelec/目录下创建个文件夹drivers,然后在里面创建文件夹 wifi,最后创建好的目录如下图所示 然后仿照海思目录创建core和rtl8189ftv目录文件夹。创建完成的如下图所示。 其中core目录下只有一个文件hdf_wlan_sdio_adapt.c,rtl8189ftv目前只保留了hdfadapt和include文件夹,如下图所示,因为我们目前还只是在搭建编译wifi模块驱动的框架,所以不需要那么多的文件,只保留基本的文件即可。 目前hdf只保留了的文件有driver_register.c,hdfinit_3881.c,net_adpater.c和net_adpater.h文件,其中driver_register.c不为空文件,其他两个都是空文件,保留driver_register.c文件内容只为测试是否编译成功。device目录修改完成后接着修改编译脚本配置。首先需要添加我们自己wifi芯片模组的内核配置选项,修改如下,使用其他可以仿照添加
--- a/drivers/adapter/khdf/linux/model/network/wifi/Kconfig
+++ b/drivers/adapter/khdf/linux/model/network/wifi/Kconfig
@@ -10,4 +10,11 @@ config DRIVERS_HI3881
default n
depends on DRIVERS_HDF_WIFI
help
- Answer Y to enable hi3881 wifi chip driver.
\ No newline at end of file
+ Answer Y to enable hi3881 wifi chip driver.
+
+config DRIVERS_RTL8189FTV
+ bool "Enable rtl8189ftv"
+ default n
+ depends on DRIVERS_HDF_WIFI
+ help
+ Answer Y to enable rtl8189ftv wifi chip driver.
然后修改某些编译文件的路径,此处我是增加了宏定义,让它直接链接到我的文件路径即可,这里也想吐槽下,openharmony的文件放置确实有点乱,到处都放文件,然后修改起来感觉特别乱,倒不如规规矩矩放一个地方,这样不用到处找文件。
diff --git a/drivers/adapter/khdf/linux/model/network/wifi/hdfwifi.mk b/drivers/adapter/khdf/linux/model/network/wifi/hdfwifi.mk
index 63703c3544..65fd55179a 100644
--- a/drivers/adapter/khdf/linux/model/network/wifi/hdfwifi.mk
+++ b/drivers/adapter/khdf/linux/model/network/wifi/hdfwifi.mk
@@ -14,7 +14,13 @@
HDF_WIFI_FRAMEWORKS_ROOT = $(HDF_DIR_PREFIX)/framework/model/network/wifi
HDF_WIFI_KHDF_FRAMEWORKS_ROOT = $(HDF_DIR_PREFIX)/adapter/khdf/linux/model/network/wifi
+
+ifeq ($(CONFIG_DRIVERS_RTL8189FTV),y)
+HDF_WIFI_VENDOR_ROOT = $(HDF_VENDOR_PREFIX)/device/xingyunelec/drivers/wifi
+else
HDF_WIFI_VENDOR_ROOT = $(HDF_VENDOR_PREFIX)/device/hisilicon/drivers/wifi/driver
+endif
+
HDF_FRAMEWORKS_INC := \
-Idrivers/hdf/framework/ability/sbuf/include \
-Idrivers/hdf/framework/core/common/include/host \
添加我们自己的编译目录到Makefile文件。
diff --git a/drivers/adapter/khdf/linux/model/network/wifi/vendor/Makefile b/drivers/adapter/khdf/linux/model/network/wifi/vendor/Makefile
index ea4a0d17fe..cce9285919 100755
--- a/drivers/adapter/khdf/linux/model/network/wifi/vendor/Makefile
+++ b/drivers/adapter/khdf/linux/model/network/wifi/vendor/Makefile
@@ -34,4 +34,5 @@ HDF_WIFI_FLAGS +=-D_PRE_OS_VERSION=_PRE_OS_VERSION_LINUX
ccflags-$(CONFIG_DRIVERS_HDF_WIFI) += $(HDF_WIFI_FLAGS)
-obj-$(CONFIG_DRIVERS_HI3881) += hi3881/
\ No newline at end of file
+obj-$(CONFIG_DRIVERS_HI3881) += hi3881/
+obj-$(CONFIG_DRIVERS_RTL8189FTV) += rtl8189ftv/
然后在drivers/adapter/khdf/linux/model/network/wifi/vendor目录下添加rtl8189ftv文件夹,文件直接拷贝hi3881的内容填充,env_config.mk 和Makefile文件,然后修改Makefile文件内容为如下内容,env_config.mk 暂时不动。
MODULE_NAME := rtl8189ftv
HDF_VENDOR_PREFIX := ../../../../../../../../../
include drivers/hdf/khdf/model/network/wifi/hdfwifi.mk
INC_TOP_PATH := $(PROJECT_ROOT)
VENDOR_WIFI_PATH := device/xingyunelec/drivers/wifi
WIFI_DRIVER_DIR := rtl8189ftv //对应的芯片模组
ADPATER_PATH := $(HDF_WIFI_VENDOR_ROOT)/$(WIFI_DRIVER_DIR)/hdfadapt/
ccflags-$(CONFIG_DRIVERS_HDF_WIFI) += \
$(HDF_FRAMEWORKS_INC) \
$(HDF_WIFI_FRAMEWORKS_INC) \
$(HDF_WIFI_ADAPTER_INC) \
$(HDF_WIFI_VENDOR_INC) \
$(SECURE_LIB_INC)
include drivers/hdf/khdf/model/network/wifi/vendor/hi3881/env_config.mk
HI1131_HOST_CFLAGS += -Wextra -fsigned-char -fno-strict-aliasing -Wdate-time \
-Wformat=2 -Wshadow -fvisibility=hidden -fno-common -fstack-protector-strong
HI1131_HOST_CFLAGS += -Wall
HI1131_HOST_CFLAGS += $(HI1131_WIFI_CFLAGS)
obj-$(CONFIG_DRIVERS_RTL8189FTV) += $(MODULE_NAME).o
adapter-objs := hdfinit_3881.o net_adpater.o driver_register.o
adapter-objs := $(addprefix $(ADPATER_PATH),$(adapter-objs))
plat-objs = $(adapter-objs)
$(MODULE_NAME)-objs := $(plat-objs)
ccflags-$(CONFIG_DRIVERS_RTL8189FTV) += $(HI1131_HOST_CFLAGS)
这样编译框架就算搭建好了,开始编译吧。接下来就是按照官网给的开发指导,去调试wifi模块了。 首先适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化功能函数,
struct HdfChipDriverFactory {
const char *driverName;
int32_t (*InitChip)(struct HdfWlanDevice *device);
int32_t (*DeinitChip)(struct HdfWlanDevice *device);
void (*ReleaseFactory)(struct HdfChipDriverFactory *factory);
struct HdfChipDriver *(*Build)(struct HdfWlanDevice *device, uint8_t ifIndex);
void (*Release)(struct HdfChipDriver *chipDriver);
uint8_t (*GetMaxIFCount)(struct HdfChipDriverFactory *factory);
};
以上为官方自定义的头文件已经函数指针,需要填充注册这些函数给到上层操作。 目前我这边先是空实现,具体内容如下。
#include "hdf_device_desc.h"
#include "hdf_log.h"
#include "hdf_wlan_chipdriver_manager.h"
#define HDF_LOG_TAG wifi_rtl8189ftv_driver
static const char * const WIFI_DRIVER_NAME = "rtl8189ftv";
int32_t rtl8189ftvInitChip(struct HdfWlanDevice *device)
{
HDF_LOGD("rtl8189ftvInitChip");
return HDF_SUCCESS;
}
int32_t rtl8189ftvDeinitChip(struct HdfWlanDevice *device)
{
HDF_LOGD("rtl8189ftvDeinitChip");
return HDF_SUCCESS;
}
void rtl8189ftvReleaseFactory(struct HdfChipDriverFactory *factory)
{
HDF_LOGD("rtl8189ftvReleaseFactory");
}
struct HdfChipDriver *rtl8189ftvBuild(struct HdfWlanDevice *device, uint8_t ifIndex)
{
HDF_LOGD("rtl8189ftvBuild = %d",ifIndex);
struct HdfChipDriver *specificDriver = NULL;
return specificDriver;
}
void rtl8189ftvRelease(struct HdfChipDriver *chipDriver)
{
HDF_LOGD("rtl8189ftvRelease");
}
uint8_t rtl8189ftvGetMaxIFCount(struct HdfChipDriverFactory *factory)
{
HDF_LOGD("rtl8189ftvGetMaxIFCount");
return 1;
}
static int32_t HdfRtl8189ChipDriverInit(struct HdfDeviceObject *device)
{
(void)device;
struct HdfChipDriverFactory rtlDriverFactory = {0};
struct HdfChipDriverManager *driverMgr = NULL;
HDF_LOGD("%s: entry",__func__);
driverMgr = HdfWlanGetChipDriverMgr();
if (driverMgr == NULL) {
HDF_LOGE("%s fail: driverMgr is NULL!", __func__);
return HDF_FAILURE;
}
rtlDriverFactory.driverName = WIFI_DRIVER_NAME;
rtlDriverFactory.InitChip = rtl8189ftvInitChip;
rtlDriverFactory.DeinitChip = rtl8189ftvDeinitChip;
rtlDriverFactory.ReleaseFactory = rtl8189ftvReleaseFactory;
rtlDriverFactory.Build = rtl8189ftvBuild;
rtlDriverFactory.Release = rtl8189ftvRelease;
rtlDriverFactory.GetMaxIFCount = rtl8189ftvGetMaxIFCount;
if ( driverMgr->RegChipDriver(&rtlDriverFactory) != HDF_SUCCESS )
{
HDF_LOGE("%s fail: driverMgr is NULL!", __func__);
return HDF_FAILURE;
}
HDF_LOGD("%s: exit succ",__func__);
return HDF_SUCCESS;
}
static int HdRtl8189DriverBind(struct HdfDeviceObject *dev)
{
(void)dev;
return HDF_SUCCESS;
}
static void HdfRtl8189ChipRelease(struct HdfDeviceObject *object)
{
(void)object;
}
struct HdfDriverEntry g_hdfrtl8189ftvChipEntry = {
.moduleVersion = 1,
.Bind = HdRtl8189DriverBind,
.Init = HdfRtl8189ChipDriverInit,
.Release = HdfRtl8189ChipRelease,
.moduleName = "HDF_WLAN_CHIPS"
};
HDF_INIT(g_hdfrtl8189ftvChipEntry);
先分析下重点,即wifi的主要控制部分,drivers/framework/model/network/wifi/core/hdf_wifi_core.c文件。
static int32_t HdfWlanMainInit(struct HdfDeviceObject *device)
{
struct HdfConfigWlanRoot *rootConfig = NULL;
const struct HdfConfigWlanModuleConfig *moduleConfig = NULL;
HDF_LOGV("%s:start..", __func__);
if (device == NULL) {
return HDF_FAILURE;
}
if (HdfWlanGetConfig(device) != HDF_SUCCESS) {
HDF_LOGE("%s:HdfWlanGetConfig get wlan config failed!", __func__);
return HDF_FAILURE;
}
rootConfig = HdfWlanGetModuleConfigRoot();
moduleConfig = &rootConfig->wlanConfig.moduleConfig;
if (HdfWlanInitProduct(device, moduleConfig) != HDF_SUCCESS) {
HDF_LOGE("%s:HdfWlanInitProduct failed!", __func__);
return HDF_FAILURE;
}
if (HdfWlanScanAndInitThread(device) != HDF_SUCCESS) {
HDF_LOGE("%s: LoadChipFactoryThread failed, the load process failed!", __func__);
return HDF_FAILURE;
}
HDF_LOGV("%s:finished.", __func__);
return HDF_SUCCESS;
}
int HdfWlanInitProduct(struct HdfDeviceObject *device, const struct HdfConfigWlanModuleConfig *config)^M
{
int ret;
if (g_hdfWlanProductData != NULL) {
HDF_LOGE("%s:already inited!", __func__);
return HDF_FAILURE;
}
g_hdfWlanProductData = OsalMemCalloc(sizeof(struct HdfWifiProductData));
if (g_hdfWlanProductData == NULL) {
HDF_LOGE("%s:oom", __func__);
return HDF_FAILURE;
}
ret = InitWifiModule(&(g_hdfWlanProductData->module), config);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s:InitWifiModule failed! ret=%d", __func__, ret);
OsalMemFree(g_hdfWlanProductData);
g_hdfWlanProductData = NULL;
return ret;
}
g_hdfWlanProductData->device = device;
return HDF_SUCCESS;
}
|