--- 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 @@ -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},