蓝牙扫描在Ubuntu 21.10上未检测到任何设备。

我刚买了一个Tp-link蓝牙5.0 USB适配器(UB500),我检查过它的芯片是Realtek RTL8761B。 在Windows 10上它工作得很好,但在Ubuntu上却遇到了问题。 我正在运行Ubuntu 21.10,并刚刚升级到最新的稳定内核版本:5.14.14。 在升级之前,我尝试了这个解决方案,但没有成功:https://linuxreviews.org/Realtek_RTL8761B 我几乎尝试了网上找到的所有方法,但大多数解决方案都不适用,因为没有明显的问题:适配器似乎已经正确安装并正常工作,但扫描却无法检测到任何蓝牙设备。我尝试了两个耳机(我知道它们是正常工作的)和我的手机,但都没有成功。当我在手机上进行扫描时,电脑没有显示出来,即使我将其设置为可见。
我无法弄清楚问题出在哪里。
    dmesg |grep -i bluetooth
    [    3.596913] Bluetooth: Core ver 2.22
    [    3.596935] NET: Registered PF_BLUETOOTH protocol family
    [    3.596936] Bluetooth: HCI device and connection manager initialized
    [    3.596939] Bluetooth: HCI socket layer initialized
    [    3.596941] Bluetooth: L2CAP socket layer initialized
    [    3.596945] Bluetooth: SCO socket layer initialized
    [   93.519895] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
    [   93.519899] Bluetooth: BNEP filters: protocol multicast
    [   93.519903] Bluetooth: BNEP socket layer initialized
    [  144.060814] Bluetooth: RFCOMM TTY layer initialized
    [  144.060821] Bluetooth: RFCOMM socket layer initialized
    [  144.060825] Bluetooth: RFCOMM ver 1.11

    hciconfig -a
    hci0:    Type: Primary  Bus: USB
        BD Address: E8:48:B8:C8:20:00  ACL MTU: 1021:6  SCO MTU: 255:12
        UP RUNNING 
        RX bytes:4264 acl:0 sco:0 events:560 errors:0
        TX bytes:9000 acl:0 sco:0 commands:490 errors:0
        Features: 0xff 0xff 0xff 0xfe 0xdb 0xfd 0x7b 0x87
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 
        Link policy: RSWITCH HOLD SNIFF PARK 
        Link mode: SLAVE ACCEPT 
        Name: 'gaia-ubuntu-desktop'
        Class: 0x7c0104
        Service Classes: Rendering, Capturing, Object Transfer, Audio, Telephony
        Device Class: Computer, Desktop workstation
        HCI Version: 5.1 (0xa)  Revision: 0xb
        LMP Version: 5.1 (0xa)  Subversion: 0x8761
        Manufacturer: Realtek Semiconductor Corporation (93)

    rfkill list
    0: hci0: Bluetooth
        Soft blocked: no
        Hard blocked: no

    lsusb
    Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    Bus 003 Device 004: ID 046d:0826 Logitech, Inc. HD Webcam C525
    Bus 003 Device 003: ID 04b8:013d Seiko Epson Corp. Epson Perfection V39
    Bus 003 Device 002: ID 0c76:2068 JMTek, LLC. USB MIC-SG01
    Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    Bus 001 Device 003: ID 2357:0604 TP-Link TP%Link UB500 Adapter
    Bus 001 Device 002: ID 062a:3633 MosArt Semiconductor Corp. Full-Speed Mouse
    Bus 001 Device 004: ID 145f:0176 Trust Isla Keyboard
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

usb-devices | awk '/0604/' RS=
T:  Bus=01 Lev=01 Prnt=01 Port=07 Cnt=03 Dev#=  3 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=2357 ProdID=0604 Rev=02.00
S:  Manufacturer= 
S:  Product=TP%Link UB500 Adapter
S:  SerialNumber=E848B8C82000
C:  #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA
I:  If#=0x0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
I:  If#=0x1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb

