RK3326[Android 8.1],获取BT、WIFI地址

背景

  
最近在做RK平台的项目,遇到了写号的问题;最开始是SN、wifi地址、bt地址无法写到机器里面去;更新了写号工具之后,可以写入机器,但是并没有使用到写号工具写入的数据,即写入的数据并没有生效。

平台:RK3326,Android 8.1;
工具:RKDevInfoWriteTool_Setup_V1.0.4_0422

出现问题

  
最开始是SN、wifi地址、bt地址无法写到机器里面去;更新了写号工具之后,可以写入机器,但是并没有使用到我们使用写号工具写入的信息,即写入的数据并没有生效。

分析问题

  
我觉得想要解决这个问题,需要弄清楚2个问题:

1、工具写入的数据是存放在哪里的?
2、蓝牙和wifi分别是在哪里去获取工具写入的数据?

解决问题

存放位置

  根据RK文档可得知:vendor storage,用于存储SN, MAC, LAN,BT等数据,主要特性是不会丢失以及系统启动各个阶段都可以访问,包括uboot, kernel, linux用户空间以及pc端。

获取地址

1、WIFI Mac

WIFI Mac是在wifi驱动里面去获取的;

路径:
kernel/drivers/net/wireless/rockchip_wlan/rtlxxxx/core/rtw_ieee80211.c

在函数rtw_macaddr_cfg()中,添加如下:

void rtw_macaddr_cfg(u8 *out, const u8 *hw_mac_addr)
{
    
    …………
    
err_chk:

    /*添加代码 start*/
    if (!rockchip_wifi_mac_addr(mac)) {
        RTW_ERR("get mac address from flash=[%02x:%02x:%02x:%02x:%02x:%02x]\n", mac[0], mac[1],
        mac[2], mac[3], mac[4], mac[5]);
    }
    
/*添加代码 end*/

    if (rtw_check_invalid_mac_address(mac, _TRUE) == _TRUE) {

  简单的去跟踪一下rockchip_wifi_mac_addr()函数,可以发现是从vendor分区里面把数据读出来的,其实有一个值得注意得地方,如下:

int rockchip_wifi_mac_addr(unsigned char *buf)
{
    char mac_buf[20] = {0};

    LOG("%s: enter.\n", __func__);

    // from vendor storage
    if (is_zero_ether_addr(wifi_custom_mac_addr)) {
        if (get_wifi_addr_vendor(wifi_custom_mac_addr) != 0)
            return -1;
    }

    sprintf(mac_buf, "%02x:%02x:%02x:%02x:%02x:%02x",
        wifi_custom_mac_addr[0], wifi_custom_mac_addr[1],
        wifi_custom_mac_addr[2], wifi_custom_mac_addr[3],
        wifi_custom_mac_addr[4], wifi_custom_mac_addr[5]);
    LOG("falsh wifi_custom_mac_addr=[%s]\n", mac_buf);

    if (is_valid_ether_addr(wifi_custom_mac_addr)) {
        /*如果是rtl开头的芯片,这里会对第一个字节进行一些处理(一共6个字节),导致写入的值和实际呈现的值有偏差*/
        if (!strncmp(wifi_chip_type_string, "rtl", 3))
            wifi_custom_mac_addr[0] &= ~0x2; // for p2p
    } else {
        LOG("This mac address is not valid, ignored...\n");
        return -1;
    }

    memcpy(buf, wifi_custom_mac_addr, 6);

    return 0;
}                                                           

get_wifi_addr_vendor(wifi_custom_mac_addr) -> rk_vendor_read(WIFI_MAC_ID, addr, 6) -> return _vendor_read(id, pbuf, size);

  wifi地址的获取比较简单,但是我在解决这个问题的过程中,遇到了驱动模块加载的问题,因为wifi驱动是以模块的方式编进内核的,在重新编译了kernel之后一定要将模块卸载之后再重新加载,不然不会生效!

2、蓝牙地址

蓝牙地址的获取是在HAL层;

相关路径:
hardware/realtek/rtkbt/code/libbt-vendor/src/hardware.c
hardware/interfaces/bluetooth/1.0/default/vendor_interface.cc
hardware/interfaces/bluetooth/1.0/default/bluetooth_address.cc

  hardware/下面有很多厂商,若所想要自己添加的东西被编译进系统,需要在build/make/core/product.mk文件里面做如下添加,如宏:BOARD_HAVE_BLUETOOTH_RTK,在Android.mk文件里面可以提现这个宏的作用;

_product_stash_var_list += \
    BOARD_WPA_SUPPLICANT_DRIVER \
    BOARD_WLAN_DEVICE \
    BOARD_USES_GENERIC_AUDIO \
    BOARD_KERNEL_CMDLINE \
    BOARD_KERNEL_BASE \
    BOARD_HAVE_BLUETOOTH \
    BOARD_HAVE_BLUETOOTH_RTK \    

在vendor_interface.cc文件中:


static const char* VENDOR_LIBRARY_SYMBOL_NAME =
    "BLUETOOTH_VENDOR_LIB_INTERFACE"; //和后面调用init函数有关

bool VendorInterface::Open(InitializeCompleteCallback initialize_complete_cb,
                           PacketReadCallback event_cb,
                           PacketReadCallback acl_cb,
                           PacketReadCallback sco_cb) {
    
    /*省略部分代码*/
    
    uint8_t local_bda[BluetoothAddress::kBytes];
    /*从vendor分区获取BT地址*/
    if (!BluetoothAddress::get_local_address(local_bda)) {
        LOG_ALWAYS_FATAL("%s: No Bluetooth Address!", __func__);
    }
    
    /*调用init函数,位于realtek下面,后面详细说*/
    int status = lib_interface_->init(&lib_callbacks, (unsigned char*)local_bda);
    if (status) {
        ALOGE("%s unable to initialize vendor library: %d", __func__, status);
        return false;
    }

    /*省略部分代码*/             
        
}

  在bluetooth_address.cc文件中,定义了get_local_address()函数,将获取到的蓝牙地址放在形参local_addr里面,即VendorInterface::Open函数中的local_bda数组里面;

bool BluetoothAddress::get_local_address(uint8_t* local_addr) {
     
     /*省略部分代码*/
     
    ret = bt_addr_vendor_storage_read_or_write(0, bd_addr, 6);
    if (ret == 0) {
        memcpy(local_addr, bd_addr, 6);

        valid_bda = true;
        ALOGE("Got local bdaddr for vendor storage %02X:%02X:%02X:%02X:%02X:%02X",
                local_addr[0], local_addr[1], local_addr[2],
                local_addr[3], local_addr[4], local_addr[5]);
    }
    
    /*省略部分代码*/
    
}

上面提到的init函数,其实定义在bt_vendor_rtk.c文件中,在该文件中,有如下定义:

/*可用于interfaces下面的调用(我现在也不知道为什么,是凭着直觉找到的[捂脸])*/
const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
    sizeof(bt_vendor_interface_t),
    init,
    op,
    cleanup
};

//在init函数中将local_bdaddr数组里面的地址(即上面所获取到的蓝牙地址)放在vnd_local_bd_addr数组里
static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr)
{

    /*省略部分代码*/

    /* This is handed over from the stack */
    memcpy(vnd_local_bd_addr, local_bdaddr, 6);
    byte_reverse(vnd_local_bd_addr, 6);
    
    /*省略部分代码*/
}

