lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20071021173529.GH1880@earth.li>
Date:	Sun, 21 Oct 2007 18:35:29 +0100
From:	Jonathan McDowell <noodles@...th.li>
To:	John Belmonte <toshiba_acpi@...ebeam.org>
Cc:	linux-acpi@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH] Add bluetooth support to toshiba-acpi driver

This patch adds bluetooth support to the toshiba-acpi driver. I have
tried to follow the same format for the /proc/acpi/toshiba/bluetooth
file as followed in the thinkpad-acpi driver. In the long term the
rfkill infrastructure looks like the way forward for this functionality,
but at present it doesn't seem to be suitable.

Traditionally the userland "toshset" program would have been used to
enable bluetooth, but this requires either CONFIG_TOSHIBA or a patched
toshiba-acpi to emulate the /dev/toshiba device. Also toshset doesn't
currently run in 64bit mode.

Patch has been successfully tested on a Portégé R200 (in 32bit mode) and
an R500 (in 64bit mode).

Signed-Off-By: Jonathan McDowell <noodles@...th.li>

-----
--- drivers/acpi/toshiba_acpi.c.orig	2007-10-21 18:29:01.000000000 +0100
+++ drivers/acpi/toshiba_acpi.c	2007-10-21 18:15:34.000000000 +0100
@@ -33,7 +33,7 @@
  *
  */
 
-#define TOSHIBA_ACPI_VERSION	"0.18"
+#define TOSHIBA_ACPI_VERSION	"0.19"
 #define PROC_INTERFACE_VERSION	1
 
 #include <linux/kernel.h>
@@ -55,6 +55,7 @@ MODULE_LICENSE("GPL");
 #define MY_ERR KERN_ERR MY_LOGPREFIX
 #define MY_NOTICE KERN_NOTICE MY_LOGPREFIX
 #define MY_INFO KERN_INFO MY_LOGPREFIX
+#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
 
 /* Toshiba ACPI method paths */
 #define METHOD_LCD_BRIGHTNESS	"\\_SB_.PCI0.VGA_.LCD_._BCM"
@@ -90,6 +91,7 @@ MODULE_LICENSE("GPL");
 #define HCI_VIDEO_OUT			0x001c
 #define HCI_HOTKEY_EVENT		0x001e
 #define HCI_LCD_BRIGHTNESS		0x002a
+#define HCI_BLUETOOTH			0x0056
 
 /* field definitions */
 #define HCI_LCD_BRIGHTNESS_BITS		3
@@ -482,6 +484,129 @@ static unsigned long write_keys(const ch
 	return count;
 }
 
+static int toshiba_bluetooth_present(void)
+{
+	u32 hci_result;
+	u32 value;
+
+	hci_read1(HCI_BLUETOOTH, &value, &hci_result);
+	if (hci_result == HCI_SUCCESS) {
+		return (value & 0x0f) == 0x0f;
+	} else
+		return -EFAULT;
+}
+
+static int toshiba_bluetooth_get(void)
+{
+	u32 in[HCI_WORDS];
+	u32 out[HCI_WORDS];
+	acpi_status status;
+
+	in[0] = HCI_GET;
+	in[1] = HCI_BLUETOOTH;
+	in[2] = 0;
+	in[3] = 1;
+	status = hci_raw(in, out);
+	if (status != AE_OK) {
+		printk(MY_ERR "Error checking Bluetooth device status.\n");
+		return -EIO;
+	}
+
+	/* 0x1 == switch on, 0x40 == attached, 0x80 == power on */
+	return (out[2] & 0xC1) == 0xC1;
+}
+
+static int toshiba_bluetooth_set(int state)
+{
+	u32 in[HCI_WORDS];
+	u32 out[HCI_WORDS];
+	acpi_status status;
+	
+	switch (state) {
+	case 0:
+		in[0] = HCI_SET;
+		in[1] = HCI_BLUETOOTH;
+		in[2] = 0;
+		in[3] = 0x40;
+		status = hci_raw(in, out);
+		if (status != AE_OK) {
+			printk(MY_ERR "Error detaching Bluetooth device.\n");
+			return -EIO;
+		}
+
+		in[0] = HCI_SET;
+		in[1] = HCI_BLUETOOTH;
+		in[2] = 0;
+		in[3] = 0x80;
+		status = hci_raw(in, out);
+		if (status != AE_OK) {
+			printk(MY_ERR "Error deactivating Bluetooth device.\n");
+			return -EIO;
+		}
+		break;
+	case 1:
+		in[0] = HCI_SET;
+		in[1] = HCI_BLUETOOTH;
+		in[2] = 1;
+		in[3] = 0x80;
+		status = hci_raw(in, out);
+		if (status != AE_OK) {
+			printk(MY_ERR "Error activating Bluetooth device.\n");
+			return -EIO;
+		}
+	
+		in[0] = HCI_SET;
+		in[1] = HCI_BLUETOOTH;
+		in[2] = 1;
+		in[3] = 0x40;
+		status = hci_raw(in, out);
+		if (status != AE_OK) {
+			printk(MY_ERR "Error attaching Bluetooth device.\n");
+			return -EIO;
+		}
+		break;
+	default:
+		printk(MY_ERR "Unknown state for Bluetooth.\n");
+	};
+
+	return 0;
+}
+
+static char *read_bluetooth(char *p)
+{
+	int value = toshiba_bluetooth_get();
+
+	if (!toshiba_bluetooth_present()) {
+		p += sprintf(p, "status:\t\tnot supported\n");
+	} else if (value >= 0) {
+		p += sprintf(p, "status:\t\t%s\n", 
+				value ? "enabled" : "disabled");
+		p += sprintf(p, "commands:\tenable, disable\n");
+	} else {
+		printk(MY_ERR "Error reading bluetooth status.\n");
+	}
+
+	return p;
+}
+
+static unsigned long write_bluetooth(const char *buffer, unsigned long count)
+{
+	int ret ;
+
+	if (!toshiba_bluetooth_present()) {
+		ret = -ENODEV;
+	} else if (strlencmp(buffer, "enable") == 0) {
+		toshiba_bluetooth_set(1);
+		ret = count;
+	} else if (strlencmp(buffer, "disable") == 0) {
+		toshiba_bluetooth_set(0);
+		ret = count;
+	} else {
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
 static char *read_version(char *p)
 {
 	p += sprintf(p, "driver:                  %s\n", TOSHIBA_ACPI_VERSION);
@@ -496,6 +621,7 @@ static char *read_version(char *p)
 #define PROC_TOSHIBA		"toshiba"
 
 static ProcItem proc_items[] = {
+	{"bluetooth", read_bluetooth, write_bluetooth},
 	{"lcd", read_lcd, write_lcd},
 	{"video", read_video, write_video},
 	{"fan", read_fan, write_fan},
-----

J.

-- 
One-seventh of your life is spent on Monday.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