rtl8821cs 原理图
DTS 驱动配置
rk3399.dtsi
uart0 {
uart0_xfer: uart0-xfer {
rockchip,pins =
<2 RK_PC0 1 &pcfg_pull_up>,
<2 RK_PC1 1 &pcfg_pull_up>;
};
uart0_cts: uart0-cts {
rockchip,pins =
<2 RK_PC2 1 &pcfg_pull_none>;
};
uart0_rts: uart0-rts {
rockchip,pins =
<2 RK_PC3 1 &pcfg_pull_none>;
};
};
rk3399-evb.dtsi
wireless-wlan {
compatible = "wlan-platdata";
rockchip,grf = <&grf>;
wifi_chip_type = "rtl8821cs";
sdio_vref = <1800>;
WIFI,host_wake_irq = <&gpio0 3 GPIO_ACTIVE_HIGH>; /* GPIO0_a3 */
status = "okay";
};
wireless-bluetooth {
compatible = "bluetooth-platdata";
clocks = <&rk808 1>;
clock-names = "ext_clock";
//wifi-bt-power-toggle;
uart_rts_gpios = <&gpio2 19 GPIO_ACTIVE_LOW>; /* GPIO2_C3 */
pinctrl-names = "default", "rts_gpio";
pinctrl-0 = <&uart0_rts>;
pinctrl-1 = <&uart0_gpios>;
//BT,power_gpio = <&gpio3 19 GPIO_ACTIVE_HIGH>; /* GPIOx_xx */
BT,reset_gpio = <&gpio0 9 GPIO_ACTIVE_HIGH>; /* GPIO0_B1 */
BT,wake_gpio = <&gpio2 27 GPIO_ACTIVE_HIGH>; /* GPIO2_D3 BT_WAKE */
BT,wake_host_irq = <&gpio0 4 GPIO_ACTIVE_HIGH>; /* GPIO0_A4 */
status = "okay";
};
&pinctrl {
wireless-bluetooth {
uart0_gpios: uart0-gpios {
rockchip,pins = <2 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
}
代码流程跟踪
Settings
./src/com/android/settings/bluetooth/BluetoothEnabler.java
public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchChangeListener {
private final BluetoothAdapter mBluetoothAdapter;
public BluetoothEnabler(Context context, SwitchWidgetController switchController,
MetricsFeatureProvider metricsFeatureProvider, int metricsEvent,
RestrictionUtils restrictionUtils) {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
@Override
public boolean onSwitchToggled(boolean isChecked) {
if (mBluetoothAdapter != null) {
boolean status = setBluetoothEnabled(isChecked);
}
}
private boolean setBluetoothEnabled(boolean isEnabled) {
return isEnabled ? mBluetoothAdapter.enable() : mBluetoothAdapter.disable();
}
}
frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
public final class BluetoothAdapter {
public static synchronized BluetoothAdapter getDefaultAdapter() {
if (sAdapter == null) {
IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
if (b != null) {
IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
sAdapter = new BluetoothAdapter(managerService);
} else {
Log.e(TAG, "Bluetooth binder is null");
}
}
return sAdapter;
}
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean enable() {
if (isEnabled()) {
if (DBG) {
Log.d(TAG, "enable(): BT already enabled!");
}
return true;
}
try {
return mManagerService.enable(ActivityThread.currentPackageName());
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
return false;
}
}
SystemServer
BluetoothManagerService日志
BluetoothManagerService D enable(com.android.settings): mBluetooth =null mBinding = false mState = OFF
BluetoothManagerService D enable returning
BluetoothManagerService D MESSAGE_ENABLE(0): mBluetooth = null
BluetoothManagerService D binding Bluetooth service
BluetoothManagerService D Bluetooth Adapter name changed to rk3399
BluetoothManagerService D Stored Bluetooth name: rk3399
BluetoothManagerService D BluetoothServiceConnection: com.android.bluetooth.btservice.AdapterService
BluetoothManagerService D MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 1
BluetoothManagerService D Broadcasting onBluetoothServiceUp() to 5 receivers.
BluetoothManagerService D MESSAGE_BLUETOOTH_STATE_CHANGE: OFF > BLE_TURNING_ON
BluetoothManagerService D Sending BLE State Change: OFF > BLE_TURNING_ON
--------- beginning of crash
BluetoothManagerService D BluetoothServiceConnection, disconnected: com.android.bluetooth.btservice.AdapterService
BluetoothManagerService E MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(1)
BluetoothManagerService D Broadcasting onBluetoothServiceDown() to 4 receivers.
BluetoothManagerService D MESSAGE_RESTART_BLUETOOTH_SERVICE: retry count=1
frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java
class BluetoothManagerService extends IBluetoothManager.Stub {
private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
public boolean enable(String packageName) throws RemoteException {
if (DBG) {
Slog.d(TAG, "enable(" + packageName + "): mBluetooth =" + mBluetooth + " mBinding = "
+ mBinding + " mState = " + BluetoothAdapter.nameForState(mState));
}
synchronized (mReceiver) {
// waive WRITE_SECURE_SETTINGS permission check
sendEnableMsg(false,
BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
}
if (DBG) {
Slog.d(TAG, "enable returning");
}
return true;
}
private void handleEnable(boolean quietMode) {
mQuietEnable = quietMode;
try {
mBluetoothLock.writeLock().lock();
if ((mBluetooth == null) && (!mBinding)) {
Slog.d(TAG, "binding Bluetooth service");
//Start bind timeout and bind
Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
Intent i = new Intent(IBluetooth.class.getName());
if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
UserHandle.CURRENT)) {
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
} else {
mBinding = true;
}
} else if (mBluetooth != null) {
//Enable bluetooth
try {
if (!mBluetooth.enable(mQuietEnable)) {
Slog.e(TAG, "IBluetooth.enable() returned false");
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to call enable()", e);
}
}
} finally {
mBluetoothLock.writeLock().unlock();
}
}
boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
Slog.e(TAG, "Fail to bind to: " + intent);
return false;
}
return true;
}
}
Bluetooth App
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
public class AdapterService extends Service {
private static final String TAG = "BluetoothAdapterService";
public synchronized boolean enable(boolean quietMode) {
debugLog("enable() - Enable called with quiet mode status = " + quietMode);
mQuietmode = quietMode;
mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);
return true;
}
native boolean enableNative();
}
状态机
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/BondStateMachine.java
final class BondStateMachine extends StateMachine {
private class StableState extends State {}
private class PendingCommandState extends State {}
}
JNI
packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
static jboolean enableNative(JNIEnv* env, jobject obj) {
ALOGV("%s", __func__);
if (!sBluetoothInterface) return JNI_FALSE;
int ret = sBluetoothInterface->enable();
return (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE
: JNI_FALSE;
}
static void adapter_properties_callback(bt_status_t status, int num_properties,
bt_property_t* properties) {
ALOGV("%s: Status is: %d, Properties: %d", __func__, status, num_properties);
if (status != BT_STATUS_SUCCESS) {
ALOGE("%s: Status %d is incorrect", __func__, status);
return;
}
}
蓝牙协议栈
AOSP 中提供了蓝牙默认堆栈, 该堆栈实现常规蓝牙HAL
system/bt/btif
日志
BluetoothServiceJni I hal_util_load_bt_library: loaded Bluetooth library successfully
bt_btif I init: start restricted = 0 ; niap = 0, config compare result = 0
bt_btif I init Preserving legacy bluetooth functionality
bt_osi_all...on_tracker D canary initialized
droid.bluetoot I [0326/184852.057007:INFO:message_loop_thread.cc(175)] Run: message loop starting for thread bt_stack_manager_thread
bt_stack_manager I event_init_stack is initializing the stack
bt_osi_thread I run_thread: thread id 2040, thread name alarm_default_ca started
bt_osi_thread I run_thread: thread id 2041, thread name alarm_dispatcher started
bt_btif_core I btif_init_bluetooth entered
bt_stack_config I init attempt to load stack conf from /etc/bluetooth/bt_stack.conf
droid.bluetoot I [0326/184852.059266:INFO:message_loop_thread.cc(175)] Run: message loop starting for thread bt_jni_thread
bt_btif_core I btif_init_bluetooth finished
bt_stack_manager I event_init_stack finished
bt_osi_wakelock I wakelock_set_os_callouts set to non-native
bt_btif I get_profile_interface: id = socket
// 错误日志
bt_btif_storage E btif_storage_get_adapter_property: Controller not ready! Unable to return Bluetooth Address
bt_btif I get_profile_interface: id = bluetooth_keystore
bt_btif I get_profile_interface: id = sdp
bt_btif I get_profile_interface: id = gatt
bt_stack_manager I event_start_up_stack is bringing up the stack
bt_core_module I module_start_up Starting module "btif_config_module"
bt_core_module I module_start_up Started module "btif_config_module"
bt_core_module I module_start_up Starting module "btsnoop_module"
bt_core_module I module_start_up Started module "btsnoop_module"
bt_core_module I module_start_up Starting module "hci_module"
bt_hci I hci_module_start_up
droid.bluetoot I [0326/184852.180148:INFO:message_loop_thread.cc(175)] Run: message loop starting for thread bt_hci_thread
bt_hci D hci_module_start_up starting async portion
bt_hci I hci_initialize
bt_hci I hci_initialize: IBluetoothHci::getService() returned 0xb4000078058dcf10 (remote)
./system/bt/hci/src/btif_storage.cc
bt_status_t btif_storage_get_adapter_property(bt_property_t* property) {
/* Special handling for adapter address and BONDED_DEVICES */
if (property->type == BT_PROPERTY_BDADDR) {
RawAddress* bd_addr = (RawAddress*)property->val;
/* Fetch the local BD ADDR */
const controller_t* controller = controller_get_interface();
if (!controller->get_is_ready()) {
LOG_ERROR(LOG_TAG,
"%s: Controller not ready! Unable to return Bluetooth Address",
__func__);
*bd_addr = RawAddress::kEmpty;
return BT_STATUS_FAIL;
} else {
LOG_ERROR(LOG_TAG, "%s: Controller ready!", __func__);
*bd_addr = *controller->get_address();
}
property->len = RawAddress::kLength;
return BT_STATUS_SUCCESS;
}
}
./system/bt/hci/src/hci_layer_android.cc
class BluetoothHciCallbacks : public V1_1::IBluetoothHciCallbacks {
Return<void> initializationComplete(Status status) override {
if (hci_is_root_inflammation_event_received()) {
// Ignore the initializationComplete here as we have already received
// root inflammation event earlier.
LOG_ERROR(
LOG_TAG,
"initializationComplete after root inflammation event! status=%d",
status);
return Void();
}
CHECK(status == Status::SUCCESS);
initialization_complete();
return Void();
}
}
system/bt/vendor_libs/linux/interface/bluetooth_hci.cc
Return<void> BluetoothHci::initialize_impl(
const ::android::sp<V1_0::IBluetoothHciCallbacks>& cb,
const ::android::sp<V1_1::IBluetoothHciCallbacks>& cb_1_1) {
ALOGI("BluetoothHci::initialize()");
if (cb == nullptr) {
ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
return Void();
}
death_recipient_->setHasDied(false);
cb->linkToDeath(death_recipient_, 0);
int hci_fd = openBtHci();
auto hidl_status = cb->initializationComplete(
hci_fd > 0 ? V1_0::Status::SUCCESS : V1_0::Status::INITIALIZATION_ERROR);
if (!hidl_status.isOk()) {
ALOGE("VendorInterface -> Unable to call initializationComplete(ERR)");
}
}
HIDL
AOSP 提供的规范接口
hardware/interfaces/bluetooth$ tree -L 3
.
├── 1.0
│ ├── Android.bp
│ ├── default
│ │ ├── Android.bp
│ │ ├── android.hardware.bluetooth@1.0-service.rc
│ │ ├── async_fd_watcher.cc
│ │ ├── async_fd_watcher.h
│ │ ├── bluetooth_address.cc
│ │ ├── bluetooth_address.h
│ │ ├── bluetooth_hci.cc
│ │ ├── bluetooth_hci.h
│ │ ├── bt_vendor_lib.h
│ │ ├── h4_protocol.cc
│ │ ├── h4_protocol.h
│ │ ├── hci_internals.h
│ │ ├── hci_packetizer.cc
│ │ ├── hci_packetizer.h
│ │ ├── hci_protocol.cc
│ │ ├── hci_protocol.h
│ │ ├── mct_protocol.cc
│ │ ├── mct_protocol.h
│ │ ├── OWNERS
│ │ ├── service.cpp
│ │ ├── test
│ │ ├── vendor_interface.cc
│ │ └── vendor_interface.h
│ ├── IBluetoothHciCallbacks.hal
│ ├── IBluetoothHci.hal
│ ├── types.hal
│ └── vts
│ ├── functional
│ └── OWNERS
├── 1.1
│ ├── Android.bp
│ ├── default
│ │ ├── Android.bp
│ │ ├── android.hardware.bluetooth@1.1-service.rc
│ │ ├── bluetooth_hci.cc
│ │ ├── bluetooth_hci.h
│ │ ├── OWNERS
│ │ └── service.cpp
│ ├── IBluetoothHciCallbacks.hal
│ ├── IBluetoothHci.hal
│ └── vts
│ ├── functional
│ └── OWNERS
├── a2dp
│ └── 1.0
│ ├── Android.bp
│ ├── default
│ ├── IBluetoothAudioHost.hal
│ ├── IBluetoothAudioOffload.hal
│ ├── types.hal
│ └── vts
└── audio
└── 2.0
├── Android.bp
├── default
├── IBluetoothAudioPort.hal
├── IBluetoothAudioProvider.hal
├── IBluetoothAudioProvidersFactory.hal
├── types.hal
└── vts
供应商实现
供应商使用硬件接口语言HIDL与蓝牙堆栈交互
源码目录
hardware/realtek/rtkbt$ tree
.
├── Android.mk
├── bluetooth
│ └── bdroid_buildcfg.h
├── code
│ ├── Android.mk
│ ├── libbt-vendor
│ │ ├── Android.mk
│ │ ├── codec
│ │ │ ├── Android.mk
│ │ │ ├── plc
│ │ │ │ ├── sbcplc.c
│ │ │ │ └── sbcplc.h
│ │ │ └── sbc
│ │ │ ├── formats.h
│ │ │ ├── sbc.c
│ │ │ ├── sbc.h
│ │ │ ├── sbc_math.h
│ │ │ ├── sbc_primitives_armv6.c
│ │ │ ├── sbc_primitives_armv6.h
│ │ │ ├── sbc_primitives.c
│ │ │ ├── sbc_primitives.h
│ │ │ ├── sbc_primitives_iwmmxt.c
│ │ │ ├── sbc_primitives_iwmmxt.h
│ │ │ ├── sbc_primitives_mmx.c
│ │ │ ├── sbc_primitives_mmx.h
│ │ │ ├── sbc_primitives_neon.c
│ │ │ ├── sbc_primitives_neon.h
│ │ │ ├── sbc_private.h
│ │ │ └── sbc_tables.h
│ │ ├── include
│ │ │ ├── bt_list.h
│ │ │ ├── bt_skbuff.h
│ │ │ ├── bt_vendor_rtk.h
│ │ │ ├── hardware.h
│ │ │ ├── hci_h5_int.h
│ │ │ ├── rtk_btservice.h
│ │ │ ├── rtk_btsnoop_net.h
│ │ │ ├── rtk_common.h
│ │ │ ├── rtk_hcidefs.h
│ │ │ ├── rtk_parse.h
│ │ │ ├── rtk_poll.h
│ │ │ ├── rtk_socket.h
│ │ │ ├── unused.h
│ │ │ ├── upio.h
│ │ │ └── userial_vendor.h
│ │ ├── MODULE_LICENSE_APACHE2
│ │ ├── NOTICE
│ │ └── src
│ │ ├── Android.mk
│ │ ├── bt_list.c
│ │ ├── bt_skbuff.c
│ │ ├── bt_vendor_rtk.c
│ │ ├── hardware.c
│ │ ├── hardware_uart.c
│ │ ├── hardware_usb.c
│ │ ├── hci_h5.c
│ │ ├── rtk_btservice.c
│ │ ├── rtk_btsnoop_net.c
│ │ ├── rtk_heartbeat.c
│ │ ├── rtk_parse.c
│ │ ├── rtk_poll.c
│ │ ├── rtk_socket.c
│ │ ├── upio.c
│ │ └── userial_vendor.c
│ └── rtkcmd
│ ├── Android.mk
│ └── rtkcmd.c
├── rtkbt.mk
└── vendor
├── etc
│ └── bluetooth
│ ├── rtkbt.conf
│ └── rtkbt_S0.conf
├── firmware
│ ├── BT_Firmware.mk
│ ├── fw_info.txt
│ ├── readme.txt
│ ├── rtl8821cs_config
│ ├── rtl8821cs_config_vendor
│ ├── rtl8821cs_fw
└── firmware_box
├── fw_info.txt
├── readme.txt
├── rtl8821cs_config
├── rtl8821cs_config_vendor
├── rtl8821cs_fw
└── TV_Firmware.mk
异常日志
android.hardware.bluetooth@1.0-service
android.ha...h@1.0-impl I BluetoothHci::initialize()
android.ha....0-service E found device pid:vid :024c:c821: Permission denied
android.ha....0-service E check_wifi_chip_type_string : RTL8821CS: Permission denied
android.ha...h@1.0-impl D Open: libbt-vendor-realtek.so
android.ha....0-service E vendor storage read success
android.ha....0-service E Got local bdaddr for vendor storage 22:22:D1:CC:6E:CF
android.ha....0-service D get_local_address: Trying /data/misc/bluetooth/bdaddr
libbt_vendor I RTKBT_RELEASE_NAME: 20201130_BT_ANDROID_11.0
libbt_vendor I init
bt_h5_int E OsAllocateTimer rtk_parse sigev.sigev_notify_thread_id = syscall(__NR_gettid)!
bt_h5_int E OsAllocateTimer rtk_parse sigev.sigev_notify_thread_id = syscall(__NR_gettid)!
rtk_parse I RTKBT_RELEASE_NAME: 20200318_BT_ANDROID_10.0
libbt_vendor E bt_wake_up_host_mode_set(1)
bt_upio E bt_wake_up_host_mode_set
bt_upio E bt_wake_up_host_mode_set path:/proc/bluetooth/sleep/lpm
bt_upio E bt_wake_up_host_mode_set fd:8 = open(path, O_RDWR): open(/proc/bluetooth/sleep/lpm) success
bt_upio E bt_wake_up_host_mode_set buffer:49
libbt_vendor E rtk_btsnoop_dump = 0, rtk_btsnoop_save_log = 0
android.ha...h@1.0-impl D Open vendor library loaded
libbt_vendor D set power off and delay 200ms
libbt_vendor D set power on and delay 1000ms
bt_userial_vendor I userial vendor open: opening /dev/ttyS0
bt_userial_vendor I userial vendor open: with HW flowctrl OFF
bt_userial_vendor I device fd = 8 open
bt_service D OsAllocateTimer bt_service sigev.sigev_notify_thread_id = syscall(__NR_gettid)!
bt_service D RTK_btservice_init init done!
bt_hwcfg_uart D RTKBT_RELEASE_NAME: 20201130_BT_ANDROID_11.0
bt_hwcfg_uart D
Realtek libbt-vendor_uart Version 5.1.1
bt_hwcfg_uart D hw_config_start, transtype = 0x11
//错误日志
bt_hwcfg_uart E hw_config_cback, status = 3
android.ha...h@1.0-impl D OnFirmwareConfigured result: 1
android.ha...h@1.0-impl I Firmware configured in 3.512s
--------- beginning of crash
//错误日志
android.ha...h@1.0-impl E VendorInterface -> Unable to call initializationComplete()
android.ha...h@1.0-impl I OnFirmwareConfigured: lpm_timeout_ms 0
android.ha...h@1.0-impl D OnFirmwareConfigured Calling StartLowPowerWatchdog()
hardware/realtek/rtkbt/code/libbt-vendor/src/hardware_uart.c
void hw_config_start(char transtype)
{
memset(&hw_cfg_cb, 0, sizeof(bt_hw_cfg_cb_t));
hw_cfg_cb.dl_fw_flag = 1;
hw_cfg_cb.chip_type = CHIPTYPE_NONE;
BTVNDDBG("RTKBT_RELEASE_NAME: %s",RTKBT_RELEASE_NAME);
BTVNDDBG("\nRealtek libbt-vendor_uart Version %s \n",RTK_VERSION);
HC_BT_HDR *p_buf = NULL;
uint8_t *p;
BTVNDDBG("hw_config_start, transtype = 0x%x \n", transtype);
}
void hw_config_cback(void *p_mem)
{
if(opcode == HCI_VSC_H5_INIT) {
if(status != 0) {
ALOGE("%s, status = %d", __func__, status); // 错误打印位置
if ((bt_vendor_cbacks) && (p_evt_buf != NULL))
bt_vendor_cbacks->dealloc(p_evt_buf);
if(rtkbt_auto_restart) {
if(bt_vendor_cbacks)
bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
kill(getpid(), SIGKILL);
}
return;
}
}
}
蓝牙驱动
BT 电源控制驱动位于: net/rfkill/rfkill-bt.c , 代码会生成节点/sys/class/rfkill/rfkill0/state。
- echo 1 > /sys/class/rfkill/rfkill0/state 可以手动给蓝牙模块上电
- echo 0 > /sys/class/rfkill/rfkill0/state 可以手动给蓝牙模块下电
系统在打开蓝牙时候,会自动执行上电过程。
kernel/net/rfkill$ tree
.
├── core.c
├── input.c
├── Kconfig
├── Makefile
├── rfkill-bt.c
├── rfkill-gpio.c
├── rfkill.h
└── rfkill-wlan.c
错误日志
[BT_RFKILL] kernel I bt shut off power
libbt_vendor and...ardware.bluetooth@1.0-service D set power off and delay 200ms
[BT_RFKILL] kernel I rfkill_rk_set_power: set bt wake_host high!
[BT_RFKILL] kernel I ENABLE UART_RTS
[BT_RFKILL] kernel I DISABLE UART_RTS
[BT_RFKILL] kernel I bt turn on power
[BT_RFKILL] kernel I Request irq for bt wakeup host
[BT_RFKILL] kernel I ** disable irq
// 上电
libbt_vendor and...ardware.bluetooth@1.0-service D set power on and delay 1000ms
bt_userial_vendor and...ardware.bluetooth@1.0-service I userial vendor open: opening /dev/ttyS0
bt_userial_vendor and...ardware.bluetooth@1.0-service I userial vendor open: with HW flowctrl OFF
bt_userial_vendor and...ardware.bluetooth@1.0-service I device fd = 8 open
bt_service and...ardware.bluetooth@1.0-service D OsAllocateTimer bt_service sigev.sigev_notify_thread_id = syscall(__NR_gettid)!
bt_service and...ardware.bluetooth@1.0-service D RTK_btservice_init init done!
bt_hwcfg_uart and...ardware.bluetooth@1.0-service D RTKBT_RELEASE_NAME: 20201130_BT_ANDROID_11.0
bt_hwcfg_uart and...ardware.bluetooth@1.0-service D Realtek libbt-vendor_uart Version 5.1.1
bt_hwcfg_uart and...ardware.bluetooth@1.0-service D hw_config_start, transtype = 0x11
// 错误日志
bt_hwcfg_uart and...ardware.bluetooth@1.0-service E hw_config_cback, status = 3
正常日志
libbt_vendor and...ardware.bluetooth@1.0-service D set power off and delay 200ms
[BT_RFKILL] kernel I rfkill_rk_set_power: set bt wake_host high!
[BT_RFKILL] kernel I ENABLE UART_RTS
[BT_RFKILL] kernel I DISABLE UART_RTS
[BT_RFKILL] kernel I bt turn on power
[BT_RFKILL] kernel I Request irq for bt wakeup host
[BT_RFKILL] kernel I ** disable irq
<no-tag> kernel W ttyS0 - failed to request DMA, use interrupt mode
libbt_vendor and...ardware.bluetooth@1.0-service D set power on and delay 1000ms
bt_userial_vendor and...ardware.bluetooth@1.0-service I userial vendor open: opening /dev/ttyS0
bt_userial_vendor and...ardware.bluetooth@1.0-service I userial vendor open: with HW flowctrl OFF
bt_userial_vendor and...ardware.bluetooth@1.0-service I device fd = 8 open
bt_service and...ardware.bluetooth@1.0-service D OsAllocateTimer bt_service sigev.sigev_notify_thread_id = syscall(__NR_gettid)!
bt_service and...ardware.bluetooth@1.0-service D RTK_btservice_init init done!
bt_hwcfg_uart and...ardware.bluetooth@1.0-service D RTKBT_RELEASE_NAME: 20201130_BT_ANDROID_11.0
bt_hwcfg_uart and...ardware.bluetooth@1.0-service D
Realtek libbt-vendor_uart Version 5.1.1
bt_hwcfg_uart and...ardware.bluetooth@1.0-service D hw_config_start, transtype = 0x11
bt_hwcfg_uart and...ardware.bluetooth@1.0-service D hw_cfg_cb.state = 1
bt_hwcfg_uart and...ardware.bluetooth@1.0-service D hw_cfg_cb.state = 2
bt_hwcfg_uart and...ardware.bluetooth@1.0-service D lmp_subversion = 0x8821 hw_cfg_cb.hci_version = 0x8 hw_cfg_cb.hci_revision = 0xc
bt_hwcfg_uart and...ardware.bluetooth@1.0-service D hw_cfg_cb.state = 3
bt_hwcfg_uart and...ardware.bluetooth@1.0-service D hw_config_cback chip_id of the IC:2
bt_hwcfg_uart and...ardware.bluetooth@1.0-service I check_match_state return 1(cfg->lmp_subversion:0x8821 cfg->hci_vesion:0x8 cfg->hci_revision:0xc cfg->chip_type:0x1f mask:00000000)
bt_hwcfg_uart and...ardware.bluetooth@1.0-service I get_patch_entry(lmp_subversion:0x8821 hci_vesion:0x8 cfg->hci_revision:0xc chip_type:0x1f)
bt_hwcfg_uart and...ardware.bluetooth@1.0-service I get_patch_entry return(patch_name:rtl8821cs_fw config_name:rtl8821cs_config mac_offset:0x44)
从以上报错日志可以分析出,hw_config_start函数执行报错,hw_config_cback, status = 3是具体报错内容
android 7 和 android 11 蓝牙引脚对比
Android 7
Android 11
对比分析发现蓝牙关闭时bt_default_reset引脚也是高电平,显示是异常的,需要找原因, 通过dts查找 gpio0 9 引脚的复用情况,发现未其他功能复用这个引脚,只能另找原因
kernel/net/rfkill/rfkill-bt.c
static int rfkill_rk_setup_gpio(struct platform_device *pdev,
struct rfkill_rk_gpio *gpio, const char *prefix,
const char *name)
{
if (gpio_is_valid(gpio->io)) {
int ret = 0;
sprintf(gpio->name, "%s_%s", prefix, name); // bt_default_reset
ret = devm_gpio_request(&pdev->dev, gpio->io, gpio->name);
if (ret) {
LOG("Failed to get %s gpio.\n", gpio->name);
return -1;
}
}
return 0;
}
static int rfkill_rk_probe(struct platform_device *pdev)
{
ret = rfkill_rk_setup_gpio(pdev, &pdata->reset_gpio, pdata->name,
"reset");
}
原理图的提示
从原理图上看到,启动后用做GPIO的功能,有理由怀疑GPIO异常
kernel/net/rfkill/rfkill-bt.c 文件中增加日志调试
static int rfkill_rk_set_power(void *data, bool blocked)
{
struct rfkill_rk_data *rfkill = data;
struct rfkill_rk_gpio *wake_host = &rfkill->pdata->wake_host_irq.gpio;
struct rfkill_rk_gpio *poweron = &rfkill->pdata->poweron_gpio;
struct rfkill_rk_gpio *reset = &rfkill->pdata->reset_gpio;
struct rfkill_rk_gpio *rts = &rfkill->pdata->rts_gpio;
struct pinctrl *pinctrl = rfkill->pdata->pinctrl;
int wifi_power = 0;
bool toggle = false;
int res = 0;
//------------------------------------------------------------------------------------------------
bt_power_state = 0;
LOG("bt shut off power\n");
if (gpio_is_valid(reset->io)) {
if (gpio_get_value(reset->io) == reset->enable) {
LOG("bt shut off power=================================\n");
pr_info("Setting GPIO %d as output with value %d\n", reset->io, !reset->enable);
res = gpio_direction_output(reset->io, 0);
if (res) {
pr_err("Failed to set GPIO %d as output, error: %d\n", reset->io, res);
} else {
pr_info("Successfully set GPIO %d as output\n", reset->io);
}
msleep(100);
res = gpio_get_value(reset->io);
pr_err("gpio_get_value GPIO %d, value: %d\n", reset->io, res);
}
}
//------------------------------------------------------------------------------------------------------
}
通过上述日志打印发现gpio_direction_output函数关闭RST引脚时返回的是成功,但是gpio_get_value获取到的RST值仍然是1, 也是说gpio_direction_output函数修改引脚并未生效。
Rockchip_RK3399_Datasheet_V2.1
PinCtrl
异常情况
rk3399_Android11:/sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl $ cat pinmux-pins | grep gpio0:9
pin 9 (gpio0-9): (MUX UNCLAIMED) gpio0:9
MUX UNCLAIMED: 表示该引脚的复用功能(multiplexer function)还没有被设置或激活,也就是说,它没有被配置为某种特定的硬件接口功能
从上边分析看到gpio0:9的function是未定义的
修改后的正常情况
rk3399_Android11:/sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl $ cat pinmux-pins | grep gpio0:9
pin 9 (gpio0-9): wireless-bluetooth gpio0:9 function wireless-bluetooth group bt-reset
修改方案
显式指定GPIO0_B1引脚为RK_FUNC_GPIO
kernel/arch/arm64/boot/dts/rockchip/rk3399-evb.dtsi
diff --git a/android/kernel/arch/arm64/boot/dts/rockchip/rk3399-evb.dtsi b/android/kernel/arch/arm64/boot/dts/rockchip/rk3399-evb.dtsi
index c050c5cf9f..2582c0a950 100755
--- a/android/kernel/arch/arm64/boot/dts/rockchip/rk3399-evb.dtsi
+++ b/android/kernel/arch/arm64/boot/dts/rockchip/rk3399-evb.dtsi
@@ -330,7 +330,7 @@
//wifi-bt-power-toggle;
uart_rts_gpios = <&gpio2 19 GPIO_ACTIVE_LOW>; /* GPIO2_C3 */
pinctrl-names = "default", "rts_gpio";
- pinctrl-0 = <&uart0_rts>;
+ pinctrl-0 = <&uart0_rts &bt_reset>;
pinctrl-1 = <&uart0_gpios>;
//BT,power_gpio = <&gpio3 19 GPIO_ACTIVE_HIGH>; /* GPIOx_xx */
BT,reset_gpio = <&gpio0 9 GPIO_ACTIVE_HIGH>; /* GPIO0_B1 */
@@ -650,6 +650,9 @@
};
wireless-bluetooth {
+ bt_reset: bt-reset{
+ rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
uart0_gpios: uart0-gpios {
rockchip,pins = <2 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
};
Realtek 官方文档
Realtek_Bluetooth_Porting_Guide_for_BT_Android11.0.pdf
发现部分 LE 设备在 android r 之前版本可以使用,在 android r 上使用会出现可以配对,但是开关 bt 后回连失败的现象以及在使用 7min 到 15min 后,出现自动断线和回连失败现象。 这个问题普遍原因是,LE设备不支持 link layer privacy 的问题。可以提供两个方式去解决:
- LE 设备增加支持 link layer privacy 功能。
- 编译阶段关闭协议栈 bt_target.h 里的 BLE_PRIVACY_SPT。第二个方式,是 workaroud 的方式,目前 android r 是不被允许的,需要客户自行评估风险。
dumpsys bluetooth_manager 调试蓝牙状态
蓝牙地址
一组由48位(6字节)二进制表示的数据,是蓝牙设备的唯一标识
蓝牙名字和地址一般是从蓝牙协议栈bluedroid获取来的,时序图: