Jonathan McDowell wrote: > 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. > 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 > 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@xxxxxxxx> > > ----- > --- 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. > - To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html