Fixing thinkpad bluetooth keyboard (by quqi99)

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 (作者:张华 发表于: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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

quqi99

你的鼓励就是我创造的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值