移植openharmony之添加wifi驱动

最近在调试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 //对应的芯片模组

##################path of compile file :start###############
#####wifi#####
ADPATER_PATH := $(HDF_WIFI_VENDOR_ROOT)/$(WIFI_DRIVER_DIR)/hdfadapt/
##################path of compile file :end###############

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

####################################### platform module start #########################################

adapter-objs := hdfinit_3881.o net_adpater.o driver_register.o
adapter-objs := $(addprefix $(ADPATER_PATH),$(adapter-objs))




plat-objs =  $(adapter-objs)
####################################### platform module end #########################################

####################################### wifi module start #########################################

####################################### wifi module end #########################################

$(MODULE_NAME)-objs := $(plat-objs)

ccflags-$(CONFIG_DRIVERS_RTL8189FTV) += $(HI1131_HOST_CFLAGS) #此处修改为对应的芯片配置

这样编译框架就算搭建好了,开始编译吧。接下来就是按照官网给的开发指导,去调试wifi模块了。 首先适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化功能函数,

struct HdfChipDriverFactory {
          
   
    const char *driverName;  /**< Driver name */

    /**
     * @brief Initializes a specified chip.
     *
     * @param device Indicates the pointer to the WLAN device where the chip resides.
     * @return Returns <b>0</b> if the chip is initialized; returns a negative value otherwise.
     *
     * @since 1.0
     * @version 1.0
     */
    int32_t (*InitChip)(struct HdfWlanDevice *device);

    /**
     * @brief Deinitializes a specified chip.
     *
     * @param device Indicates the pointer to the WLAN device where the chip resides.
     * @return Returns <b>0</b> if the chip is deinitialized; returns a negative value otherwise.
     *
     * @since 1.0
     * @version 1.0
     */
    int32_t (*DeinitChip)(struct HdfWlanDevice *device);

    /**
     * @brief Releases a specified <b>HdfChipDriverFactory</b> instance.
     *
     * @param factory Indicates the pointer to the <b>HdfChipDriverFactory</b> instance.
     *
     * @since 1.0
     * @version 1.0
     */
    void (*ReleaseFactory)(struct HdfChipDriverFactory *factory);

    /**
     * @brief Creates a <b>HdfChipDriver</b> instance with the initialization and deinitialization functions.
     *
     * @param device Indicates the pointer to the WLAN device.
     * @param ifIndex Indicates the interface index.
     * @return Returns the pointer to the <b>HdfChipDriver</b> instance.
     *
     * @since 1.0
     * @version 1.0
     */
    struct HdfChipDriver *(*Build)(struct HdfWlanDevice *device, uint8_t ifIndex);
     /**
     * @brief Releases a specified <b>HdfChipDriver</b> instance.
     *
     * @param chipDriver Indicates the pointer to the <b>HdfChipDriver</b> instance.
     *
     * @since 1.0
     * @version 1.0
     */
    void (*Release)(struct HdfChipDriver *chipDriver);

    /**
     * @brief Obtains the maximum number of interfaces of a specified <b>HdfChipDriverFactory</b> instance.
     *
     * @param factory Indicates the pointer to the <b>HdfChipDriverFactory</b> instance.
     * @return Returns the maximum number of interfaces.
     *
     * @since 1.0
     * @version 1.0
     */
    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) {
          
    //获取hcs中的资源,保存在 g_configWlanModuleRoot.wlanConfig ,
        HDF_LOGE("%s:HdfWlanGetConfig get wlan config failed!", __func__);
        return HDF_FAILURE;
    }
    /* feature init */
    rootConfig = HdfWlanGetModuleConfigRoot(); // 获取 g_configWlanModuleRoot
    moduleConfig = &rootConfig->wlanConfig.moduleConfig; //获取hcs中的 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;
}
//初始化module配置
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;
}
经验分享 程序员 微信小程序 职场和发展