public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Jes Sorensen <jes.sorensen@gmail.com>
To: Alan Jenkins <sourcejedi.lkml@googlemail.com>
Cc: linux-acpi@vger.kernel.org,
	linux-kernel <linux-kernel@vger.kernel.org>,
	lenb@kernel.org, Matthew Garrett <mjg59@srcf.ucam.org>
Subject: Toshiba Bluetooth enabler (v2) (was: Re: [PATCH] Toshiba Bluetooth enabler (rfkill))
Date: Tue, 08 Dec 2009 17:58:17 +0100	[thread overview]
Message-ID: <4B1E85A9.3030005@gmail.com> (raw)
In-Reply-To: <9b2b86520912080205x478b47eek2377dacdbe44a522@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1950 bytes --]

On 12/08/2009 11:05 AM, Alan Jenkins wrote:
> Cool.  This must be the shortest ACPI driver :-).

Hi Alan,

Here's an updated version that addresses most of your comments.

> Try to send patches inline if possible, it makes them easier to review.

Not possible with Thunderbug, sorry.

>> +static int toshiba_bt_rfkill_add(struct acpi_device *device);
>
> I think it's simpler to avoid the need for forward declarations, e.g.
> by putting the driver structure after the ops functions.  I suppose
> it's a matter of taste though.

I am going to keep it as is. I find it cleaner and it is more consistent
with how other drivers are written IMHO.

> Please also set
> 	.owner = THIS_MODULE,

Good point, thanks!

>> +static int toshiba_bt_resume(struct acpi_device *device)
>> +{
>> +	return toshiba_bluetooth_enable(device->handle);
>> +}
>
> Good to see you're handling resume, but what happens if the rfkill
> switch is _not_ set to on?  It looks like resume will return an error,
> which will produce a warning message in the kernel log.  I don't think
> we want that.

Fixed, this version only calls the enabler if the switch is at ON at
resume time.

>> +	status = acpi_evaluate_integer(device->handle, "_STA", NULL,
>> +				&bt_present);
>
> I think this would benefit from an explanation.

Comments added.

>> +	result = acpi_bus_register_driver(&toshiba_bt_rfkill_driver);
>> +	if (result<  0) {
>> +		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
>> +				  "Error registering driver\n"));
>> +		return -ENODEV;
>> +	}
>
> I would suggest you return result, instead of ignoring it and always
> returning ENODEV.

I agree, added.

>
>> +	depends on RFKILL
>> +	depends on BT
>
> But you doesn't use either of these subsystems :-). The BT one
> definitely seems bogus; please drop it.

It seemed kinda silly to me to enable this driver on kernels with no
BT subsystem, but it's not a biggie so I pulled it.

Please find attached v2 of the patch.

Cheers,
Jes