lsusb 显示了什么? - Pilot6
我已经编辑了原始帖子并包含了lsusb。 - gwendydd
这不受任何现有内核支持。请添加usb-devices | awk '/0604/' RS=的输出结果。 - Pilot6
再次编辑后的翻译文本,请查收。顺便说一句,谢谢。 - gwendydd
很难说这是什么芯片?谁告诉你它是RTL8761B?如果真的是那个芯片,一个简单的内核补丁就能修复它。 - Pilot6
请提供 "sudo lshw" 的输出。 - Error404
我在谷歌上搜索了这个ID,并在这里找到了它:https://usb-ids.gowdy.us/read/UD/2357/0604 @Pilot6 - gwendydd
好的。然后它应该添加到btusb.c中。我建议在Launchpad上提交一个错误报告。但也可以创建一个带有代码的小型DKMS模块。 - Pilot6
@AkshajSingla 发帖太长了 - gwendydd
@Pilot6 好的!你能帮我一下吗?我完全不知道该怎么做。 - gwendydd
有人可以帮忙。你可以使用补丁来构建内核,或者创建一个dkms模块。如果设备正常工作,应该将补丁发送到上游以添加到主线代码中。 - Pilot6
4个回答

我遇到了与Tp-Link UB500适配器相同的问题,但是我按照Pilot6的建议解决了这个问题。请按照以下步骤操作。感谢Pilot6。 步骤1:下载并提取Linux内核源文件。
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.11.tar.xz
tar xpvf linux-5.11.tar.xz

请确保根据您的系统使用适当的内核版本(可以通过uname -r命令进行检查)。 步骤2:编辑btusb.c文件
cd linux-5.11/drivers/bluetooth
gedit btusb.c

添加以下内容
/* Tp-Link UB500 */
{ USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK },


在"static const struct usb_device_id blacklist_table[]"部分之下。在/* Silicon Wave based devices */之后。 步骤3:编辑hci_ldisc.c (某些内核版本可能不需要此步骤)
替换
static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file,
                 unsigned char __user *buf, size_t nr)

static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file,
                 unsigned char __user *buf, size_t nr,
                 void **cookie, unsigned long offset)


第四步:编译模块
make -C /lib/modules/$(uname -r)/build M=$(pwd) clean
cp /usr/src/linux-headers-$(uname -r)/.config ./
cp /usr/src/linux-headers-$(uname -r)/Module.symvers Module.symvers
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
sudo cp btusb.ko /lib/modules/$(uname -r)/kernel/drivers/bluetooth

如果您启用了安全启动,还需要对模块进行签名,请搜索“如何为安全启动签署文件”。
第五步:替换旧模块。
sudo cp btusb.ko /lib/modules/$(uname -r)/kernel/drivers/bluetooth

第六步:加载新的btusb
sudo modprobe -r btusb
sudo modprobe -v btusb

它对我来说有效!

非常感谢!只是一个问题:我应该在btusb.c的哪个位置添加这些行?只是为了确保我不犯更多错误。 - gwendydd
我已经在"static const struct usb_device_id blacklist_table[]"部分下添加了代码。在/* Silicon Wave based devices */之后。 - gauthsree
1哇!太厉害了!谢谢你! - gwendydd
你能解释一下 void **cookie, unsigned long offset 吗?对我来说,它看起来像是一个“脏的黑科技”。如果我们想要在Linux中使用它,我们需要上游提交一个补丁。 - Pilot6
作为一个临时解决方案,创建一个dkms btusb模块以使其与内核更新兼容是有道理的。这很简单。 - Pilot6
2嗯,对我来说在Ubuntu 21.04上似乎不起作用。 - starbeamrainbowlabs
1我觉得这在Ubuntu 20.04上不起作用。 - Anderson
这个问题很快会在即将发布的Ubuntu补丁中解决吗? - Thomas Kimber
这个没有解决我的问题,但是学习如何修补内核也不是每天都有的事情 - 谢谢,太棒了! - Ash
编译时出现错误:/hci_vhci.c:181:7: error: ‘HCI_ISODATA_PKT’未声明。 - We are Borg
2这可能有点傻,但请确保在驱动程序/蓝牙目录中进行第4步操作时使用源代码而不是顶级目录,否则会出现错误。记住这一点,在Ubuntu 20.04中可以运行。我还按照@Laion的回答重新安装了固件。 - J. Knoblauch
只需要在drivers/bluetooth目录中执行第4步吗?我收到错误信息...我是否应该执行第1、2、3步,尽管已经有了?(Ubuntu 20.04) - cosmonaut

我按照@gauthsree的回答中的步骤操作,但系统停止检测适配器。
然后(经过大量搜索和阅读)我运行了lsusb; dmesg | egrep -i 'blue|firm',得到了以下结果:
RTL: firmware file rtl_bt/rtl8761b_fw.bin not found

所以,我下载了文件并放置在:/lib/firmware/rtl_bt/

然后,重新启动系统,最后可以正常工作!

