2011/2/24 Martin Pitt <martin.p...@ubuntu.com>: > Hello Lin, > > Keng-Yu Lin [2011-02-24 14:49 +0800]: >> +btusbget() { >> + local dev usb >> + usb="/sys/bus/usb/devices" >> + for dev in "$usb"/*; do >> + [[ -f "${dev}/bDeviceClass" ]] || continue >> + [[ "$(cat "${dev}/bDeviceClass")" = "e0" ]] || continue # Wireless >> + [[ -f "${dev}/bDeviceProtocol" ]] || continue >> + [[ "$(cat "${dev}/bDeviceProtocol")" = "01" ]] || continue # Bluetooth >> + case $1 in >> + vendor) echo "$(cat "${dev}/idVendor")" ;; >> + device) echo "$(cat "${dev}/idProduct")" ;; >> + esac >> + break >> + done >> +} > > This should still be improved, as it will run hundreds of cat > subprocesses, iterate through the device tree twice, and also stop at > the first bluetooth adapter instead of testing all of them. > > A nice trick for this is to use udevadm trigger. This works on my > system (with a different adapter which I added to $quirks for > testing): > > ---------------- 8< -------------------- > quirks="0a5c:219c 0a5c:21bc 413c:8187" > > for usbid in $quirks; do > vendor=${usbid%:*} > product=${usbid#*:} > > DEVS=$(udevadm trigger --verbose --dry-run \ > --attr-match=bDeviceClass=e0 --attr-match=bDeviceProtocol=01 \ > --attr-match=idVendor=$vendor --attr-match=idProduct=$product) > if [ -n "$DEVS" ]; then > echo add_parameters --quirk-bluetooth-service-off > fi > done > ---------------- 8< -------------------- > > This will consider all bluetooth adapters and only do one external > program call. Can you please confirm that this still works on your > system? This should also be forwarded upstream, but Michael and I can > also take care of that. >
Hi Martin: I removed the echo before add_parameters. It works well. I attached the modified patch in this mail. Thanks for taking care of this. -kengyu
From 021a1c5696ec7bdf6434550bb48cca67c1846d82 Mon Sep 17 00:00:00 2001 From: Keng-Yu Lin <keng-yu....@canonical.com> Date: Fri, 25 Feb 2011 15:59:43 +0800 Subject: [PATCH] Add the quirk support for stoping/restarting bluetooth service It is found that the bluetooth modules with USB VID/PIDs [0a5c:219c] [0a5c:21bc] and [413c:8187] are causing random S4 hangs on various laptops with SandyBridge chipset. The hangs can be observed by repeating hibernate/resume in a 250 iterations. The successful cycles number before the hang is usually ranged in tens, though it varies on different types of laptops. This patch added a parameter for the use as "pm-hibernate --quirk-bluetooth-service-off" and a couple of USB ID quirks I found with this S4 problem. Martin Pitt contributed the code to utilize udevadm for matching the quirk in sysfs. Signed-off-by: Keng-Yu Lin <keng-yu....@canonical.com> --- pm/sleep.d/44bluetooth-known-quirk | 24 +++++++++++++++++++++ pm/sleep.d/45bluetooth-service | 41 ++++++++++++++++++++++++++++++++++++ pm/sleep.d/Makefile.am | 2 + 3 files changed, 67 insertions(+), 0 deletions(-) create mode 100755 pm/sleep.d/44bluetooth-known-quirk create mode 100755 pm/sleep.d/45bluetooth-service diff --git a/pm/sleep.d/44bluetooth-known-quirk b/pm/sleep.d/44bluetooth-known-quirk new file mode 100755 index 0000000..f9df8b8 --- /dev/null +++ b/pm/sleep.d/44bluetooth-known-quirk @@ -0,0 +1,24 @@ +#!/bin/bash + +. "${PM_FUNCTIONS}" + +quirks="0a5c:219c 0a5c:21bc 413c:8187" + +case "$1" in + hibernate|suspend) + # known bluetooth devices needing to stop bluetoothd + for usbid in $quirks; do + vendor=${usbid%:*} + product=${usbid#*:} + + DEVS=$(udevadm trigger --verbose --dry-run \ + --attr-match=bDeviceClass=e0 --attr-match=bDeviceProtocol=01 \ + --attr-match=idVendor=$vendor --attr-match=idProduct=$product) + if [ -n "$DEVS" ]; then + add_parameters --quirk-bluetooth-service-off + fi + done + ;; + thaw|resume) + ;; +esac diff --git a/pm/sleep.d/45bluetooth-service b/pm/sleep.d/45bluetooth-service new file mode 100755 index 0000000..969ca86 --- /dev/null +++ b/pm/sleep.d/45bluetooth-service @@ -0,0 +1,41 @@ +#!/bin/bash + +. "${PM_FUNCTIONS}" + +for opt in $PM_CMDLINE; do + case "${opt##--quirk-}" in # just quirks, please + bluetooth-service-off) QUIRK_BLUETOOTH_SERVICE_OFF="true" ;; + bluetooth-none) QUIRK_BLUETOOTH_NONE="true" ;; + *) continue ;; + esac +done + +quirk() { is_set "$1" && [ -z $QUIRK_BLUETOOTH_NONE ]; } + +suspend_bluetooth_service() +{ + quirk "${QUIRK_BLUETOOTH_SERVICE_OFF}" && stopservice bluetooth +} + +resume_bluetooth_service() +{ + quirk "${QUIRK_BLUETOOTH_SERVICE_OFF}" && restartservice bluetooth +} + +help() { + echo # first echo makes it look nicer. + echo "Bluetooth quirk handler options:" + echo + echo " --quirk-bluetooth-service-off" + echo " --quirk-bluetooth-none" +} + +case "$1" in + hibernate|suspend) + suspend_bluetooth_service + ;; + thaw|resume) + resume_bluetooth_service + ;; + help) help ;; +esac diff --git a/pm/sleep.d/Makefile.am b/pm/sleep.d/Makefile.am index 2350825..88df79c 100644 --- a/pm/sleep.d/Makefile.am +++ b/pm/sleep.d/Makefile.am @@ -4,6 +4,8 @@ sleep_SCRIPTS = \ 00logging \ 00powersave \ 01grub \ + 44bluetooth-known-quirk \ + 45bluetooth-service \ 49bluetooth \ 55NetworkManager \ 75modules \ -- 1.7.1