Re: Status of 'toshiba-acpi: Add support for hotkey notifications'patch?

From: cascardo
Date: Thu Jan 28 2010 - 13:15:12 EST


On Tue, Jan 26, 2010 at 05:59:00PM +0100, Frans Pop wrote:
> Hi Matthew,
>
> What's the status of the patch below [1]? IIRC you were waiting for feedback
> from a particular user?
>
> The patch works fine for me on my Satellite A40 and I'd like to see
> it included.
>
> Cheers,
> FJP
>

I'd recommend using the new sparse keymap feature instead of introducing
struct key_entry and scancode/keycode functions already in place in this
new feature.

Regards,
Cascardo.

> [1] Patch has been rebased for current mainline.
>
> Author: Matthew Garrett <mjg59@xxxxxxxxxxxxx>
> ~Subject: toshiba-acpi: Add support for hotkey notifications
>
> Calling the ENAB method on Toshiba laptops results in notifications being
> sent when laptop hotkeys are pressed. This patch simply calls that method
> and sets up an input device if it's successful.
>
> Signed-off-by: Matthew Garrett <mjg@xxxxxxxxxx>
>
> diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
> index 77bf5d8..13344b1 100644
> --- a/drivers/platform/x86/toshiba_acpi.c
> +++ b/drivers/platform/x86/toshiba_acpi.c
> @@ -46,6 +46,8 @@
> #include <linux/backlight.h>
> #include <linux/platform_device.h>
> #include <linux/rfkill.h>
> +#include <linux/input-polldev.h>
> +#include <linux/input.h>
>
> #include <asm/uaccess.h>
>
> @@ -62,9 +64,10 @@ MODULE_LICENSE("GPL");
>
> /* Toshiba ACPI method paths */
> #define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
> -#define METHOD_HCI_1 "\\_SB_.VALD.GHCI"
> -#define METHOD_HCI_2 "\\_SB_.VALZ.GHCI"
> +#define TOSH_INTERFACE_1 "\\_SB_.VALD"
> +#define TOSH_INTERFACE_2 "\\_SB_.VALZ"
> #define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
> +#define GHCI_METHOD ".GHCI"
>
> /* Toshiba HCI interface definitions
> *
> @@ -116,6 +119,37 @@ static const struct acpi_device_id toshiba_device_ids[] = {
> };
> MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
>
> +struct key_entry {
> + char type;
> + u16 code;
> + u16 keycode;
> +};
> +
> +enum {KE_KEY, KE_END};
> +
> +static struct key_entry toshiba_acpi_keymap[] = {
> + {KE_KEY, 0x101, KEY_MUTE},
> + {KE_KEY, 0x13b, KEY_COFFEE},
> + {KE_KEY, 0x13c, KEY_BATTERY},
> + {KE_KEY, 0x13d, KEY_SLEEP},
> + {KE_KEY, 0x13e, KEY_SUSPEND},
> + {KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE},
> + {KE_KEY, 0x140, KEY_BRIGHTNESSDOWN},
> + {KE_KEY, 0x141, KEY_BRIGHTNESSUP},
> + {KE_KEY, 0x142, KEY_WLAN},
> + {KE_KEY, 0x143, KEY_PROG1},
> + {KE_KEY, 0x17f, KEY_BRIGHTNESSDOWN},
> + {KE_KEY, 0xb05, KEY_PROG2},
> + {KE_KEY, 0xb06, KEY_WWW},
> + {KE_KEY, 0xb07, KEY_MAIL},
> + {KE_KEY, 0xb30, KEY_STOP},
> + {KE_KEY, 0xb31, KEY_PREVIOUSSONG},
> + {KE_KEY, 0xb32, KEY_NEXTSONG},
> + {KE_KEY, 0xb33, KEY_PLAYPAUSE},
> + {KE_KEY, 0xb5a, KEY_MEDIA},
> + {KE_END, 0, 0},
> +};
> +
> /* utility
> */
>
> @@ -251,6 +285,9 @@ static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32
> *result)
> struct toshiba_acpi_dev {
> struct platform_device *p_dev;
> struct rfkill *bt_rfk;
> + struct input_polled_dev *poll_dev;
> + struct input_dev *hotkey_dev;
> + acpi_handle handle;
>
> const char *bt_name;
>
> @@ -711,6 +748,154 @@ static struct backlight_ops toshiba_backlight_data = {
> .update_status = set_lcd_status,
> };
>
> +static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code)
> +{
> + struct key_entry *key;
> +
> + for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
> + if (code == key->code)
> + return key;
> +
> + return NULL;
> +}
> +
> +static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code)
> +{
> + struct key_entry *key;
> +
> + for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
> + if (code == key->keycode && key->type == KE_KEY)
> + return key;
> +
> + return NULL;
> +}
> +
> +static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode,
> + int *keycode)
> +{
> + struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode);
> +
> + if (key && key->type == KE_KEY) {
> + *keycode = key->keycode;
> + return 0;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static int toshiba_acpi_setkeycode(struct input_dev *dev, int scancode,
> + int keycode)
> +{
> + struct key_entry *key;
> + int old_keycode;
> +
> + if (keycode < 0 || keycode > KEY_MAX)
> + return -EINVAL;
> +
> + key = toshiba_acpi_get_entry_by_scancode(scancode);
> + if (key && key->type == KE_KEY) {
> + old_keycode = key->keycode;
> + key->keycode = keycode;
> + set_bit(keycode, dev->keybit);
> + if (!toshiba_acpi_get_entry_by_keycode(old_keycode))
> + clear_bit(old_keycode, dev->keybit);
> + return 0;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static void toshiba_acpi_notify(acpi_handle handle, u32 event, void **data)
> +{
> + u32 hci_result, value;
> + struct key_entry *key;
> +
> + if (event != 0x80)
> + return;
> + do {
> + hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
> + if (hci_result == HCI_SUCCESS) {
> + if (value == 0x100)
> + continue;
> + else if (!(value & 0x80)) {
> + key = toshiba_acpi_get_entry_by_scancode
> + (value);
> + if (!key) {
> + printk(MY_INFO "Unknown key %x\n",
> + value);
> + continue;
> + }
> + input_report_key(toshiba_acpi.hotkey_dev,
> + key->keycode, 1);
> + input_sync(toshiba_acpi.hotkey_dev);
> + input_report_key(toshiba_acpi.hotkey_dev,
> + key->keycode, 0);
> + input_sync(toshiba_acpi.hotkey_dev);
> + }
> + } else if (hci_result == HCI_NOT_SUPPORTED) {
> + /* This is a workaround for an unresolved issue on
> + * some machines where system events sporadically
> + * become disabled. */
> + hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
> + printk(MY_NOTICE "Re-enabled hotkeys\n");
> + }
> + } while (hci_result != HCI_EMPTY);
> +}
> +
> +static int toshiba_acpi_setup_keyboard(char *device)
> +{
> + acpi_status status;
> + acpi_handle handle;
> + int result;
> + const struct key_entry *key;
> +
> + status = acpi_get_handle(NULL, device, &handle);
> + if (ACPI_FAILURE(status)) {
> + printk(MY_INFO "Unable to get notification device\n");
> + return -ENODEV;
> + }
> +
> + toshiba_acpi.handle = handle;
> +
> + status = acpi_evaluate_object(handle, "ENAB", NULL, NULL);
> + if (ACPI_FAILURE(status)) {
> + printk(MY_INFO "Unable to enable hotkeys\n");
> + return -ENODEV;
> + }
> +
> + status = acpi_install_notify_handler (handle, ACPI_DEVICE_NOTIFY,
> + toshiba_acpi_notify, NULL);
> + if (ACPI_FAILURE(status)) {
> + printk(MY_INFO "Unable to install hotkey notification\n");
> + return -ENODEV;
> + }
> +
> + toshiba_acpi.hotkey_dev = input_allocate_device();
> + if (!toshiba_acpi.hotkey_dev) {
> + printk(MY_INFO "Unable to register input device\n");
> + return -ENOMEM;
> + }
> +
> + toshiba_acpi.hotkey_dev->name = "Toshiba input device";
> + toshiba_acpi.hotkey_dev->phys = device;
> + toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
> + toshiba_acpi.hotkey_dev->getkeycode = toshiba_acpi_getkeycode;
> + toshiba_acpi.hotkey_dev->setkeycode = toshiba_acpi_setkeycode;
> +
> + for (key = toshiba_acpi_keymap; key->type != KE_END; key++) {
> + set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit);
> + set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit);
> + }
> +
> + result = input_register_device(toshiba_acpi.hotkey_dev);
> + if (result) {
> + printk(MY_INFO "Unable to register input device\n");
> + return result;
> + }
> +
> + return 0;
> +}
> +
> static void toshiba_acpi_exit(void)
> {
> if (toshiba_acpi.bt_rfk) {
> @@ -718,9 +903,15 @@ static void toshiba_acpi_exit(void)
> rfkill_destroy(toshiba_acpi.bt_rfk);
> }
>
> + if (toshiba_acpi.hotkey_dev)
> + input_unregister_device(toshiba_acpi.hotkey_dev);
> +
> if (toshiba_backlight_device)
> backlight_device_unregister(toshiba_backlight_device);
>
> + acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
> + toshiba_acpi_notify);
> +
> remove_device();
>
> if (toshiba_proc_dir)
> @@ -742,11 +933,15 @@ static int __init toshiba_acpi_init(void)
> return -ENODEV;
>
> /* simple device detection: look for HCI method */
> - if (is_valid_acpi_path(METHOD_HCI_1))
> - method_hci = METHOD_HCI_1;
> - else if (is_valid_acpi_path(METHOD_HCI_2))
> - method_hci = METHOD_HCI_2;
> - else
> + if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) {
> + method_hci = TOSH_INTERFACE_1 GHCI_METHOD;
> + if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1))
> + printk(MY_INFO "Unable to activate hotkeys\n");
> + } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) {
> + method_hci = TOSH_INTERFACE_2 GHCI_METHOD;
> + if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2))
> + printk(MY_INFO "Unable to activate hotkeys\n");
> + } else
> return -ENODEV;
>
> printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n",
> --
> 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
>

Attachment: signature.asc
Description: Digital signature