我遵循了这个教程:蓝牙5.0芯片Realtek RTL8761B下载并复制固件。

我的系统:

  • 操作系统:Ubuntu 20.04.1
  • 内核:5.11.0-46-generic

希望这能帮到你!


1非常感谢,Laion!这是@gauthsree答案中遗漏的最后一步。我还需要验证我的键盘,并按照这个指南解决了这个问题: https://itectec.com/ubuntu/ubuntu-pairing-bluetooth-keyboard-that-needs-code-failed-to-pair-org-bluez-error-authenticationfailed/ - SRG
救命稻草!这个在我的Ubuntu 20.04上起作用了。 - Alexander Soare

如果设备是RTL8761B,则需要对btusb.c内核代码进行补丁,添加以下内容:
 /* Tp-Link UB500 */
{ USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK },

问题是目前还没有人将这个设备添加到Linux内核中。芯片似乎是支持的,但Tp-Link的ID却不在其中。
我建议将此问题报告给Launchpad。使用Ubuntu内核启动,并在终端中运行。
ubuntu-bug linux

这将创建一个错误报告。
更新:对于带有5.15内核的Ubuntu 20.04和Ubuntu 22.04+,补丁已添加到内核源代码中。设备应该可以正常工作,无需额外努力。

天哪,我不知道该怎么做。我已经在btusb.c中添加了那些代码行,但之后我完全不知道该怎么办。无论如何,我会报告这个问题的。谢谢你。 - gwendydd
完成这些之后,你需要构建一个内核,安装它并测试蓝牙是否正常工作。 - Pilot6
我以前从来没有做过这件事 - gwendydd
还是不工作 :/ - gwendydd
那么,你是否构建了一个定制的内核呢? - Pilot6
其实我不太确定我做了什么,但显然它没有起作用。而且我的意思是 uname -r 没有显示我以为我正在安装的内核版本,而是之前的版本。我有点迷失,我可能只会报告这个错误。 - gwendydd
请从Launchpad上提供一个链接。如果我有时间的话,也许我会制作一个模块。顺便说一下,你只能构建btusb模块。 - Pilot6
在此提供翻译内容:无论如何,尽管Ubuntu-Bug似乎无法工作,这是它(问题链接)https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1948502。顺便说一句,感谢你的时间。 - gwendydd
看起来在这里已经提交了一个类似的补丁:https://www.spinics.net/lists/linux-bluetooth/msg94476.html - Guillaume Husta
根据https://bbs.archlinux.org/viewtopic.php?pid=2003276#p2003276的消息,这个功能预计会在Linux内核5.16中实现。 - Guillaume Husta
1我开始安装最新的内核,等待这个问题得到解决,但是5.18.9-051809-generic仍然无法识别蓝牙适配器 :D - Recct
1我可以确认在完全更新的22.04版本中,这仍然是一个问题。 - Kingsley
遇到了相同的问题,使用22.04内核6.2.0-35-generic。 - undefined

这是一个执行Aeolun所有步骤的脚本。
同时,也下载并复制了Driver,就像Laion所描述的那样。
(我只是在学习bash脚本,尝试了这个并想分享一下。)
#!/bin/bash

# Initialization

