All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Explicitly disable BT radio using rfkill interface on suspend
@ 2009-05-18 20:12 Mario Limonciello
  2009-05-18 21:02 ` Matthew Garrett
  0 siblings, 1 reply; 35+ messages in thread
From: Mario Limonciello @ 2009-05-18 20:12 UTC (permalink / raw)
  To: linux-acpi, linux-kernel; +Cc: Matthew Garrett


[-- Attachment #1.1: Type: text/plain, Size: 417 bytes --]

 Dell BT devices need to be removed from the bus and reinserted
 so that userspace udev rules can transition the devices into the
 proper mode after S3 or S4.

---
 drivers/platform/x86/dell-laptop.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)


Attaching patch so Exchange doesn't mangle it.
-- 
Mario Limonciello
*Dell | Linux Engineering*
mario_limonciello@dell.com

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Explicitly-disable-BT-radio-using-rfkill-interface-o.patch --]
[-- Type: text/x-patch; name="0001-Explicitly-disable-BT-radio-using-rfkill-interface-o.patch", Size: 1842 bytes --]

From ab8b8ad20dede82f9d13293e94e76b4dd360fcf4 Mon Sep 17 00:00:00 2001
From: Mario Limonciello <Mario_Limonciello@Dell.com>
Date: Mon, 18 May 2009 21:07:59 +0100
Subject: [PATCH] Explicitly disable BT radio using rfkill interface on suspend.
 Dell BT devices need to be removed from the bus and reinserted
 so that userspace udev rules can transition the devices into the
 proper mode after S3 or S4.

---
 drivers/platform/x86/dell-laptop.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index af9f430..90a3d7c 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -186,6 +186,24 @@ static int dell_rfkill_set(int radio, enum rfkill_state state)
 	return 0;
 }
 
+static int dell_rfkill_suspend(struct device *dev, pm_message_t state)
+{
+	struct rfkill *rfkill = to_rfkill(dev);
+
+	/* store state for the resume handler */
+	rfkill->state_for_resume = rfkill->state;
+
+	/* kill radio explicitly if it's on. it needs proper
+	 * reinitialization post suspend */
+	rfkill->toggle_radio(NULL,RFKILL_STATE_SOFT_BLOCKED);
+
+	/* mark class device as suspended */
+	if (dev->power.power_state.event != state.event)
+		dev->power.power_state = state;
+
+	return 0;
+}
+
 static int dell_wifi_set(void *data, enum rfkill_state state)
 {
 	return dell_rfkill_set(1, state);
@@ -266,6 +284,7 @@ static int dell_setup_rfkill(void)
 		bluetooth_rfkill->name = "dell-bluetooth";
 		bluetooth_rfkill->toggle_radio = dell_bluetooth_set;
 		bluetooth_rfkill->get_state = dell_bluetooth_get;
+		bluetooth_rfkill->dev.class->suspend = dell_rfkill_suspend;
 		ret = rfkill_register(bluetooth_rfkill);
 		if (ret)
 			goto err_bluetooth;
-- 
1.5.4.3


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply related	[flat|nested] 35+ messages in thread
* Re: [PATCH] Explicitly disable BT radio using rfkill interface on
@ 2009-06-30 22:02 Mario Limonciello
  2009-07-01  3:53 ` [PATCH] Explicitly disable BT radio using rfkill interface on suspend Mario_Limonciello
  2009-07-01 13:13 ` Mario_Limonciello
  0 siblings, 2 replies; 35+ messages in thread
From: Mario Limonciello @ 2009-06-30 22:02 UTC (permalink / raw)
  To: linux-hotplug


[-- Attachment #1.1: Type: text/plain, Size: 2006 bytes --]

Hi Alan:


Alan Stern wrote:
> On Wed, 20 May 2009, Mario Limonciello wrote:
>
>   
>
> 	echo 0 >/sys/bus/usb/devices/.../power/persist
>
> This will also prevent reset-resume after hibernation.
>
>   
Yes, as it turns out this works properly for a single resume if I apply
that to the bits of all the child devices.  I take it that bit is just
for debugging purposes, and any solution centered around it would not be
a good solution.
>
> You can't.  Instead you have to arrange things so that when the
> intentional change was made, it left behind a timestamp indicator.  If
> that timestamp if present and not more than a few seconds in the past,
> you know the change was intentional.
>
>
>   
So I took up your advice here and tried to assemble a new udev rule and
function that would get called out upon when coming out of S3. It takes
the Vendor and Product IDs of the parent device of the device we just
lost and passes them to the new function.  The new function then tries
to walk that USB bus again to find the child device that it is supposed
to operate upon.

There is "remove" event in the udev log for that BT radio child device. 
I tried to extract as many attributes as I could from that information
and put it in the rule.  The details from this are in attribute_walk.out
(attached).

Unfortunately, this rule isn't getting ran after S3 even though I see
the remove event.  I can run udevadm test PATH (where PATH is the one of
the BT device we lost) and see that it should be spawning the rule.

However, running udevadm test -a remove PATH, I just see that the rule
gets matched, but not executed.  I can't help but think this is all very
close to functional and there is either something silly i'm doing wrong
or a deficiency of udev that's preventing the attributes from being
matched on the removal event.  Would you mind taking a look and/or
commenting?

-- 
Mario Limonciello
*Dell | Linux Engineering*
mario_limonciello@dell.com

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: resuscitate.patch --]
[-- Type: text/x-patch; name="resuscitate.patch", Size: 4327 bytes --]

=== modified file 'extras/hid2hci/70-hid2hci.rules'
--- extras/hid2hci/70-hid2hci.rules	2009-06-26 06:17:23 +0000
+++ extras/hid2hci/70-hid2hci.rules	2009-06-30 21:49:54 +0000
@@ -1,7 +1,7 @@
 # do not edit this file, it will be overwritten on update
 
-ACTION!="add", GOTO="hid2hci_end"
 SUBSYSTEM!="usb", GOTO="hid2hci_end"
+ACTION!="add|change", GOTO="addchange_end"
 
 # Variety of Dell Bluetooth devices - it looks like a bit of an odd rule,
 # because it is matching on a mouse device that is self powered, but that
@@ -22,4 +22,17 @@
 ATTR{idVendor}=="0458", ATTR{idProduct}=="1000", RUN+="hid2hci --method csr -v $attr{idVendor} -p $attr{idProduct} --mode hci"
 ATTR{idVendor}=="05ac", ATTR{idProduct}=="1000", RUN+="hid2hci --method csr -v $attr{idVendor} -p $attr{idProduct} --mode hci"
 
+LABEL="addchange_end"
+
+# When a Dell device recovers from S3, the mouse child needs to be repoked
+# Well, unfortunately the only event we see is the BT device disappearing, so
+# we have to run with that and chase down the mouse device on USB bus as a child.
+ATTR{bDeviceClass}=="e0", \
+ATTR{bDeviceSubClass}=="01", \
+ATTR{bDeviceProtocol}=="01", \
+ATTR{idVendor}=="413c", \
+ATTR{bmAttributes}=="e0", \
+IMPORT{parent}="ID_*", \
+RUN+="hid2hci --method dell -v $env{ID_VENDOR_ID} -p $env{ID_MODEL_ID} --mode hci -s 02"
+
 LABEL="hid2hci_end"

=== modified file 'extras/hid2hci/hid2hci.c'
--- extras/hid2hci/hid2hci.c	2009-06-16 17:30:22 +0000
+++ extras/hid2hci/hid2hci.c	2009-06-30 21:49:27 +0000
@@ -271,6 +271,28 @@
 	return 0;
 }
 
+static struct usb_device* find_resuscitated_device(uint16_t base_vendor, uint16_t base_product, uint8_t bInterfaceProtocol)
+{
+	struct usb_bus *bus;
+	struct usb_device *dev;
+	int i,j,k,l;
+
+	usb_find_busses();
+	usb_find_devices();
+
+	for (bus = usb_get_busses(); bus; bus = bus->next)
+		for (dev = bus->devices; dev; dev = dev->next)
+			if (dev->descriptor.idVendor == base_vendor &&
+			    dev->descriptor.idProduct == base_product)
+				for (i = 0; i < dev->num_children; i++)
+					for (j = 0; j < dev->children[i]->descriptor.bNumConfigurations; j++)
+						for (k = 0; k < dev->children[i]->config[j].bNumInterfaces; k++)
+							for (l = 0; l < dev->children[i]->config[j].interface[k].num_altsetting; l++)
+								if (dev->children[i]->config[j].interface[k].altsetting[l].bInterfaceProtocol == bInterfaceProtocol)
+									return dev->children[i];
+	return NULL;
+}
+
 static void usage(char* error)
 {
 	if (error)
@@ -289,6 +311,7 @@
 		"\t-v, --vendor=        Vendor ID to act upon\n"
 		"\t-p, --product=       Product ID to act upon\n"
 		"\t-m, --method=        Method to use to switch [csr, logitech, dell]\n"
+		"\t-s, --resuscitate=   Find the child device with this bInterfaceProtocol to run on \n"
 		"\n");
 	if (error)
 		exit(1);
@@ -301,6 +324,7 @@
 	{ "vendor",	required_argument, 0, 'v' },
 	{ "product",	required_argument, 0, 'p' },
 	{ "method",	required_argument, 0, 'm' },
+	{ "resuscitate",required_argument, 0, 's' },
 	{ 0, 0, 0, 0 }
 };
 
@@ -309,8 +333,9 @@
 	struct device_info dev = { NULL, HCI, 0, 0 };
 	int opt, quiet = 0;
 	int (*method)(struct device_info *dev) = NULL;
+	uint8_t resuscitate = 0;
 
-	while ((opt = getopt_long(argc, argv, "+r:v:p:m:qh", main_options, NULL)) != -1) {
+	while ((opt = getopt_long(argc, argv, "+s:r:v:p:m:qh", main_options, NULL)) != -1) {
 		switch (opt) {
 		case 'r':
 			if (optarg && !strcmp(optarg, "hid"))
@@ -341,6 +366,9 @@
 			break;
 		case 'h':
 			usage(NULL);
+        case 's':
+            sscanf(optarg, "%2hx", (short unsigned int*) &resuscitate);
+            break;
 		default:
 			exit(0);
 		}
@@ -355,7 +383,16 @@
 
 	usb_init();
 
-	if (!find_device(&dev)) {
+	if (resuscitate) {
+		dev.dev = find_resuscitated_device(dev.vendor, dev.product, resuscitate);
+		if (!quiet && !dev.dev) {
+			fprintf(stderr, "Device %04x:%04x was unable to resucitate any child devices.\n",dev.vendor,dev.product);
+			exit(1);
+		}
+		dev.vendor = dev.dev->descriptor.idVendor;
+		dev.product = dev.dev->descriptor.idProduct;
+	}
+	else if (!find_device(&dev)) {
 		if (!quiet)
 			fprintf(stderr, "Device %04x:%04x not found on USB bus.\n",
 				dev.vendor, dev.product);


[-- Attachment #1.3: attribute_walk.out --]
[-- Type: text/plain, Size: 3589 bytes --]


Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:04.0/usb3/3-4/3-4.3':
    KERNEL=="3-4.3"
    SUBSYSTEM=="usb"
    DRIVER=="usb"
    ATTR{configuration}==""
    ATTR{bNumInterfaces}==" 4"
    ATTR{bConfigurationValue}=="1"
    ATTR{bmAttributes}=="e0"
    ATTR{bMaxPower}=="100mA"
    ATTR{urbnum}=="186"
    ATTR{idVendor}=="413c"
    ATTR{idProduct}=="8156"
    ATTR{bcdDevice}=="0172"
    ATTR{bDeviceClass}=="e0"
    ATTR{bDeviceSubClass}=="01"
    ATTR{bDeviceProtocol}=="01"
    ATTR{bNumConfigurations}=="1"
    ATTR{bMaxPacketSize0}=="64"
    ATTR{speed}=="12"
    ATTR{busnum}=="3"
    ATTR{devnum}=="7"
    ATTR{version}==" 2.00"
    ATTR{maxchild}=="0"
    ATTR{quirks}=="0x0"
    ATTR{authorized}=="1"
    ATTR{manufacturer}=="Dell Computer Corp"
    ATTR{product}=="Dell Wireless 370 Bluetooth Mini-card"

  looking at parent device '/devices/pci0000:00/0000:00:04.0/usb3/3-4':
    KERNELS=="3-4"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}==" 94mA"
    ATTRS{urbnum}=="195"
    ATTRS{idVendor}=="0a5c"
    ATTRS{idProduct}=="4500"
    ATTRS{bcdDevice}=="0100"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{speed}=="12"
    ATTRS{busnum}=="3"
    ATTRS{devnum}=="2"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="3"
    ATTRS{quirks}=="0x0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Broadcom"
    ATTRS{product}=="BCM2046B1"

  looking at parent device '/devices/pci0000:00/0000:00:04.0/usb3':
    KERNELS=="usb3"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="  0mA"
    ATTRS{urbnum}=="75"
    ATTRS{idVendor}=="1d6b"
    ATTRS{idProduct}=="0001"
    ATTRS{bcdDevice}=="0206"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="12"
    ATTRS{busnum}=="3"
    ATTRS{devnum}=="1"
    ATTRS{version}==" 1.10"
    ATTRS{maxchild}=="4"
    ATTRS{quirks}=="0x0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Linux 2.6.30-10-generic ohci_hcd"
    ATTRS{product}=="OHCI Host Controller"
    ATTRS{serial}=="0000:00:04.0"
    ATTRS{authorized_default}=="1"

  looking at parent device '/devices/pci0000:00/0000:00:04.0':
    KERNELS=="0000:00:04.0"
    SUBSYSTEMS=="pci"
    DRIVERS=="ohci_hcd"
    ATTRS{vendor}=="0x10de"
    ATTRS{device}=="0x0aa5"
    ATTRS{subsystem_vendor}=="0x1028"
    ATTRS{subsystem_device}=="0x0271"
    ATTRS{class}=="0x0c0310"
    ATTRS{irq}=="21"
    ATTRS{local_cpus}=="ff"
    ATTRS{local_cpulist}=="0-7"
    ATTRS{modalias}=="pci:v000010DEd00000AA5sv00001028sd00000271bc0Csc03i10"
    ATTRS{broken_parity_status}=="0"
    ATTRS{msi_bus}==""

  looking at parent device '/devices/pci0000:00':
    KERNELS=="pci0000:00"
    SUBSYSTEMS==""
    DRIVERS==""


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2009-07-01 13:13 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-18 20:12 [PATCH] Explicitly disable BT radio using rfkill interface on suspend Mario Limonciello
2009-05-18 21:02 ` Matthew Garrett
2009-05-18 21:36   ` Mario Limonciello
2009-05-19  5:03     ` Matthew Garrett
2009-05-19  5:14       ` Marcel Holtmann
2009-05-19  6:27         ` Oliver Neukum
2009-05-19  6:27           ` Oliver Neukum
2009-05-19  6:45           ` Marcel Holtmann
2009-05-19  7:36             ` Oliver Neukum
2009-05-19  9:06         ` Matthew Garrett
2009-05-19 12:47           ` Oliver Neukum
2009-05-19 12:58             ` Matthew Garrett
2009-05-19 16:30               ` Mario Limonciello
2009-05-19 16:33                 ` Matthew Garrett
2009-05-19 16:52                   ` Mario Limonciello
2009-05-19 19:58                     ` Oliver Neukum
2009-05-19 20:36                       ` Mario Limonciello
2009-05-19 21:26                         ` Oliver Neukum
2009-05-19 21:26                           ` Oliver Neukum
2009-05-19 21:47                           ` Mario Limonciello
     [not found]                             ` <4A1328D6.5090404-8PEkshWhKlo@public.gmane.org>
2009-05-19 22:16                               ` Oliver Neukum
2009-05-19 22:16                                 ` Oliver Neukum
     [not found]                                 ` <200905200016.49110.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
2009-05-19 22:19                                   ` Mario Limonciello
2009-05-19 22:19                                     ` Mario Limonciello
2009-05-20  2:17                                 ` Alan Stern
2009-05-20  2:17                                   ` Alan Stern
2009-05-20 12:29                                   ` Oliver Neukum
2009-05-20 12:29                                     ` Oliver Neukum
     [not found]                                     ` <200905201429.06113.oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
2009-05-20 14:17                                       ` Alan Stern
2009-05-20 14:17                                         ` Alan Stern
2009-05-20 17:52                                         ` Mario Limonciello
     [not found]                                           ` <4A144347.80303-8PEkshWhKlo@public.gmane.org>
2009-05-20 18:31                                             ` Alan Stern
2009-05-20 18:31                                               ` Alan Stern
  -- strict thread matches above, loose matches on Subject: below --
2009-06-30 22:02 [PATCH] Explicitly disable BT radio using rfkill interface on Mario Limonciello
2009-07-01  3:53 ` [PATCH] Explicitly disable BT radio using rfkill interface on suspend Mario_Limonciello
2009-07-01 13:13 ` Mario_Limonciello

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.