版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 (作者:张华 发表于:2019-03-30)
为了保护颈椎, 已经习惯不用鼠标, 但是高度依赖于Thinkpad的小红点鼠标. 但是蓝牙经常性一个月会断一次, 断了之后很难连接上. 这次更奇葩了, 蓝牙灯也不灭, 键盘上也没有重置的键, 只好等到今天蓝牙键盘电池耗尽之后再试, 但是还是连不上, 错误为:
Mar 30 07:46:42 t440p bluetoothd[10079]: Can't get HIDP connection info
Mar 30 07:46:43 t440p bluetoothd[10079]: connect error: Invalid exchange (52)
Mar 30 07:46:50 t440p kernel: [240741.397564] Bluetooth: hci0: last event is not cmd complete (0x0f)
在设置GUI里先删除这个蓝牙, 也报错:
Mar 30 07:58:28 t440p gnome-control-c[9696]: Failed to remove device '/org/bluez/hci1/dev_90_7F_61_00_23_C3': GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name :1.505 was not provided by any .service files
好吧, 通过下列命令删除, 再连接, 这次终于算成功了. 本博客将继续记录蓝牙今后遇到的所有连接问题.
hua@t440p:$ bluetoothctl
[NEW] Controller 00:15:00:CB:B0:FF t440p #2 [default]
[NEW] Device 90:7F:61:00:23:C3 ThinkPad Compact Bluetooth Keyboard with TrackPoint
[NEW] Device 04:F1:28:31:D2:10 Nokia 7
[NEW] Controller 00:1A:7D:DA:71:13 t440p #1
[NEW] Device 00:15:00:CB:B0:FF t440p
[NEW] Device 90:7F:61:00:23:C3 ThinkPad Compact Bluetooth Keyboard with TrackPoint
Agent registered
[bluetooth]# list
Controller 00:15:00:CB:B0:FF t440p #2 [default]
Controller 00:1A:7D:DA:71:13 t440p #1
[bluetooth]# devices
Device 90:7F:61:00:23:C3 ThinkPad Compact Bluetooth Keyboard with TrackPoint
Device 04:F1:28:31:D2:10 Nokia 7
[bluetooth]# info 90:7F:61:00:23:C3
Device 90:7F:61:00:23:C3 (public)
Name: ThinkPad Compact Bluetooth Keyboard with TrackPoint
Alias: ThinkPad Compact Bluetooth Keyboard with TrackPoint
Class: 0x00000540
Icon: input-keyboard
Paired: yes
Trusted: no
Blocked: no
Connected: no
LegacyPairing: no
[bluetooth]# remove 90:7F:61:00:23:C3
[DEL] Device 90:7F:61:00:23:C3 ThinkPad Compact Bluetooth Keyboard with TrackPoint
Device has been removed
[bluetooth]# power on
Changing power on succeeded
注:20220414更新, 今天忽然遇到这么一个问题,平时使用蓝牙键盘好好的,平时也不用鼠标,但昨天临时插了一个蓝牙鼠标,结果今天无法使用蓝牙键盘唤醒了。然后接usb链盘在gnome的蓝牙设置处无法打开蓝牙。而此时的表现是:
1, 使用bluetoothctl无法检测到controller, 也就无法检测到蓝牙
$ sudo bluetoothctl
Agent registered
[bluetooth]# show
No default controller available
2, 此时,bluetooth服务是正常的,也可以使用bluetoothd -n -d来调试
sudo systemctl stop bluetooth
#sudo bluetoothd -n -d
3, 看到如下log
hua@t440p:~$ dmesg | grep -i bluetooth
[ 6.989347] thinkpad_acpi: rfkill switch tpacpi_bluetooth_sw: radio is unblocked
[ 8.100694] Bluetooth: Core ver 2.22
[ 8.100722] Bluetooth: HCI device and connection manager initialized
[ 8.100725] Bluetooth: HCI socket layer initialized
[ 8.100726] Bluetooth: L2CAP socket layer initialized
[ 8.100728] Bluetooth: SCO socket layer initialized
[ 10.240756] Bluetooth: hci0: command 0x0c03 tx timeout
[ 12.914425] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[ 12.914426] Bluetooth: BNEP filters: protocol multicast
[ 12.914430] Bluetooth: BNEP socket layer initialized
[ 18.272725] Bluetooth: hci0: sending initial HCI reset command failed (-110)
最后,根据https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1859592 这个bug的提示,将所有usb外设全拨了再重启就好了(之前也没拔usb重启过未果)
4, 在grub中添加了btusb.enable_autosuspend=n
一行命令搞定:
#bt-device -l |grep -i keyboard
DEVICE_MAC='90:7F:61:00:23:C3'
<<<"connect $DEVICE_MAC" bluetoothctl
<<<"connect $DEVICE_MAC" bluetoothctl &> /dev/null
然后升级bluez到5.5版本
dpkg --status bluez | grep '^Version:'
sudo add-apt-repository ppa:bluetooth/bluez
sudo apt-get update
sudo apt-get upgrade
解决suspend唤醒之后的usb问题
#重启USB
#!/bin/bash
for I in $(ls /sys/bus/pci/drivers/xhci_hcd/|grep : ) ; do
echo $I
sudo echo $I > /sys/bus/pci/drivers/xhci_hcd/unbind
sudo echo $I > /sys/bus/pci/drivers/xhci_hcd/bind
done
#https://itectec.com/ubuntu/ubuntu-wakes-from-suspend-immediately-when-bluetooth-device-disconnected/
#通过重启USB让系统进入suspend之后马上又唤醒
chmod a+x /lib/systemd/system-sleep/custom-xhci_hcd
#!/bin/bash
# Original script was using /bin/sh but shellcheck reporting warnings.
# NAME: custom-xhci_hcd
# PATH: /lib/systemd/system-sleep
# CALL: Called from SystemD automatically
# DESC: Suspend broken for USB3.0 as of Oct 25/2018 various kernels all at once
# DATE: Oct 28 2018.
# NOTE: From comment #61 at: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/522998
TMPLIST=/tmp/xhci-dev-list
# Original script was: case "${1}" in hibernate|suspend)
case $1/$2 in
pre/*)
echo "$0: Going to $2..."
echo -n '' > $TMPLIST
for i in `ls /sys/bus/pci/drivers/xhci_hcd/ | egrep '[0-9a-z]+\:[0-9a-z]+\:.*$'`; do
# Unbind xhci_hcd for first device XXXX:XX:XX.X:
echo -n "$i" | tee /sys/bus/pci/drivers/xhci_hcd/unbind
echo "$i" >> $TMPLIST
done
;;
post/*)
echo "$0: Waking up from $2..."
for i in `cat $TMPLIST`; do
# Bind xhci_hcd for first device XXXX:XX:XX.X:
echo -n "$i" | tee /sys/bus/pci/drivers/xhci_hcd/bind
done
rm $TMPLIST
;;
esac
如果想在系统在suspend时usb不suspend 还能继续供电的话可以修改/etc/tlp.conf添加: USB_AUTOSUSPEND=0 即可
20220215更新: 根据(https://wiki.archlinux.org/title/bluetooth)在grub中添加了btusb.enable_autosuspend=n
让蓝牙不autosuspend或者通过蓝牙唤醒suspend系统(not work)
现在的问题是不是唤醒之后蓝牙有问题,而是蓝牙无法唤醒suspend系统。我的问题如同的描述 - https://unix.stackexchange.com/questions/609438/how-can-i-use-a-usb-keyboard-or-mouse-to-wake-from-suspend
将下面语句添加到rc.local中去,
echo enabled > /sys/bus/usb/devices/3-11/power/wakeup
或者使用udev,但都不work
#lsusb -tv |grep btusb -A1
vim /etc/udev/rules.d/80-persistent-usb.rules
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="8087", ATTRS{idProduct}=="07dc" RUN+="/bin/sh -c 'echo enabled > /sys/bus/usb/devices/3-11/power/wakeup'"
sudo update-initramfs -u
下面是不让蓝牙进入autosuspend的方法,但也不work
lsusb -tv
grep . /sys/bus/usb/devices/*/product
root@t440p:~# grep -r 'auto' /etc/rc.local
# disable bluetooth's autosuspend - dmesg |grep blue
echo -1 >/sys/bus/usb/devices/3-11/power/autosuspend_delay_ms
root@t440p:~# grep -r 'IdleTimeout' /etc/bluetooth/input.conf
IdleTimeout=0
root@t440p:~# grep -r 'FastConnectable' /etc/bluetooth/main.conf
FastConnectable = true
sudo systemctl restart bluetooth
sudo systemctl suspend #or sudo pm-suspend
#https://blog.csdn.net/weixin_43971560/article/details/100591034
sudo apt-get install --reinstall xserver-xorg-input-all
下面的也不work
# chmod a+x /usr/lib/pm-utils/sleep.d/45fixbluetoothwakeup
#!/bin/bash
case $1 in
hibernate)
echo "Going to suspend to disk!"
;;
suspend)
/etc/init.d/bluetooth start
echo enabled > /sys/bus/usb/devices/3-11/power/wakeup
/sbin/modprobe btusb
echo "Suspending to RAM."
;;
thaw)
echo "Suspend to disk is now over!"
;;
resume)
/etc/init.d/bluetooth start
echo "We are now resuming."
;;
*)
echo "Somebody is callin me totally wrong."
;;
esac
这个网页的方法(http://www.thedreaming.org/2020/11/13/ubuntu-mac-bluetooth-wake/)也不work, 它会交/sys/devices/pci0000:00/0000:00:14.0/usb3/3-11/power/wakeup设置成enabled, 它会让它一进入suspend马上就又唤醒了。
root@t440p:~# lsusb -tv |grep btusb -A1
|__ Port 11: Dev 5, If 0, Class=Wireless, Driver=btusb, 12M
ID 8087:07dc Intel Corp.
|__ Port 11: Dev 5, If 1, Class=Wireless, Driver=btusb, 12M
ID 8087:07dc Intel Corp.
root@t440p:~# lsusb |grep 8087:07dc
Bus 003 Device 005: ID 8087:07dc Intel Corp.
root@t440p:~# lsusb -v -s 003:005 |grep 'id'
idVendor 0x8087 Intel Corp.
idProduct 0x07dc
root@t440p:~# lsusb -v -d 8087:07dc |grep -i bus
Bus 003 Device 005: ID 8087:07dc Intel Corp.
#DEVPATH is /devices/pci0000:00/0000:00:14.0/usb3/3-11
root@t440p:~# udevadm info -q path -n /dev/bus/usb/003/005
/devices/pci0000:00/0000:00:14.0/usb3/3-11
root@t440p:~# udevadm info -a -p $(udevadm info -q path -n /dev/bus/usb/003/005)
...
root@t440p:~# cat /sys/devices/pci0000:00/0000:00:14.0/usb3/3-11/power/wakeup
enabled
https://blog.csdn.net/quqi99/article/details/78729252
# /usr/local/sbin/enable-wakeup /sys/devices/pci0000:00/0000:00:14.0/usb3/3-11/power/wakeup
root@t440p:~# cat /etc/udev/rules.d/80-persistent-usb.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="8087", ATTRS{idProduct}=="07dc" RUN+="/usr/local/sbin/enable-wakeup $env{DEVPATH}"
#don't forget to run: sudo update-initramfs -u
# https://unix-memo.readthedocs.io/en/latest/udev.html
#test it by: udevadm test /devices/pci0000:00/0000:00:14.0/usb3/3-11
root@t440p:~# cat /usr/local/sbin/enable-wakeup
#!/bin/bash
#
# Script to enable a USB devices to be used to resume computer from sleep
#
# Depends on udevadm package
# 09/05/2012 - V1.0 by Nicolas Bernaerts
# if device has been removed, exit
[ "$ACTION" = "remove" ] && exit 0
# set PATH as it is not set for udev scripts
PATH="/usr/sbin:/usr/bin:/sbin:/bin"
# set device SYSFS path
DEVICE_SYSFS="/sys$1"
CURRENT_SYSFS=$DEVICE_SYSFS
# get device product and vendor name from parent SYSFS
DEVICE_VENDOR=`udevadm info --query=all -p "$CURRENT_SYSFS/../" | grep "ID_VENDOR_ID=" | cut -d "=" -f 2`
DEVICE_PRODUCT=`udevadm info --query=all -p "$CURRENT_SYSFS/../" | grep "ID_MODEL_ID=" | cut -d "=" -f 2`
DEVICE_LABEL=`lsusb | grep "${DEVICE_VENDOR}:${DEVICE_PRODUCT}" | sed 's/^.*[0-9a-f]\:[0-9a-f]* \(.*\)$/\1/g'`
# loop thru the SYSFS path, up to PCI bus
CARRY_ON=1
while [ $CARRY_ON -eq 1 ]
do
# get the first three letters of current SYSFS folder
FIRST_LETTERS=`basename $CURRENT_SYSFS | sed 's/^\(...\).*$/\1/g'`
# if current SYSFS is PCI bus, stop the loop
if [ "$FIRST_LETTERS" = "pci" ] || [ "$FIRST_LETTERS" = "/" ] ; then
CARRY_ON=0
# else,
else
# if possible, enable wakeup for current SYSFS
WAKEUP_FILE="${CURRENT_SYSFS}/power/wakeup"
if [ -f $WAKEUP_FILE ]; then
echo "enabled" > $WAKEUP_FILE
fi
# go to father directory of current SYSFS
CURRENT_SYSFS=`dirname $CURRENT_SYSFS`
fi
done
# log the action
LOG_HEADER="USB device ${DEVICE_VENDOR}:${DEVICE_PRODUCT}"
logger "${LOG_HEADER} - Description : ${DEVICE_LABEL}"
logger "${LOG_HEADER} - SysFS path : ${DEVICE_SYSFS}"
logger "${LOG_HEADER} - Device is enabled to handle suspend/resume"
总结
下面两个设置了运行’systemctl suspend’后再敲蓝牙键盘不会有任何反应:
# grep . /sys/bus/usb/devices/*/power/wakeup
echo enabled > /sys/bus/usb/devices/3-11/power/wakeup
echo enabled > /sys/devices/pci0000:00/0000:00:14.0/usb3/3-11/power/wakeup
下面设置了之后再suspend之后不敲蓝牙键盘也马上会wakeup无法使用:
echo enabled > /sys/bus/usb/devices/usb3/power/wakeup
看来目前使用蓝牙键盘唤醒suspend系统是不可能的了,放弃,将suspend改为1小时这样短途休息时不用suspend,第二天要唤醒时使用电源键或者专门买一个无线鼠标来专门用于唤醒。
20220217更新
蓝牙在休眠后总是恢复不了,可能跟系统的high cpu load有点相关:
ps aux --sort="-pcpu" |head -n15
另外,发现只是过一个小时蓝牙suspend之后才唤不配,可以将btusb与usbcore设置为不autosuspend
$ dmesg |grep -i bluetooth |tail -n2
[38641.161758] input: ThinkPad Compact Bluetooth Keyboard with TrackPoint as /devices/pci0000:00/0000:00:14.0/usb3/3-11/3-11:1.0/bluetooth/hci0/hci0:256/0005:17EF:6048.0005/input/input26
[38641.162614] lenovo 0005:17EF:6048.0005: input,hidraw2: BLUETOOTH HID v3.12 Keyboard [ThinkPad Compact Bluetooth Keyboard with TrackPoint] on 00:15:00:cb:b0:ff
# 这里是关键,这是之前蓝牙自动autosuspend的根本原因
echo enabled > /sys/bus/usb/devices/3-11/power/wakeup
echo enabled > /sys/bus/usb/devices/usb3/power/wakeup
echo on > /sys/bus/usb/devices/3-11/power/level
echo on > /sys/bus/usb/devices/usb3/power/level
$ grep . /sys/bus/usb/devices/*/power/wakeup |grep 3-11
/sys/bus/usb/devices/3-11/power/wakeup:enabled
# grub
btusb.enable_autosuspend=n usbcore.autosuspend=-1 usbcore.autosuspend_delay_ms=-1
cat cat /sys/module/usbcore/parameters/autosuspend
$ grep -r 'IdleTimeout' /etc/bluetooth/input.conf
IdleTimeout=0
问题终于找到了,原因是上面使用rc.local设置的’echo enabled > /sys/bus/usb/devices/3-11/power/wakeup’会定期失效。所以再添加:
cat << EOF | sudo tee /usr/lib/pm-utils/sleep.d/45fixbluetoothwakeup
#!/bin/bash
case \$1 in
hibernate)
echo "Going to suspend to disk!"
;;
suspend)
#/etc/init.d/bluetooth start
echo enabled > /sys/bus/usb/devices/3-11/power/wakeup
echo on > /sys/bus/usb/devices/3-11/power/level
#/sbin/modprobe btusb
echo "Suspending to RAM."
;;
thaw)
echo "Suspend to disk is now over!"
;;
resume)
#/etc/init.d/bluetooth start
echo "We are now resuming."
;;
*)
echo "Somebody is callin me totally wrong."
;;
esac
EOF
sudo chmod a+x /usr/lib/pm-utils/sleep.d/45fixbluetoothwakeup
sudo /usr/lib/pm-utils/sleep.d/45fixbluetoothwakeup suspend
vim /var/log/pm-suspend.log
20220228更新
上面的‘20220217更新’确实通过/usr/lib/pm-utils/sleep.d/45fixbluetoothwakeup解决了蓝牙在auto suspend后无法唤醒导致无法自动连接的问题。但今天遇到另外一种情况,由于chrome突然更新, cpu usage上来了,蓝牙就失去了连接,过一会,cpu usage下去了,但蓝牙键盘将不会再次连接.
先禁用掉chrome ComponentUpdatesEnabled
# https://support.google.com/chrome/a/answer/9052345
# https://support.google.com/chrome/a/answer/9027408
# ComponentUpdatesEnabled equals --disable-component-update
grep -r 'repo_add_once=false'/etc/default/google-chrome
sudo mkdir -p /etc/opt/chrome/policies/managed
cat << EOF | sudo tee /etc/opt/chrome/policies/managed/component_update.json
{
"ComponentUpdatesEnabled": "false"
}
EOF
Another post
https://blog.csdn.net/quqi99/article/details/103754977
https://zhhuabj.blog.csdn.net/article/details/83109470
Reference
[1] https://askubuntu.com/questions/822249/unpair-remove-bluetooth-devices-in-16-04-1-and-other-problems
[2] http://events17.linuxfoundation.org/sites/events/files/slides/Bluetooth%20on%20Modern%20Linux_0.pdf
[3] https://medium.com/@overcode/fixing-bluetooth-in-ubuntu-pop-os-18-04-d4b8dbf7ddd6