FIX_UB_500_BT_Stick () {
echo -e "This Script is intended to fix the not working BT Stick UB 500 by TP-Link"
echo -e ""
echo -e "As descrbed in https://askubuntu.com/questions/1370663/bluetooth-scan-doesnt-detect-any-device-on-ubuntu-21-10"
echo -e ""
echo -e "This scripts guides you through all necessary steps. However, please take care. This can break your system, or at least  break your bluetooth."
echo -e ""
echo -e "\033[33mStep 1: Download and extract Linux kernel source file."
echo -e "\033[0m"
echo -e ""
echo -e "Your Kernel-Version: "
version=$(uname -r)
echo $version
echo -e "If not 5.13, change script and restart! (Just search and replace 5.13 with your Version, as long as it is a 5.x)"
read -n 1 -p "Do you want to continue? [y/n]" start
  if [ "$start" = "y" ] ; then
    cd
    mkdir FIX_UB_500_BT_Stick
    cd FIX_UB_500_BT_Stick
    wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.13.tar.xz
    tar xpvf linux-5.13.tar.xz
    echo -e "\033[33mDownload location and files:"
    echo -e "\033[0m"
    pwd
    ls
    echo -e "\033[33mLocation of files to be changed:"
    echo -e "\033[0m"
    cd linux-5.13/drivers/bluetooth
    pwd
    echo -e "\033[33mStep 2: Edit btusb.c"
    echo -e "\033[31m"
    echo "Add:"
    echo -e "\033[0m"
    echo "/* Tp-Link UB500 */"
    echo "{ USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK },"
    echo -e "\033[33m"
    echo "Under the section"
    echo -e "\033[0m"
    echo "static const struct usb_device_id blacklist_table[]"
    echo -e "\033[33m"
    echo "After"
    echo -e "\033[0m"
    echo "/* Silicon Wave based devices */"
    echo -e "\033[33m"
    echo "in btusb.c"
    echo ""
    echo "It should look something like this:"
    echo -e "\033[0m"
    echo "/* Silicon Wave based devices */"
    echo "{ USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },"
    echo "/* Tp-Link UB500 */"
    echo "{ USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK }, "
    echo "{ }/* Terminating entry */"
    echo ""
    echo -e "\033[31m Safe and close KWrite."
    sleep 5
    kwrite btusb.c
    read -n 1 -p "Did you change the file and want to continue? [y/n]" filechange1
    if [ "$filechange1" = "y" ]; then
      echo -e "\033[33m"
      echo "Ok, continuing."
      echo -e "\033[0m"
    elif [ "$filechange1" = "n" ];then
      sudo rm -r /home/max/FIX_UB_500_BT_Stick
      exit
    else
      echo -e "\033[31mDid you change the file and want to continue? [y/n]; Press ctrl+c to abort."
      echo -e "\033[0m"
      read -n 1
    fi
    echo -e "\033[33mStep 3: Edit hci_ldisc.c"
    echo -e "\033[0m"
    echo -e ""
    File="hci_ldisc.c"
    if grep -q "void **cookie, unsigned long offset)" "$File"; then
      echo -e "\033[33mStep not necessary. File already correct."
      echo -e "\033[0m"
    else
      echo -e "\033[33mChange:"
      echo -e "\033[0m"
      echo "static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file,"
      echo "                 unsigned char __user *buf, size_t nr)"
      echo ""
      echo -e "\033[33minto"
      echo -e "\033[0m"
      echo "static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file,"
      echo "                 unsigned char __user *buf, size_t nr, "
      echo "                 void **cookie, unsigned long offset) "
      echo -e "\033[33m"
      echo "in hci_ldisc.c"
      echo ""
      echo "Safe and Close KWrite. (This step might not be necessary for some versions)"
      sleep 5
      kwrite hci_ldisc.c
      read -n 1 -p "Did you change the file and want to continue? [y/n]" filechange2
      if [ "$filechange2" = "y" ]; then
        echo -e "\033[33m"
        echo "Ok, continuing."
        echo -e "\033[0m"
      elif [ "$filechange2" = "n" ];then
        sudo rm -r /home/max/FIX_UB_500_BT_Stick
        exit
      else
      echo -e "\033[31mDid you change the file and want to continue? [y/n];"
        read -n 1
      fi
    fi
    echo -e "\033[33mStep 4: Compile modules."
    echo -e "\033[0m"
    make -C /lib/modules/$(uname -r)/build M=$(pwd) clean
    echo -e "\033[33mMake 1 done."
    echo -e "\033[0m"
    cp /usr/src/linux-headers-$(uname -r)/.config ./
    cp /usr/src/linux-headers-$(uname -r)/Module.symvers Module.symvers
    make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
    echo -e "\033[33mMake 2 done."
    echo -e "\033[33mStep 5: Replace the old module."
      echo -e "\033[0m"
    sudo cp btusb.ko /lib/modules/$(uname -r)/kernel/drivers/bluetooth
    echo -e "\033[33mCopied to current Kernel"
    echo -e ""
    echo -e "\033[33mStep 6: Load new btusb."
    echo -e "\033[0m"
    sudo modprobe -r btusb
    sudo modprobe -v btusb
    echo -e "\033[33mModprobe done"
    echo -e "\033[0m"


    if [[ ! -f "/lib/firmware/rtl_bt/rtl8761b_fw.bin" ]]
    then
        echo -e "\033[33mStep 7: Download Firmware for UB500 from Realteks GIT."
        read -n 1 -p "The FW for the UB500 BT-Dongle is not present in /lib/firmware/rtl_bt/. /n Do you wish to download the file from Realteks Git and copy it to your system? [y/n]" FW_Install
          if [ "$FW_Install" = "y" ]; then
            echo -e "\033[33m"
            echo "Ok, continuing."
            echo -e "\033[0m"
            cd /home/max/FIX_UB_500_BT_Stick
            mkdir FW
            cd FW
            wget https://github.com/Realtek-OpenSource/android_hardware_realtek/raw/rtk1395/bt/rtkbt/Firmware/BT/rtl8761b_fw
            sudo cp /home/max/FIX_UB_500_BT_Stick/FW/rtl8761b_fw /lib/firmware/rtl_bt/rtl8761b_fw.bin
            if [[ -f "/lib/firmware/rtl_bt/rtl8761b_fw.bin" ]]; then
              echo -e "\033[33mFW was successfully copied. Reboot and try your bluetooth stick. It should work now."
            else
              echo -e "\033[33mSomething went wrong.You will have to download the FW yourself and place it in the folder /lib/firmware/rtl_bt/ with the name rtl8761b_fw.bin /n You'll find the file in this Repo: https://github.com/Realtek-OpenSource/android_hardware_realtek/raw/rtk1395/bt/rtkbt/Firmware/BT/rtl8761b_config /n If you placed the file there, reboot and your UB500 should work now."
            fi
          elif [ "$fFW_Install" = "n" ];then
            sudo rm -r /home/max/FIX_UB_500_BT_Stick
            echo -e "\033[33mFW was not downloaded. You will have to download the FW yourself and place it in the folder /lib/firmware/rtl_bt/ with the name rtl8761b_fw.bin /n You'll find the file in this Repo: https://github.com/Realtek-OpenSource/android_hardware_realtek/raw/rtk1395/bt/rtkbt/Firmware/BT/rtl8761b_config /n If you placed the file there, reboot and your UB500 should work now."
            echo -e "\033[0m"
            exit
          else
          echo -e "\033[31mDownload the FW? [y/n];"
            read -n 1
          fi
    else
      echo -e "\033[33mIt looks like, /lib/firmware/rtl_bt/rtl8761b_fw.bin already exists. No further steps needed. Reboot and try your UB500 BT-Stick."
    fi
    sudo rm -r /home/max/FIX_UB_500_BT_Stick
    echo -e "\033[33mDeleted downloaded files and dircetory /home/max/FIX_UB_500_BT_Stick"
    echo -e "\033[0m"
  elif [ "$start" = "n" ];then
    sudo rm -r /home/max/FIX_UB_500_BT_Stick
    exit
  else
    echo -e "\033[33mYou have entered an invallid selection!"
    echo -e "\033[33mPlease try again!"
    echo -e ""
    echo -e "\033[31mPress any key to continue..."
    read -n 1

  fi
  }

