完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
背景
最近在做RK平台的项目,遇到了写号的问题;最开始是SN、wifi地址、bt地址无法写到机器里面去;更新了写号工具之后,可以写入机器,但是并没有使用到写号工具写入的数据,即写入的数据并没有生效。 平台:RK3326,Android 8.1;出现问题 最开始是SN、wifi地址、bt地址无法写到机器里面去;更新了写号工具之后,可以写入机器,但是并没有使用到我们使用写号工具写入的信息,即写入的数据并没有生效。 分析问题 我觉得想要解决这个问题,需要弄清楚2个问题: 1、工具写入的数据是存放在哪里的?解决问题 存放位置 根据RK文档可得知:vendor storage,用于存储SN, MAC, LAN,BT等数据,主要特性是不会丢失以及系统启动各个阶段都可以访问,包括uboot, kernel, linux用户空间以及pc端。 获取地址 1、WIFI Mac WIFI Mac是在wifi驱动里面去获取的; 路径:在函数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/下面有很多厂商,若所想要自己添加的东西被编译进系统,需要在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的记录。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1906 浏览 1 评论
synopsys 的design ware:DW_fpv_div,浮点数除法器,默认32位下,想提升覆盖率(TMAX),如果用功能case去提升覆盖率呢?
2382 浏览 1 评论
RK3588 GStreamer调试四路鱼眼摄像头四宫格显示报错
5175 浏览 1 评论
【飞凌嵌入式OK3576-C开发板体验】RKNN神经网络-YOLO图像识别
254 浏览 0 评论
【飞凌嵌入式OK3576-C开发板体验】SSH远程登录网络配置及CAN通讯
1336 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 06:15 , Processed in 0.718107 second(s), Total 73, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号