Loading drivers/acpi/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ config ACPI_BATTERY config ACPI_BUTTON tristate "Button" depends on INPUT default y help This driver handles events on the power, sleep and lid buttons. Loading drivers/acpi/button.c +138 −85 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <linux/types.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/input.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> Loading Loading @@ -83,7 +84,9 @@ static struct acpi_driver acpi_button_driver = { struct acpi_button { struct acpi_device *device; /* Fixed button kludge */ u8 type; unsigned int type; struct input_dev *input; char phys[32]; /* for input device */ unsigned long pushed; }; Loading @@ -109,8 +112,7 @@ static struct proc_dir_entry *acpi_button_dir; static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) { struct acpi_button *button = (struct acpi_button *)seq->private; struct acpi_button *button = seq->private; if (!button || !button->device) return 0; Loading @@ -128,22 +130,17 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file) static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) { struct acpi_button *button = (struct acpi_button *)seq->private; struct acpi_button *button = seq->private; acpi_status status; unsigned long state; if (!button || !button->device) return 0; status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, &state); if (ACPI_FAILURE(status)) { seq_printf(seq, "state: unsupported\n"); } else { seq_printf(seq, "state: %s\n", ACPI_FAILURE(status) ? "unsupported" : (state ? "open" : "closed")); } return 0; } Loading @@ -159,8 +156,7 @@ static struct proc_dir_entry *acpi_lid_dir; static int acpi_button_add_fs(struct acpi_device *device) { struct proc_dir_entry *entry = NULL; struct acpi_button *button = NULL; struct acpi_button *button; if (!device || !acpi_driver_data(device)) return -EINVAL; Loading Loading @@ -228,10 +224,8 @@ static int acpi_button_add_fs(struct acpi_device *device) static int acpi_button_remove_fs(struct acpi_device *device) { struct acpi_button *button = NULL; struct acpi_button *button = acpi_driver_data(device); button = acpi_driver_data(device); if (acpi_device_dir(device)) { if (button->type == ACPI_BUTTON_TYPE_LID) remove_proc_entry(ACPI_BUTTON_FILE_STATE, Loading @@ -253,14 +247,34 @@ static int acpi_button_remove_fs(struct acpi_device *device) static void acpi_button_notify(acpi_handle handle, u32 event, void *data) { struct acpi_button *button = (struct acpi_button *)data; struct acpi_button *button = data; struct input_dev *input; if (!button || !button->device) return; switch (event) { case ACPI_BUTTON_NOTIFY_STATUS: input = button->input; if (button->type == ACPI_BUTTON_TYPE_LID) { struct acpi_handle *handle = button->device->handle; unsigned long state; if (!ACPI_FAILURE(acpi_evaluate_integer(handle, "_LID", NULL, &state))) input_report_switch(input, SW_LID, !state); } else { int keycode = test_bit(KEY_SLEEP, input->keybit) ? KEY_SLEEP : KEY_POWER; input_report_key(input, keycode, 1); input_sync(input); input_report_key(input, keycode, 0); } input_sync(input); acpi_bus_generate_event(button->device, event, ++button->pushed); break; Loading @@ -275,8 +289,7 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data) static acpi_status acpi_button_notify_fixed(void *data) { struct acpi_button *button = (struct acpi_button *)data; struct acpi_button *button = data; if (!button) return AE_BAD_PARAMETER; Loading @@ -286,24 +299,75 @@ static acpi_status acpi_button_notify_fixed(void *data) return AE_OK; } static int acpi_button_add(struct acpi_device *device) static int acpi_button_install_notify_handlers(struct acpi_button *button) { acpi_status status; switch (button->type) { case ACPI_BUTTON_TYPE_POWERF: status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed, button); break; case ACPI_BUTTON_TYPE_SLEEPF: status = acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed, button); break; default: status = acpi_install_notify_handler(button->device->handle, ACPI_DEVICE_NOTIFY, acpi_button_notify, button); break; } return ACPI_FAILURE(status) ? -ENODEV : 0; } static void acpi_button_remove_notify_handlers(struct acpi_button *button) { int result = 0; acpi_status status = AE_OK; struct acpi_button *button = NULL; switch (button->type) { case ACPI_BUTTON_TYPE_POWERF: acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed); break; case ACPI_BUTTON_TYPE_SLEEPF: acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed); break; default: acpi_remove_notify_handler(button->device->handle, ACPI_DEVICE_NOTIFY, acpi_button_notify); break; } } static int acpi_button_add(struct acpi_device *device) { int error; struct acpi_button *button; struct input_dev *input; if (!device) return -EINVAL; button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL); button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL); if (!button) return -ENOMEM; memset(button, 0, sizeof(struct acpi_button)); button->device = device; acpi_driver_data(device) = button; button->input = input = input_allocate_device(); if (!input) { error = -ENOMEM; goto err_free_button; } /* * Determine the button type (via hid), as fixed-feature buttons * need to be handled a bit differently than generic-space. Loading Loading @@ -338,39 +402,48 @@ static int acpi_button_add(struct acpi_device *device) } else { printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", acpi_device_hid(device)); result = -ENODEV; goto end; error = -ENODEV; goto err_free_input; } result = acpi_button_add_fs(device); if (result) goto end; error = acpi_button_add_fs(device); if (error) goto err_free_input; error = acpi_button_install_notify_handlers(button); if (error) goto err_remove_fs; snprintf(button->phys, sizeof(button->phys), "%s/button/input0", acpi_device_hid(device)); input->name = acpi_device_name(device); input->phys = button->phys; input->id.bustype = BUS_HOST; input->id.product = button->type; switch (button->type) { case ACPI_BUTTON_TYPE_POWER: case ACPI_BUTTON_TYPE_POWERF: status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed, button); input->evbit[0] = BIT(EV_KEY); set_bit(KEY_POWER, input->keybit); break; case ACPI_BUTTON_TYPE_SLEEP: case ACPI_BUTTON_TYPE_SLEEPF: status = acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed, button); input->evbit[0] = BIT(EV_KEY); set_bit(KEY_SLEEP, input->keybit); break; default: status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, acpi_button_notify, button); case ACPI_BUTTON_TYPE_LID: input->evbit[0] = BIT(EV_SW); set_bit(SW_LID, input->swbit); break; } if (ACPI_FAILURE(status)) { result = -ENODEV; goto end; } error = input_register_device(input); if (error) goto err_remove_handlers; if (device->wakeup.flags.valid) { /* Button's GPE is run-wake GPE */ Loading @@ -385,47 +458,31 @@ static int acpi_button_add(struct acpi_device *device) printk(KERN_INFO PREFIX "%s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); end: if (result) { return 0; err_remove_handlers: acpi_button_remove_notify_handlers(button); err_remove_fs: acpi_button_remove_fs(device); err_free_input: input_free_device(input); err_free_button: kfree(button); } return result; return error; } static int acpi_button_remove(struct acpi_device *device, int type) { acpi_status status = 0; struct acpi_button *button = NULL; struct acpi_button *button; if (!device || !acpi_driver_data(device)) return -EINVAL; button = acpi_driver_data(device); /* Unregister for device notifications. */ switch (button->type) { case ACPI_BUTTON_TYPE_POWERF: status = acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed); break; case ACPI_BUTTON_TYPE_SLEEPF: status = acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed); break; default: status = acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, acpi_button_notify); break; } acpi_button_remove_notify_handlers(button); acpi_button_remove_fs(device); input_unregister_device(button->input); kfree(button); return 0; Loading @@ -433,8 +490,7 @@ static int acpi_button_remove(struct acpi_device *device, int type) static int __init acpi_button_init(void) { int result = 0; int result; acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); if (!acpi_button_dir) Loading @@ -451,7 +507,6 @@ static int __init acpi_button_init(void) static void __exit acpi_button_exit(void) { acpi_bus_unregister_driver(&acpi_button_driver); if (acpi_power_dir) Loading @@ -461,8 +516,6 @@ static void __exit acpi_button_exit(void) if (acpi_lid_dir) remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); return; } module_init(acpi_button_init); Loading Loading
drivers/acpi/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ config ACPI_BATTERY config ACPI_BUTTON tristate "Button" depends on INPUT default y help This driver handles events on the power, sleep and lid buttons. Loading
drivers/acpi/button.c +138 −85 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <linux/types.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/input.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> Loading Loading @@ -83,7 +84,9 @@ static struct acpi_driver acpi_button_driver = { struct acpi_button { struct acpi_device *device; /* Fixed button kludge */ u8 type; unsigned int type; struct input_dev *input; char phys[32]; /* for input device */ unsigned long pushed; }; Loading @@ -109,8 +112,7 @@ static struct proc_dir_entry *acpi_button_dir; static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) { struct acpi_button *button = (struct acpi_button *)seq->private; struct acpi_button *button = seq->private; if (!button || !button->device) return 0; Loading @@ -128,22 +130,17 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file) static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) { struct acpi_button *button = (struct acpi_button *)seq->private; struct acpi_button *button = seq->private; acpi_status status; unsigned long state; if (!button || !button->device) return 0; status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, &state); if (ACPI_FAILURE(status)) { seq_printf(seq, "state: unsupported\n"); } else { seq_printf(seq, "state: %s\n", ACPI_FAILURE(status) ? "unsupported" : (state ? "open" : "closed")); } return 0; } Loading @@ -159,8 +156,7 @@ static struct proc_dir_entry *acpi_lid_dir; static int acpi_button_add_fs(struct acpi_device *device) { struct proc_dir_entry *entry = NULL; struct acpi_button *button = NULL; struct acpi_button *button; if (!device || !acpi_driver_data(device)) return -EINVAL; Loading Loading @@ -228,10 +224,8 @@ static int acpi_button_add_fs(struct acpi_device *device) static int acpi_button_remove_fs(struct acpi_device *device) { struct acpi_button *button = NULL; struct acpi_button *button = acpi_driver_data(device); button = acpi_driver_data(device); if (acpi_device_dir(device)) { if (button->type == ACPI_BUTTON_TYPE_LID) remove_proc_entry(ACPI_BUTTON_FILE_STATE, Loading @@ -253,14 +247,34 @@ static int acpi_button_remove_fs(struct acpi_device *device) static void acpi_button_notify(acpi_handle handle, u32 event, void *data) { struct acpi_button *button = (struct acpi_button *)data; struct acpi_button *button = data; struct input_dev *input; if (!button || !button->device) return; switch (event) { case ACPI_BUTTON_NOTIFY_STATUS: input = button->input; if (button->type == ACPI_BUTTON_TYPE_LID) { struct acpi_handle *handle = button->device->handle; unsigned long state; if (!ACPI_FAILURE(acpi_evaluate_integer(handle, "_LID", NULL, &state))) input_report_switch(input, SW_LID, !state); } else { int keycode = test_bit(KEY_SLEEP, input->keybit) ? KEY_SLEEP : KEY_POWER; input_report_key(input, keycode, 1); input_sync(input); input_report_key(input, keycode, 0); } input_sync(input); acpi_bus_generate_event(button->device, event, ++button->pushed); break; Loading @@ -275,8 +289,7 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data) static acpi_status acpi_button_notify_fixed(void *data) { struct acpi_button *button = (struct acpi_button *)data; struct acpi_button *button = data; if (!button) return AE_BAD_PARAMETER; Loading @@ -286,24 +299,75 @@ static acpi_status acpi_button_notify_fixed(void *data) return AE_OK; } static int acpi_button_add(struct acpi_device *device) static int acpi_button_install_notify_handlers(struct acpi_button *button) { acpi_status status; switch (button->type) { case ACPI_BUTTON_TYPE_POWERF: status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed, button); break; case ACPI_BUTTON_TYPE_SLEEPF: status = acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed, button); break; default: status = acpi_install_notify_handler(button->device->handle, ACPI_DEVICE_NOTIFY, acpi_button_notify, button); break; } return ACPI_FAILURE(status) ? -ENODEV : 0; } static void acpi_button_remove_notify_handlers(struct acpi_button *button) { int result = 0; acpi_status status = AE_OK; struct acpi_button *button = NULL; switch (button->type) { case ACPI_BUTTON_TYPE_POWERF: acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed); break; case ACPI_BUTTON_TYPE_SLEEPF: acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed); break; default: acpi_remove_notify_handler(button->device->handle, ACPI_DEVICE_NOTIFY, acpi_button_notify); break; } } static int acpi_button_add(struct acpi_device *device) { int error; struct acpi_button *button; struct input_dev *input; if (!device) return -EINVAL; button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL); button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL); if (!button) return -ENOMEM; memset(button, 0, sizeof(struct acpi_button)); button->device = device; acpi_driver_data(device) = button; button->input = input = input_allocate_device(); if (!input) { error = -ENOMEM; goto err_free_button; } /* * Determine the button type (via hid), as fixed-feature buttons * need to be handled a bit differently than generic-space. Loading Loading @@ -338,39 +402,48 @@ static int acpi_button_add(struct acpi_device *device) } else { printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", acpi_device_hid(device)); result = -ENODEV; goto end; error = -ENODEV; goto err_free_input; } result = acpi_button_add_fs(device); if (result) goto end; error = acpi_button_add_fs(device); if (error) goto err_free_input; error = acpi_button_install_notify_handlers(button); if (error) goto err_remove_fs; snprintf(button->phys, sizeof(button->phys), "%s/button/input0", acpi_device_hid(device)); input->name = acpi_device_name(device); input->phys = button->phys; input->id.bustype = BUS_HOST; input->id.product = button->type; switch (button->type) { case ACPI_BUTTON_TYPE_POWER: case ACPI_BUTTON_TYPE_POWERF: status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed, button); input->evbit[0] = BIT(EV_KEY); set_bit(KEY_POWER, input->keybit); break; case ACPI_BUTTON_TYPE_SLEEP: case ACPI_BUTTON_TYPE_SLEEPF: status = acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed, button); input->evbit[0] = BIT(EV_KEY); set_bit(KEY_SLEEP, input->keybit); break; default: status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, acpi_button_notify, button); case ACPI_BUTTON_TYPE_LID: input->evbit[0] = BIT(EV_SW); set_bit(SW_LID, input->swbit); break; } if (ACPI_FAILURE(status)) { result = -ENODEV; goto end; } error = input_register_device(input); if (error) goto err_remove_handlers; if (device->wakeup.flags.valid) { /* Button's GPE is run-wake GPE */ Loading @@ -385,47 +458,31 @@ static int acpi_button_add(struct acpi_device *device) printk(KERN_INFO PREFIX "%s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); end: if (result) { return 0; err_remove_handlers: acpi_button_remove_notify_handlers(button); err_remove_fs: acpi_button_remove_fs(device); err_free_input: input_free_device(input); err_free_button: kfree(button); } return result; return error; } static int acpi_button_remove(struct acpi_device *device, int type) { acpi_status status = 0; struct acpi_button *button = NULL; struct acpi_button *button; if (!device || !acpi_driver_data(device)) return -EINVAL; button = acpi_driver_data(device); /* Unregister for device notifications. */ switch (button->type) { case ACPI_BUTTON_TYPE_POWERF: status = acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed); break; case ACPI_BUTTON_TYPE_SLEEPF: status = acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed); break; default: status = acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, acpi_button_notify); break; } acpi_button_remove_notify_handlers(button); acpi_button_remove_fs(device); input_unregister_device(button->input); kfree(button); return 0; Loading @@ -433,8 +490,7 @@ static int acpi_button_remove(struct acpi_device *device, int type) static int __init acpi_button_init(void) { int result = 0; int result; acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); if (!acpi_button_dir) Loading @@ -451,7 +507,6 @@ static int __init acpi_button_init(void) static void __exit acpi_button_exit(void) { acpi_bus_unregister_driver(&acpi_button_driver); if (acpi_power_dir) Loading @@ -461,8 +516,6 @@ static void __exit acpi_button_exit(void) if (acpi_lid_dir) remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); return; } module_init(acpi_button_init); Loading