RK3399 蓝牙打不开问题

rk3399 android 11

Posted by LXG on March 27, 2024

蓝牙-AOSP

rtl8821cs 原理图

rk3399_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

bt_gpio_android7

Android 11

bt_gpio_android11

对比分析发现蓝牙关闭时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");
}

原理图的提示

rk3399_rtl8821cs_2

从原理图上看到,启动后用做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

rk3399_rtl8821cs_3

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 的问题。可以提供两个方式去解决:

  1. LE 设备增加支持 link layer privacy 功能。
  2. 编译阶段关闭协议栈 bt_target.h 里的 BLE_PRIVACY_SPT。第二个方式,是 workaroud 的方式,目前 android r 是不被允许的,需要客户自行评估风险。

dumpsys bluetooth_manager 调试蓝牙状态

蓝牙地址

一组由48位(6字节)二进制表示的数据,是蓝牙设备的唯一标识

bluetooth_address

蓝牙名字和地址一般是从蓝牙协议栈bluedroid获取来的,时序图:

bluetooth_name