[-- Attachment #2: 0002-toshiba-bluetooth-v2.patch --]
[-- Type: text/plain, Size: 6411 bytes --]

Toshiba Bluetooth Enabling driver (RFKill handler)

This patch adds support for the ACPI events generated by the RFKill
switch on modern Toshiba laptops, and re-enables the Bluetooth USB
device when the switch is flipped back to the 'on' position.

The RFKill switch brute force pulls out the USB device when flipped to
'off', but it doesn't automatically re-enable it. Without this driver,
the Bluetooth is gone until after a reboot on my Portege R500.

Signed-off-by: Jes Sorensen <Jes.Sorensen@gmail.com>
---

Index: linux-2.6.31.5/drivers/platform/x86/toshiba_bluetooth.c
===================================================================
--- /dev/null
+++ linux-2.6.31.5/drivers/platform/x86/toshiba_bluetooth.c
@@ -0,0 +1,151 @@
+/*
+ * Toshiba Bluetooth Enable Driver
+ *
+ * Copyright (C) 2009 Jes Sorensen <Jes.Sorensen@gmail.com>
+ *
+ * Thanks to Matthew Garrett for background info on ACPI innards which
+ * normal people aren't meant to understand :-)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Note the Toshiba Bluetooth RFKill switch seems to be a strange
+ * fish. It only provides a BT event when the switch is flipped to
+ * the 'on' position. When flipping it to 'off', the USB device is
+ * simply pulled away underneath us, without any BT event being
+ * delivered.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>");
+MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver");
+MODULE_LICENSE("GPL");
+
+
+static int toshiba_bt_rfkill_add(struct acpi_device *device);
+static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type);
+static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
+static int toshiba_bt_resume(struct acpi_device *device);
+
+static const struct acpi_device_id bt_device_ids[] = {
+	{ "TOS6205", 0},
+	{ "", 0},
+};
+MODULE_DEVICE_TABLE(acpi, bt_device_ids);
+
+static struct acpi_driver toshiba_bt_rfkill_driver = {
+	.name =		"Toshiba BT",
+	.class =	"Toshiba",
+	.ids =		bt_device_ids,
+	.ops =		{
+				.add =		toshiba_bt_rfkill_add,
+				.remove =	toshiba_bt_rfkill_remove,
+				.notify =	toshiba_bt_rfkill_notify,
+				.resume =	toshiba_bt_resume,
+			},
+	.owner = 	THIS_MODULE,
+};
+
+
+static int toshiba_bluetooth_enable(acpi_handle handle)
+{
+	acpi_status res1, res2;
+	acpi_integer result;
+
+	/* Query ACPI to verify RFKill switch is set to on */
+	res1 = acpi_evaluate_integer(handle, "BTST", NULL, &result);
+	if (ACPI_FAILURE(res1) || !(result & 0x01))
+		return -EBUSY;
+
+	printk(KERN_INFO "toshiba_bluetooth: Re-enabling Toshiba Bluetooth\n");
+	res1 = acpi_evaluate_object(handle, "AUSB", NULL, NULL);
+	res2 = acpi_evaluate_object(handle, "BTPO", NULL, NULL);
+	if (!ACPI_FAILURE(res1) || !ACPI_FAILURE(res2)) {
+		return 0;
+	}
+	printk(KERN_WARNING "toshiba_bluetooth: Failed to re-enable "
+	       "Toshiba Bluetooth\n");
+
+	return -ENODEV;
+}
+
+static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
+{
+	toshiba_bluetooth_enable(device->handle);
+}
+
+static int toshiba_bt_resume(struct acpi_device *device)
+{
+	acpi_status res1;
+	acpi_integer result;
+
+	/*
+	 * Query ACPI to verify RFKill switch is set to on before trying
+	 * to re-enable the device or we will get back an error.
+	 */
+	res1 = acpi_evaluate_integer(device->handle, "BTST", NULL, &result);
+	if (ACPI_FAILURE(res1) || !(result & 0x01))
+		return 0;
+	return toshiba_bluetooth_enable(device->handle);
+}
+
+static int toshiba_bt_rfkill_add(struct acpi_device *device)
+{
+	acpi_status status;
+	acpi_integer bt_present;
+	int result = -ENODEV;
+
+	/*
+	 * Some Toshiba laptops may have a fake TOS6205 device in
+	 * their ACPI BIOS, so query the _STA method to see if there
+	 * is really anything there, before trying to enable it.
+	 */
+	status = acpi_evaluate_integer(device->handle, "_STA", NULL,
+				       &bt_present);
+
+	if (!ACPI_FAILURE(status) && bt_present) {
+		printk(KERN_INFO "Detected Toshiba ACPI Bluetooth device - "
+		      "installing RFKill handler\n");
+		result = toshiba_bluetooth_enable(device->handle);
+	}
+
+	return result;
+}
+
+static int __init toshiba_bt_rfkill_init(void)
+{
+	int result;
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	result = acpi_bus_register_driver(&toshiba_bt_rfkill_driver);
+	if (result < 0) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+				  "Error registering driver\n"));
+		return result;
+	}
+
+	return 0;
+}
+
+static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type)
+{
+	/* clean up */
+	return 0;
+}
+
+static void __exit toshiba_bt_rfkill_exit(void)
+{
+	acpi_bus_unregister_driver(&toshiba_bt_rfkill_driver);
+}
+
+module_init(toshiba_bt_rfkill_init);
+module_exit(toshiba_bt_rfkill_exit);
Index: linux-2.6.31.5/drivers/platform/x86/Makefile
===================================================================
--- linux-2.6.31.5.orig/drivers/platform/x86/Makefile
+++ linux-2.6.31.5/drivers/platform/x86/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_INTEL_MENLOW)	+= intel_menl
 obj-$(CONFIG_ACPI_WMI)		+= wmi.o
 obj-$(CONFIG_ACPI_ASUS)		+= asus_acpi.o
 obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
+obj-$(CONFIG_TOSHIBA_BT_RFKILL)	+= toshiba_bluetooth.o
Index: linux-2.6.31.5/drivers/platform/x86/Kconfig
===================================================================
--- linux-2.6.31.5.orig/drivers/platform/x86/Kconfig
+++ linux-2.6.31.5/drivers/platform/x86/Kconfig
@@ -425,4 +425,20 @@ config ACPI_TOSHIBA
 
 	  If you have a legacy free Toshiba laptop (such as the Libretto L1
 	  series), say Y.
+
+config TOSHIBA_BT_RFKILL
+	tristate "Toshiba Bluetooth RFKill switch support"
+	depends on ACPI
+	depends on RFKILL
+	---help---
+	  This driver adds support for Bluetooth events for the RFKill
+	  switch on modern Toshiba laptops with full ACPI support and
+	  an RFKill switch.
+
+	  This driver handles RFKill events for the TOS6205 Bluetooth,
+	  and re-enables it when the switch is set back to the 'on'
+	  position.
+
+	  If you have a modern Toshiba laptop with a Bluetooth and an
+	  RFKill switch (such as the Portege R500), say Y.
 endif # X86_PLATFORM_DEVICES

  parent reply	other threads:[~2009-12-08 16:58 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-04 15:38 [PATCH] Toshiba Bluetooth enabler (rfkill) Jes Sorensen
2009-12-08 10:05 ` Alan Jenkins
2009-12-08 12:55   ` Matthew Garrett
2009-12-08 15:45     ` Jes Sorensen
2009-12-08 15:47       ` Matthew Garrett
2009-12-08 15:50         ` Jes Sorensen
2009-12-08 15:51           ` Matthew Garrett
2009-12-08 21:30             ` Alan Jenkins
2009-12-08 16:58   ` Jes Sorensen [this message]
2009-12-09 13:17     ` Toshiba Bluetooth enabler (v2) (was: Re: [PATCH] Toshiba Bluetooth enabler (rfkill)) Alan Jenkins
2009-12-10 13:27       ` Dan Carpenter
2009-12-10 13:47         ` Alan Jenkins
2009-12-10 15:27       ` PATCH: Toshiba Bluetooth enabler (v3) Jes Sorensen
2009-12-10 17:00         ` Alan Jenkins
2009-12-11 10:51           ` Jes Sorensen
2009-12-11 13:08             ` Alan Jenkins
2009-12-16 17:06         ` Len Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B1E85A9.3030005@gmail.com \
    --to=jes.sorensen@gmail.com \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mjg59@srcf.ucam.org \
    --cc=sourcejedi.lkml@googlemail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox