背景
最近在做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的记录。
背景
最近在做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的记录。
举报