在hardware.c文件里,定义了getmacaddr()函数,是一个一看名字就知道干什么的函数;

int getmacaddr(unsigned char * addr)
{

    /*省略部分代码*/
    
    char property[100] = {0};
    if (property_get("persist.vendor.rtkbt.bdaddr_path", property, "none")) {
        if(strcmp(property, "none") == 0) {
            return -1;
        }
        else if(strcmp(property, "default") == 0) {
            memcpy(addr, vnd_local_bd_addr, BD_ADDR_LEN);
            return 0;
        }
    }

    /*省略部分代码*/
}

  可以从上面代码段中看出来,通过persist.vendor.rtkbt.bdaddr_path属性的值来决定采用哪个蓝牙地址,如果persist.vendor.rtkbt.bdaddr_path的值为default,那么就使用vendor分区里面我们写入的值;那么如何修改persist.vendor.rtkbt.bdaddr_path的值呢?通过查找代码,我们就可以看到这个属性值定义在hardware/realtek/rtkbt/rtkbt.mk文件中,如下,将none改为default就可以,刷机验证OK;

PRODUCT_PROPERTY_OVERRIDES += \
                    persist.vendor.bluetooth.rtkcoex=true \
                    persist.vendor.rtkbt.bdaddr_path=default \
                    persist.vendor.bluetooth.prefferedrole=master \
                    persist.vendor.rtkbtadvdisable=false //由none改为default

总结

  BT/Wifi这个模块,以前做MTK平台基本上没接触过;这次RK平台,Android 8.1,刚好公司采用的是RK那边也没做过的某芯片,问题比较多,接触到的东西也比较多,等有时间再写一篇蓝牙7.1升级到8.1的记录。

image

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值