Add bluetooth support to toshiba-acpi driver
PATCH 1/1 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).
-----
acpi/toshiba_acpi.c renamed from acpi/toshiba_acpi.c.orig +127 -1
@@ -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 chreturn 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.
Signature · 5 lines
One-seventh of your life is spent on Monday. - To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 6 lines · Jonathan McDowell
This patch adds bluetooth support to the toshiba-acpi driver. I have tried to follow the same format for the
/proc/acpi/toshiba/bluetoothfile 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.
Would it be possible (make sense) to add config option for that? There are probably a bunch of older models out there that do not have BT at all (I am owner of such one).
Thank you
-andrey
Quoted 180 lines
Traditionally the userland "toshset" program would have been used to enable bluetooth, but this requires either
CONFIG_TOSHIBAor a patched toshiba-acpi to emulate the/dev/toshibadevice. 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 <[email protected]>-----
acpi/toshiba_acpi.c 2007-10-21 18:15:34.000000000 +0100 renamed from acpi/toshiba_acpi.c.orig 2007-10-21 18:29:01.000000000 +0100 +126
-2@@ -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.
Quoted 10 lines · Andrey Borzenkov
Quoted 6 lines · Jonathan McDowell
This patch adds bluetooth support to the toshiba-acpi driver. I have tried to follow the same format for the
/proc/acpi/toshiba/bluetoothfile 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.Would it be possible (make sense) to add config option for that? There are probably a bunch of older models out there that do not have BT at all (I am owner of such one).
For models without bluetooth the /proc/acpi/toshiba/bluetooth file should end up with "status: not supported" in it. I don't have such a laptop to test that this happens though; perhaps you could test the patch and confirm it works as expected?
J.
Signature · 1 line
The truth is out there, but also in here.
Quoted 11 lines
This patch adds bluetooth support to the toshiba-acpi driver. I have tried to follow the same format for the
/proc/acpi/toshiba/bluetoothfile 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_TOSHIBAor a patched toshiba-acpi to emulate the/dev/toshibadevice. Also toshset doesn't currently run in 64bit mode.
Quoted 4 lines
Patch has been successfully tested on a Portégé R200 (in 32bit mode) and an R500 (in 64bit mode).
Signed-off-by Jonathan McDowell <[email protected]>
The /proc/acpi/toshiba interface should not be expanded-- do not apply this patch. If any patch is applied, it would be to optionally implement the generic /dev/toshiba interface so that user space tools like toshset can operate.
--John Belmonte
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 14 lines · John Belmonte
Quoted 14 lines
This patch adds bluetooth support to the toshiba-acpi driver. I have tried to follow the same format for the
/proc/acpi/toshiba/bluetoothfile 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_TOSHIBAor a patched toshiba-acpi to emulate the/dev/toshibadevice. 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).
Quoted 6 lines
Quoted 1 line
Signed-off-by Jonathan McDowell <[email protected]>The
/proc/acpi/toshibainterface should not be expanded-- do not apply this patch. If any patch is applied, it would be to optionally implement the generic/dev/toshibainterface so that user space tools like toshset can operate.
There's been a patch to add the /dev/toshiba functionality floating around for at least a year or two. Is there a reason it hasn't already been applied?
I'm not entirely convinced that userland is the right way to do this though. In the long run rfkill appears to be the correct generic infrastructure, but at present it's not able to cope with devices that don't exist when switched off and I can't find any other users in mainline anyway. Assuming that changes, would you accept a patch adding support for it to toshiba-acpi?
J.
Signature · 3 lines
jid: [email protected] I had a life once... but now I have a modem.
Quoted 4 lines · John Belmonte
The
/proc/acpi/toshibainterface should not be expanded-- do not apply this patch. If any patch is applied, it would be to optionally implement the generic/dev/toshibainterface so that user space tools like toshset can operate.
The correct interface is rfkill, which will require this functionality to be in-kernel anyway. I can see the argument against implementing it in /proc/acpi/toshiba (further proc interface bloat), but not against doing it in-kernel.
Signature · 1 line
Matthew Garrett | [email protected]