FIX_UB_500_BT_Stick

在第三步中,很遗憾hci_ldisc.c中的检查不起作用。所以你必须手动检查。
它使用kwrite作为文本编辑器。
不要以sudo身份运行脚本。等待它要求你输入sudo密码。
如果你像我一样对这一切都很陌生:
为了使其工作,创建一个文本文件,但使用.sh扩展名而不是.txt。
将所有代码复制到其中并保存。
在你的目录中打开一个终端。
chmod a+x YOURFILE.sh
bash YOURFILE.sh
严格按照指示操作。
我对我的答案进行了相当多的编辑,所以它更有帮助。

1这篇帖子是关于什么还不清楚?它回答了问题吗?还是说这是关于 KDE Neon 的修复,这个话题在这里是不相关的? - Pilot6
一个脚本,可以执行Aeolun的所有步骤。所以是Ubuntu的通用修复方法。但对我来说已经不起作用了。 - Max Christian Potaß
1为什么发布它如果它不起作用? - Pilot6
它确实能够解决Aeolun发布的可能修复方案。这个修复方案在Kubuntu上对我有效,但在KDE Neon上却无效。所以它可能有帮助,也可能没有。我不知道。但如果你想尝试,可以使用这个脚本,它会让事情变得更容易。关于这一点我不确定有什么不清楚的地方。 - Max Christian Potaß
我确实改变了脚本下面的那部分。也许是那个原因吧? - Max Christian Potaß
@Pilot6 再检查一下。我更新了我的脚本。现在完全修复了。 - Max Christian Potaß
你应该考虑将cd /home/max替换为某种临时目录,或者至少只使用cd命令,默认进入用户的主目录。个人建议创建一个临时工作目录,可以使用类似TMPDIR=$(mktemp -d -t btfix-XXXXXXXXXX)的方法实现。 - Kingsley
你是对的。至少我把它改成了只有"cd"。 - Max Christian Potaß