LKML Archive on lore.kernel.org help / color / mirror / Atom feed
* Re: HP WMI laptop extras driver @ 2008-11-22 21:43 Daniel Perzynski 2008-11-28 17:19 ` Matthew Garrett 0 siblings, 1 reply; 5+ messages in thread From: Daniel Perzynski @ 2008-11-22 21:43 UTC (permalink / raw) To: linux-kernel, linu-acpi; +Cc: mjg59 Hi again, Below are messages collected for all special buttons of my laptop. Nov 22 13:11:49 h3xu5 input: HP WMI hotkeys as /class/input/input9 quickplay button -> Nov 22 13:13:10 h3xu5 HP WMI: Unknown key pressed - 22142 quickplay dvd button -> Nov 22 13:14:22 h3xu5 HP WMI: Unknown key pressed - 220e6 quickplay TV button -> Nov 22 13:14:52 h3xu5 HP WMI: Unknown key pressed - 22181 previous track button -> Nov 22 13:15:50 h3xu5 HP WMI: Unknown key pressed - 32192 stop button -> Nov 22 13:16:15 h3xu5 HP WMI: Unknown key pressed - 32191 play/pause button -> Nov 22 13:16:30 h3xu5 HP WMI: Unknown key pressed - 32190 next track button -> Nov 22 13:16:46 h3xu5 HP WMI: Unknown key pressed - 32193 4 above buttons are working fine in x-windows cinema button -> Nov 22 13:21:14 h3xu5 HP WMI: Unknown key pressed - 2218b synaptics touchpad button off/on: Nov 22 13:21:28 h3xu5 atkbd.c: Unknown key pressed (translated set 2, code 0xd8 on isa0060/serio0). Nov 22 13:21:28 h3xu5 atkbd.c: Use 'setkeycodes e058 <keycode>' to make it known. Nov 22 13:21:40 h3xu5 atkbd.c: Unknown key pressed (translated set 2, code 0xd9 on isa0060/serio0). Nov 22 13:21:40 h3xu5 atkbd.c: Use 'setkeycodes e059 <keycode>' to make it known. wifi button off Nov 22 13:22:26 h3xu5 usb 3-2: USB disconnect, address 3 Nov 22 13:22:26 h3xu5 btusb_intr_complete: hci0 urb ffff88013e1252c0 failed to resubmit (19) Nov 22 13:22:26 h3xu5 btusb_send_frame: hci0 urb ffff88013e1252c0 submission failed Nov 22 13:22:26 h3xu5 hcid[3607]: HCI dev 0 down Nov 22 13:22:26 h3xu5 hcid[3607]: Stopping security manager 0 Nov 22 13:22:26 h3xu5 hcid[3607]: Device hci0 has been disabled Nov 22 13:22:27 h3xu5 hcid[3607]: HCI dev 0 unregistered Nov 22 13:22:27 h3xu5 hcid[3607]: Unregister path: /org/bluez/hci0 Nov 22 13:22:27 h3xu5 hcid[3607]: Device hci0 has been removed Nov 22 13:22:29 h3xu5 hcid[3607]: Can't remove GN bridge Nov 22 13:22:29 h3xu5 hcid[3607]: Unregistered manager path Nov 22 13:22:29 h3xu5 hcid[3607]: Unregistered manager path Nov 22 13:22:29 h3xu5 hcid[3607]: Unregistered manager path Nov 22 13:22:29 h3xu5 hcid[3607]: Stopping SDP server Nov 22 13:22:29 h3xu5 hcid[3607]: Exit wifi button on Nov 22 13:23:01 h3xu5 usb 3-2: new full speed USB device using uhci_hcd and address 4 Nov 22 13:23:01 h3xu5 usb 3-2: configuration #1 chosen from 1 choice Nov 22 13:23:01 h3xu5 hcid[17796]: Bluetooth HCI daemon Nov 22 13:23:01 h3xu5 hcid[17796]: Parsing /etc/bluetooth/main.conf failed: No such file or directory Nov 22 13:23:02 h3xu5 hcid[17796]: Starting SDP server Nov 22 13:23:02 h3xu5 hcid[17796]: Parsing /etc/bluetooth/network.conf failed: No such file or directory Nov 22 13:23:02 h3xu5 hcid[17796]: Can't create GN bridge Nov 22 13:23:02 h3xu5 hcid[17796]: Registered manager path:/org/bluez/network Nov 22 13:23:02 h3xu5 hcid[17796]: Registered input manager path:/org/bluez/input Nov 22 13:23:02 h3xu5 hcid[17796]: Parsing /etc/bluetooth/audio.conf failed: No such file or directory Nov 22 13:23:02 h3xu5 hcid[17796]: Unix socket created: 16 Nov 22 13:23:02 h3xu5 hcid[17796]: Registered manager path:/org/bluez/audio Nov 22 13:23:02 h3xu5 hcid[17796]: Starting experimental netlink support Nov 22 13:23:02 h3xu5 hcid[17796]: Failed to find Bluetooth netlink family Nov 22 13:23:02 h3xu5 hcid[17796]: Can't init plugin /usr/lib64/bluetooth/plugins/netlink.so Nov 22 13:23:02 h3xu5 hcid[17796]: Registered manager path:/org/bluez/serial Nov 22 13:23:02 h3xu5 hcid[17796]: HCI dev 0 registered Nov 22 13:23:02 h3xu5 hcid[17796]: HCI dev 0 up Nov 22 13:23:02 h3xu5 hcid[17796]: Device hci0 has been added Nov 22 13:23:02 h3xu5 hcid[17796]: Starting security manager 0 Nov 22 13:23:02 h3xu5 hcid[17796]: Device hci0 has been activated As I understand wifi on/off is supported already by hp-wmi driver sound mute button -> Nov 22 13:23:28 h3xu5 HP WMI: Unknown key pressed - 32190 volume up -> Nov 22 13:24:02 h3xu5 HP WMI: Unknown key pressed - 32190 volume down -> Nov 22 13:24:04 h3xu5 HP WMI: Unknown key pressed - 32190 above 3 are working fine in x-windows bass/treble switch button -> Nov 22 13:25:06 h3xu5 HP WMI: Unknown key pressed - 22199 bass/treble up button: Nov 22 13:26:18 h3xu5 HP WMI: Unknown key pressed - 22197 Nov 22 13:26:18 h3xu5 atkbd.c: Unknown key pressed (translated set 2, code 0xbe on isa0060/serio0). Nov 22 13:26:18 h3xu5 atkbd.c: Use 'setkeycodes e03e <keycode>' to make it known. bass/treble down button: Nov 22 13:26:21 h3xu5 HP WMI: Unknown key pressed - 22198 Nov 22 13:26:21 h3xu5 atkbd.c: Unknown key pressed (translated set 2, code 0xbf on isa0060/serio0). Nov 22 13:26:21 h3xu5 atkbd.c: Use 'setkeycodes e03f <keycode>' to make it known. cd eject button -> Nov 22 13:26:45 h3xu5 HP WMI: Unknown key pressed - 0 If you have any question please let me know. Regards, ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: HP WMI laptop extras driver 2008-11-22 21:43 HP WMI laptop extras driver Daniel Perzynski @ 2008-11-28 17:19 ` Matthew Garrett [not found] ` <28f715610811301354l7b339acajeec24e9116409bef@mail.gmail.com> 0 siblings, 1 reply; 5+ messages in thread From: Matthew Garrett @ 2008-11-28 17:19 UTC (permalink / raw) To: Daniel Perzynski; +Cc: linux-kernel, linu-acpi Can you apply the attached patch, build the quickstart driver, load it and tell me what messages you get from the quickstart keys on your device? diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b0243fd..94460ea 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -400,4 +400,11 @@ config ACPI_SBS This driver adds support for the Smart Battery System, another type of access to battery information, found on some laptops. +config ACPI_QUICKSTART + tristate "ACPI Application Quickstart Keys" + depends on INPUT + help + This driver adds support for the PNP0C32 application start keys + found on some laptops. + endif # ACPI diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 3c0c933..898ca7b 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -66,3 +66,4 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o obj-$(CONFIG_ACPI_SBS) += sbshc.o obj-$(CONFIG_ACPI_SBS) += sbs.o +obj-$(CONFIG_ACPI_QUICKSTART) += quickstart.o diff --git a/drivers/acpi/quickstart.c b/drivers/acpi/quickstart.c new file mode 100644 index 0000000..2abbeb0 --- /dev/null +++ b/drivers/acpi/quickstart.c @@ -0,0 +1,507 @@ +/* + * quickstart.c - ACPI Direct App Launch driver + * + * Copyright (C) 2007 Angelo Arrifano <miknix@gmail.com> + * + * Information gathered from disassebled dsdt and from here: + * "http://download.microsoft.com/download/9/c/5/ + * 9c5b2167-8017-4bae-9fde-d599bac8184a/DirAppLaunch_Vista.doc" + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define QUICKSTART_VERSION "1.00" + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <acpi/acpi_drivers.h> +#include <linux/platform_device.h> +#include <linux/input.h> + +MODULE_AUTHOR("Angelo Arrifano"); +MODULE_DESCRIPTION("ACPI Direct App Launch driver"); +MODULE_LICENSE("GPL"); + +#define QUICKSTART_ACPI_DEVICE_NAME "quickstart" +#define QUICKSTART_ACPI_CLASS "quickstart" +#define QUICKSTART_ACPI_HID "PNP0C32" + +#define QUICKSTART_PF_DRIVER_NAME "quickstart" +#define QUICKSTART_PF_DEVICE_NAME "quickstart" +#define QUICKSTART_PF_DEVATTR_NAME "pressed_button" + +#define QUICKSTART_MAX_BTN_NAME_LEN 16 + +struct quickstart_btn_list { + char *name; + struct quickstart_btn_list *next; +}; + +static struct quickstart_driver_data { + struct quickstart_btn_list *btn_lst; + struct quickstart_btn_list *pressed; +} quickstart_data = { +.btn_lst = NULL,.pressed = NULL,}; + +static struct input_dev *quickstart_input_dev; + +/* + * ACPI driver Structs + */ + +struct quickstart_acpi { + struct acpi_device *device; + struct quickstart_btn_list *btn; +}; +static int quickstart_acpi_add(struct acpi_device *device); +static int quickstart_acpi_remove(struct acpi_device *device, int type); +static const struct acpi_device_id quickstart_device_ids[] = { + {QUICKSTART_ACPI_HID, 0}, + {"", 0}, +}; + +static struct acpi_driver quickstart_acpi_driver = { + .name = "quickstart", + .class = QUICKSTART_ACPI_CLASS, + .ids = quickstart_device_ids, + .ops = { + .add = quickstart_acpi_add, + .remove = quickstart_acpi_remove, + }, +}; + +/* + * Platform driver structs + */ +static ssize_t buttons_show(struct device *dev, + struct device_attribute *attr, char *buf); +static ssize_t pressed_button_show(struct device *dev, + struct device_attribute *attr, char *buf); +static ssize_t pressed_button_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static DEVICE_ATTR(pressed_button, 0666, pressed_button_show, + pressed_button_store); +static DEVICE_ATTR(buttons, 0444, buttons_show, NULL); +static struct platform_device *pf_device; +static struct platform_driver pf_driver = { + .driver = { + .name = QUICKSTART_PF_DRIVER_NAME, + .owner = THIS_MODULE, + } +}; + +struct key_entry { + char type; /* See KE_* below */ + u32 code; + u16 keycode; +}; + +enum { KE_KEY, KE_END }; + +static struct key_entry quickstart_keymap[] = { + {KE_END, 0} +}; + +static struct key_entry *quickstart_get_entry_by_scancode(int code) +{ + struct key_entry *key; + + for (key = quickstart_keymap; key->type != KE_END; key++) + if (code == key->code) + return key; + + return NULL; +} + +static struct key_entry *quickstart_get_entry_by_keycode(int keycode) +{ + struct key_entry *key; + + for (key = quickstart_keymap; key->type != KE_END; key++) + if (key->type == KE_KEY && keycode == key->keycode) + return key; + + return NULL; +} + +static int quickstart_getkeycode(struct input_dev *dev, int scancode, + int *keycode) +{ + struct key_entry *key = quickstart_get_entry_by_scancode(scancode); + + if (key && key->type == KE_KEY) { + *keycode = key->keycode; + return 0; + } + + return -EINVAL; +} + +static int quickstart_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 = quickstart_get_entry_by_scancode(scancode); + if (key && key->type == KE_KEY) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!quickstart_get_entry_by_keycode(old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; + } + + return -EINVAL; +} + +/* + * Platform driver functions + */ +static ssize_t buttons_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count = 0; + char tmpbuf[QUICKSTART_MAX_BTN_NAME_LEN + 2]; + struct quickstart_btn_list *ptr = quickstart_data.btn_lst; + + if (!ptr) + return snprintf(buf, PAGE_SIZE, "none"); + + while (ptr && (count < PAGE_SIZE)) { + if (ptr->name) { + strncpy(tmpbuf, ptr->name, QUICKSTART_MAX_BTN_NAME_LEN); + strcat(tmpbuf, "\n"); + count += snprintf(buf + count, + PAGE_SIZE - count, tmpbuf); + } + ptr = ptr->next; + } + + return count; +} + +static ssize_t pressed_button_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", + (quickstart_data.pressed ? quickstart_data.pressed-> + name : "none")); +} + +static ssize_t pressed_button_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + if (count < 2) + return -EINVAL; + + if (strncasecmp(buf, "none", 4) != 0) + return -EINVAL; + + quickstart_data.pressed = NULL; + return count; +} + +/* Hotstart Helper functions */ +static int quickstart_btnlst_add(struct quickstart_btn_list **data) +{ + struct quickstart_btn_list **ptr = &quickstart_data.btn_lst; + + while (*ptr) + ptr = &((*ptr)->next); + + *ptr = kzalloc(sizeof(struct quickstart_btn_list), GFP_KERNEL); + if (!*ptr) { + *data = NULL; + return (-ENOMEM); + } + *data = *ptr; + + return 0; +} + +static void quickstart_btnlst_free(void) +{ + struct quickstart_btn_list *ptr = quickstart_data.btn_lst; + struct quickstart_btn_list *lptr = NULL; + + if (!ptr) + return; + + while (ptr) { + lptr = ptr; + ptr = ptr->next; + if (lptr->name) + kfree(lptr->name); + kfree(lptr); + } + + return; +} + +static void quickstart_acpi_get_event(struct quickstart_acpi *quickstart, + unsigned long long *button) +{ + acpi_status status; + + status = acpi_evaluate_integer(quickstart->device->handle, + "GHID", NULL, button); + if (ACPI_FAILURE(status)) + printk (KERN_WARNING + "quickstart: Warning: GHID method failed\n"); + + return; +} + +/* ACPI Driver functions */ +static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data) +{ + struct quickstart_acpi *quickstart = data; + struct key_entry *key; + unsigned long long button; + + if (!quickstart) + return; + + /* There will be two events: + * 0x02 - A quickstart button was pressed while device was off/sleeping. + * 0x80 - A quickstart button was pressed while device was up. */ + if (event & 0x02) + quickstart_data.pressed = quickstart->btn; + + quickstart_acpi_get_event(quickstart, &button); + + key = quickstart_get_entry_by_scancode(button); + + if (!key) + printk(KERN_INFO "Quickstart: Unknown key pressed - 0x%llx\n", + button); + + input_report_key(quickstart_input_dev, key->keycode, 1); + input_sync(quickstart_input_dev); + input_report_key(quickstart_input_dev, key->keycode, 0); + input_sync(quickstart_input_dev); + + return; +} + +static int quickstart_acpi_config(struct quickstart_acpi *quickstart, char *bid) +{ + int len = strlen(bid); + int ret; + + /* Add button to list */ + ret = quickstart_btnlst_add(&quickstart->btn); + if (ret) + return ret; + + quickstart->btn->name = kzalloc(len + 1, GFP_KERNEL); + if (!quickstart->btn->name) { + quickstart_btnlst_free(); + return -ENOMEM; + } + strcpy(quickstart->btn->name, bid); + + return 0; +} + +static int quickstart_acpi_add(struct acpi_device *device) +{ + int ret = 0; + acpi_status status = AE_OK; + struct quickstart_acpi *quickstart = NULL; + + if (!device) + return -EINVAL; + + quickstart = kzalloc(sizeof(struct quickstart_acpi), GFP_KERNEL); + if (!quickstart) + return -ENOMEM; + + quickstart->device = device; + strcpy(acpi_device_name(device), QUICKSTART_ACPI_DEVICE_NAME); + strcpy(acpi_device_class(device), QUICKSTART_ACPI_CLASS); + device->driver_data = quickstart; + + /* Add button to list and initialize some stuff */ + ret = quickstart_acpi_config(quickstart, acpi_device_bid(device)); + if (ret) + goto fail_config; + + status = acpi_install_notify_handler(device->handle, + ACPI_ALL_NOTIFY, + quickstart_acpi_notify, + quickstart); + if (ACPI_FAILURE(status)) { + printk("quickstart: Error installing notify handler\n"); + ret = -ENODEV; + goto fail_installnotify; + } + + /* Call device GHID method. This is a workaround to get a notify + * event when hot button is pressed while laptop is powered off. + * This works, even if the method fails. */ + quickstart_acpi_get_event(quickstart, NULL); + + return 0; + +fail_installnotify: +fail_config: + + kfree(quickstart); + + return ret; +} + +static int quickstart_acpi_remove(struct acpi_device *device, int type) +{ + acpi_status status = 0; + struct quickstart_acpi *quickstart = NULL; + + if (!device || !acpi_driver_data(device)) + return -EINVAL; + + quickstart = acpi_driver_data(device); + + status = acpi_remove_notify_handler(device->handle, + ACPI_ALL_NOTIFY, + quickstart_acpi_notify); + if (ACPI_FAILURE(status)) + printk("quickstart: Error removing notify handler\n"); + + kfree(quickstart); + + return 0; +} + +/* Module functions */ + +static void quickstart_exit(void) +{ + device_remove_file(&pf_device->dev, &dev_attr_pressed_button); + device_remove_file(&pf_device->dev, &dev_attr_buttons); + + input_unregister_device(quickstart_input_dev); + + platform_device_unregister(pf_device); + + platform_driver_unregister(&pf_driver); + + acpi_bus_unregister_driver(&quickstart_acpi_driver); + + quickstart_btnlst_free(); + + return; +} + +static int __init quickstart_init(void) +{ + int ret; + acpi_status status = 0; + struct key_entry *key; + + /* ACPI Check */ + if (acpi_disabled) + return -ENODEV; + + /* ACPI driver register */ + status = acpi_bus_register_driver(&quickstart_acpi_driver); + if (status < 0) + return -ENODEV; + + /* Platform driver register */ + ret = platform_driver_register(&pf_driver); + if (ret) + goto fail_pfdrv_reg; + + /* Platform device register */ + pf_device = platform_device_alloc(QUICKSTART_PF_DEVICE_NAME, -1); + if (!pf_device) { + ret = -ENOMEM; + goto fail_pfdev_alloc; + } + + ret = platform_device_register(pf_device); + if (ret) + goto fail_pfdev_reg; + + /* Create device sysfs file */ + ret = device_create_file(&pf_device->dev, &dev_attr_pressed_button); + if (ret) + goto fail_dev_file; + + ret = device_create_file(&pf_device->dev, &dev_attr_buttons); + if (ret) + goto fail_dev_file2; + + quickstart_input_dev = input_allocate_device(); + if (!quickstart_input_dev) + goto fail_input_alloc; + + quickstart_input_dev->name = "ACPI Quickstart hotkeys"; + quickstart_input_dev->phys = "quickstart/input0"; + quickstart_input_dev->id.bustype = BUS_HOST; + quickstart_input_dev->getkeycode = quickstart_getkeycode; + quickstart_input_dev->setkeycode = quickstart_setkeycode; + + for (key = quickstart_keymap; key->type != KE_END; key++) { + set_bit(EV_KEY, quickstart_input_dev->evbit); + set_bit(key->keycode, quickstart_input_dev->evbit); + } + + ret = input_register_device(quickstart_input_dev); + if (ret) + goto fail_input_register; + + printk("quickstart: ACPI Direct App Launch ver %s\n", + QUICKSTART_VERSION); + + return 0; + +fail_input_register: + input_free_device(quickstart_input_dev); + +fail_input_alloc: + device_remove_file(&pf_device->dev, &dev_attr_buttons); + +fail_dev_file2: + device_remove_file(&pf_device->dev, &dev_attr_pressed_button); + +fail_dev_file: + platform_device_del(pf_device); + +fail_pfdev_reg: + platform_device_put(pf_device); + +fail_pfdev_alloc: + platform_driver_unregister(&pf_driver); + +fail_pfdrv_reg: + acpi_bus_unregister_driver(&quickstart_acpi_driver); + + return ret; +} + +module_init(quickstart_init); +module_exit(quickstart_exit); -- Matthew Garrett | mjg59@srcf.ucam.org ^ permalink raw reply [flat|nested] 5+ messages in thread
[parent not found: <28f715610811301354l7b339acajeec24e9116409bef@mail.gmail.com>]
* Fwd: HP WMI laptop extras driver [not found] ` <28f715610811301354l7b339acajeec24e9116409bef@mail.gmail.com> @ 2008-12-22 22:36 ` Daniel Perzynski 0 siblings, 0 replies; 5+ messages in thread From: Daniel Perzynski @ 2008-12-22 22:36 UTC (permalink / raw) To: linux-kernel; +Cc: mjg59 I've tried to load that driver on 2.6.28-rc6 and 2.6.27.4. Both are giving me that :( Nov 30 14:27:29 h3xu5 quickstart: Warning: GHID method failed Nov 30 14:27:29 h3xu5 quickstart: Warning: GHID method failed Nov 30 14:27:29 h3xu5 quickstart: Warning: GHID method failed Nov 30 14:27:29 h3xu5 quickstart: Warning: GHID method failed Nov 30 14:27:29 h3xu5 quickstart: Warning: GHID method failed Nov 30 14:27:29 h3xu5 quickstart: Warning: GHID method failed Nov 30 14:27:29 h3xu5 kobject (ffff88013f8e9100): tried to init an initialized object, something is seriously wrong. Nov 30 14:27:29 h3xu5 Pid: 3565, comm: modprobe Not tainted 2.6.28-rc6-qp #1 Nov 30 14:27:29 h3xu5 Call Trace: Nov 30 14:27:29 h3xu5 [<ffffffff8037db0e>] kobject_init+0x9e/0xa0 Nov 30 14:27:29 h3xu5 [<ffffffffa03e2000>] ? quickstart_init+0x0/0x1bd [quickstart] Nov 30 14:27:29 h3xu5 [<ffffffff8040579d>] device_initialize+0x2d/0xc0 Nov 30 14:27:29 h3xu5 [<ffffffff8040a055>] platform_device_register+0x15/0x30 Nov 30 14:27:29 h3xu5 [<ffffffffa03e2069>] quickstart_init+0x69/0x1bd [quickstart] Nov 30 14:27:29 h3xu5 [<ffffffff8020903b>] _stext+0x3b/0x170 Nov 30 14:27:29 h3xu5 [<ffffffff803d70dc>] ? acpi_bus_register_driver+0x0/0x40 Nov 30 14:27:29 h3xu5 [<ffffffff8026f67d>] sys_init_module+0xad/0x1e0 Nov 30 14:27:29 h3xu5 [<ffffffff8020c3ab>] system_call_fastpath+0x16/0x1b Nov 30 14:27:29 h3xu5 input: ACPI Quickstart hotkeys as /class/input/input11 Nov 30 14:27:29 h3xu5 quickstart: ACPI Direct App Launch ver 1.00 On Fri, Nov 28, 2008 at 6:19 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote: > Can you apply the attached patch, build the quickstart driver, load it > and tell me what messages you get from the quickstart keys on your > device? > > diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig > index b0243fd..94460ea 100644 > --- a/drivers/acpi/Kconfig > +++ b/drivers/acpi/Kconfig > @@ -400,4 +400,11 @@ config ACPI_SBS > This driver adds support for the Smart Battery System, another > type of access to battery information, found on some laptops. > > +config ACPI_QUICKSTART > + tristate "ACPI Application Quickstart Keys" > + depends on INPUT > + help > + This driver adds support for the PNP0C32 application start keys > + found on some laptops. > + > endif # ACPI > diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile > index 3c0c933..898ca7b 100644 > --- a/drivers/acpi/Makefile > +++ b/drivers/acpi/Makefile > @@ -66,3 +66,4 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o > obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o > obj-$(CONFIG_ACPI_SBS) += sbshc.o > obj-$(CONFIG_ACPI_SBS) += sbs.o > +obj-$(CONFIG_ACPI_QUICKSTART) += quickstart.o > diff --git a/drivers/acpi/quickstart.c b/drivers/acpi/quickstart.c > new file mode 100644 > index 0000000..2abbeb0 > --- /dev/null > +++ b/drivers/acpi/quickstart.c > @@ -0,0 +1,507 @@ > +/* > + * quickstart.c - ACPI Direct App Launch driver > + * > + * Copyright (C) 2007 Angelo Arrifano <miknix@gmail.com> > + * > + * Information gathered from disassebled dsdt and from here: > + * "http://download.microsoft.com/download/9/c/5/ > + * 9c5b2167-8017-4bae-9fde-d599bac8184a/DirAppLaunch_Vista.doc" > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + * > + */ > + > +#define QUICKSTART_VERSION "1.00" > + > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/init.h> > +#include <linux/types.h> > +#include <acpi/acpi_drivers.h> > +#include <linux/platform_device.h> > +#include <linux/input.h> > + > +MODULE_AUTHOR("Angelo Arrifano"); > +MODULE_DESCRIPTION("ACPI Direct App Launch driver"); > +MODULE_LICENSE("GPL"); > + > +#define QUICKSTART_ACPI_DEVICE_NAME "quickstart" > +#define QUICKSTART_ACPI_CLASS "quickstart" > +#define QUICKSTART_ACPI_HID "PNP0C32" > + > +#define QUICKSTART_PF_DRIVER_NAME "quickstart" > +#define QUICKSTART_PF_DEVICE_NAME "quickstart" > +#define QUICKSTART_PF_DEVATTR_NAME "pressed_button" > + > +#define QUICKSTART_MAX_BTN_NAME_LEN 16 > + > +struct quickstart_btn_list { > + char *name; > + struct quickstart_btn_list *next; > +}; > + > +static struct quickstart_driver_data { > + struct quickstart_btn_list *btn_lst; > + struct quickstart_btn_list *pressed; > +} quickstart_data = { > +.btn_lst = NULL,.pressed = NULL,}; > + > +static struct input_dev *quickstart_input_dev; > + > +/* > + * ACPI driver Structs > + */ > + > +struct quickstart_acpi { > + struct acpi_device *device; > + struct quickstart_btn_list *btn; > +}; > +static int quickstart_acpi_add(struct acpi_device *device); > +static int quickstart_acpi_remove(struct acpi_device *device, int type); > +static const struct acpi_device_id quickstart_device_ids[] = { > + {QUICKSTART_ACPI_HID, 0}, > + {"", 0}, > +}; > + > +static struct acpi_driver quickstart_acpi_driver = { > + .name = "quickstart", > + .class = QUICKSTART_ACPI_CLASS, > + .ids = quickstart_device_ids, > + .ops = { > + .add = quickstart_acpi_add, > + .remove = quickstart_acpi_remove, > + }, > +}; > + > +/* > + * Platform driver structs > + */ > +static ssize_t buttons_show(struct device *dev, > + struct device_attribute *attr, char *buf); > +static ssize_t pressed_button_show(struct device *dev, > + struct device_attribute *attr, char *buf); > +static ssize_t pressed_button_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count); > +static DEVICE_ATTR(pressed_button, 0666, pressed_button_show, > + pressed_button_store); > +static DEVICE_ATTR(buttons, 0444, buttons_show, NULL); > +static struct platform_device *pf_device; > +static struct platform_driver pf_driver = { > + .driver = { > + .name = QUICKSTART_PF_DRIVER_NAME, > + .owner = THIS_MODULE, > + } > +}; > + > +struct key_entry { > + char type; /* See KE_* below */ > + u32 code; > + u16 keycode; > +}; > + > +enum { KE_KEY, KE_END }; > + > +static struct key_entry quickstart_keymap[] = { > + {KE_END, 0} > +}; > + > +static struct key_entry *quickstart_get_entry_by_scancode(int code) > +{ > + struct key_entry *key; > + > + for (key = quickstart_keymap; key->type != KE_END; key++) > + if (code == key->code) > + return key; > + > + return NULL; > +} > + > +static struct key_entry *quickstart_get_entry_by_keycode(int keycode) > +{ > + struct key_entry *key; > + > + for (key = quickstart_keymap; key->type != KE_END; key++) > + if (key->type == KE_KEY && keycode == key->keycode) > + return key; > + > + return NULL; > +} > + > +static int quickstart_getkeycode(struct input_dev *dev, int scancode, > + int *keycode) > +{ > + struct key_entry *key = quickstart_get_entry_by_scancode(scancode); > + > + if (key && key->type == KE_KEY) { > + *keycode = key->keycode; > + return 0; > + } > + > + return -EINVAL; > +} > + > +static int quickstart_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 = quickstart_get_entry_by_scancode(scancode); > + if (key && key->type == KE_KEY) { > + old_keycode = key->keycode; > + key->keycode = keycode; > + set_bit(keycode, dev->keybit); > + if (!quickstart_get_entry_by_keycode(old_keycode)) > + clear_bit(old_keycode, dev->keybit); > + return 0; > + } > + > + return -EINVAL; > +} > + > +/* > + * Platform driver functions > + */ > +static ssize_t buttons_show(struct device *dev, > + struct device_attribute *attr, char *buf) > +{ > + int count = 0; > + char tmpbuf[QUICKSTART_MAX_BTN_NAME_LEN + 2]; > + struct quickstart_btn_list *ptr = quickstart_data.btn_lst; > + > + if (!ptr) > + return snprintf(buf, PAGE_SIZE, "none"); > + > + while (ptr && (count < PAGE_SIZE)) { > + if (ptr->name) { > + strncpy(tmpbuf, ptr->name, QUICKSTART_MAX_BTN_NAME_LEN); > + strcat(tmpbuf, "\n"); > + count += snprintf(buf + count, > + PAGE_SIZE - count, tmpbuf); > + } > + ptr = ptr->next; > + } > + > + return count; > +} > + > +static ssize_t pressed_button_show(struct device *dev, > + struct device_attribute *attr, char *buf) > +{ > + return snprintf(buf, PAGE_SIZE, "%s\n", > + (quickstart_data.pressed ? quickstart_data.pressed-> > + name : "none")); > +} > + > +static ssize_t pressed_button_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + if (count < 2) > + return -EINVAL; > + > + if (strncasecmp(buf, "none", 4) != 0) > + return -EINVAL; > + > + quickstart_data.pressed = NULL; > + return count; > +} > + > +/* Hotstart Helper functions */ > +static int quickstart_btnlst_add(struct quickstart_btn_list **data) > +{ > + struct quickstart_btn_list **ptr = &quickstart_data.btn_lst; > + > + while (*ptr) > + ptr = &((*ptr)->next); > + > + *ptr = kzalloc(sizeof(struct quickstart_btn_list), GFP_KERNEL); > + if (!*ptr) { > + *data = NULL; > + return (-ENOMEM); > + } > + *data = *ptr; > + > + return 0; > +} > + > +static void quickstart_btnlst_free(void) > +{ > + struct quickstart_btn_list *ptr = quickstart_data.btn_lst; > + struct quickstart_btn_list *lptr = NULL; > + > + if (!ptr) > + return; > + > + while (ptr) { > + lptr = ptr; > + ptr = ptr->next; > + if (lptr->name) > + kfree(lptr->name); > + kfree(lptr); > + } > + > + return; > +} > + > +static void quickstart_acpi_get_event(struct quickstart_acpi *quickstart, > + unsigned long long *button) > +{ > + acpi_status status; > + > + status = acpi_evaluate_integer(quickstart->device->handle, > + "GHID", NULL, button); > + if (ACPI_FAILURE(status)) > + printk (KERN_WARNING > + "quickstart: Warning: GHID method failed\n"); > + > + return; > +} > + > +/* ACPI Driver functions */ > +static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data) > +{ > + struct quickstart_acpi *quickstart = data; > + struct key_entry *key; > + unsigned long long button; > + > + if (!quickstart) > + return; > + > + /* There will be two events: > + * 0x02 - A quickstart button was pressed while device was off/sleeping. > + * 0x80 - A quickstart button was pressed while device was up. */ > + if (event & 0x02) > + quickstart_data.pressed = quickstart->btn; > + > + quickstart_acpi_get_event(quickstart, &button); > + > + key = quickstart_get_entry_by_scancode(button); > + > + if (!key) > + printk(KERN_INFO "Quickstart: Unknown key pressed - 0x%llx\n", > + button); > + > + input_report_key(quickstart_input_dev, key->keycode, 1); > + input_sync(quickstart_input_dev); > + input_report_key(quickstart_input_dev, key->keycode, 0); > + input_sync(quickstart_input_dev); > + > + return; > +} > + > +static int quickstart_acpi_config(struct quickstart_acpi *quickstart, char *bid) > +{ > + int len = strlen(bid); > + int ret; > + > + /* Add button to list */ > + ret = quickstart_btnlst_add(&quickstart->btn); > + if (ret) > + return ret; > + > + quickstart->btn->name = kzalloc(len + 1, GFP_KERNEL); > + if (!quickstart->btn->name) { > + quickstart_btnlst_free(); > + return -ENOMEM; > + } > + strcpy(quickstart->btn->name, bid); > + > + return 0; > +} > + > +static int quickstart_acpi_add(struct acpi_device *device) > +{ > + int ret = 0; > + acpi_status status = AE_OK; > + struct quickstart_acpi *quickstart = NULL; > + > + if (!device) > + return -EINVAL; > + > + quickstart = kzalloc(sizeof(struct quickstart_acpi), GFP_KERNEL); > + if (!quickstart) > + return -ENOMEM; > + > + quickstart->device = device; > + strcpy(acpi_device_name(device), QUICKSTART_ACPI_DEVICE_NAME); > + strcpy(acpi_device_class(device), QUICKSTART_ACPI_CLASS); > + device->driver_data = quickstart; > + > + /* Add button to list and initialize some stuff */ > + ret = quickstart_acpi_config(quickstart, acpi_device_bid(device)); > + if (ret) > + goto fail_config; > + > + status = acpi_install_notify_handler(device->handle, > + ACPI_ALL_NOTIFY, > + quickstart_acpi_notify, > + quickstart); > + if (ACPI_FAILURE(status)) { > + printk("quickstart: Error installing notify handler\n"); > + ret = -ENODEV; > + goto fail_installnotify; > + } > + > + /* Call device GHID method. This is a workaround to get a notify > + * event when hot button is pressed while laptop is powered off. > + * This works, even if the method fails. */ > + quickstart_acpi_get_event(quickstart, NULL); > + > + return 0; > + > +fail_installnotify: > +fail_config: > + > + kfree(quickstart); > + > + return ret; > +} > + > +static int quickstart_acpi_remove(struct acpi_device *device, int type) > +{ > + acpi_status status = 0; > + struct quickstart_acpi *quickstart = NULL; > + > + if (!device || !acpi_driver_data(device)) > + return -EINVAL; > + > + quickstart = acpi_driver_data(device); > + > + status = acpi_remove_notify_handler(device->handle, > + ACPI_ALL_NOTIFY, > + quickstart_acpi_notify); > + if (ACPI_FAILURE(status)) > + printk("quickstart: Error removing notify handler\n"); > + > + kfree(quickstart); > + > + return 0; > +} > + > +/* Module functions */ > + > +static void quickstart_exit(void) > +{ > + device_remove_file(&pf_device->dev, &dev_attr_pressed_button); > + device_remove_file(&pf_device->dev, &dev_attr_buttons); > + > + input_unregister_device(quickstart_input_dev); > + > + platform_device_unregister(pf_device); > + > + platform_driver_unregister(&pf_driver); > + > + acpi_bus_unregister_driver(&quickstart_acpi_driver); > + > + quickstart_btnlst_free(); > + > + return; > +} > + > +static int __init quickstart_init(void) > +{ > + int ret; > + acpi_status status = 0; > + struct key_entry *key; > + > + /* ACPI Check */ > + if (acpi_disabled) > + return -ENODEV; > + > + /* ACPI driver register */ > + status = acpi_bus_register_driver(&quickstart_acpi_driver); > + if (status < 0) > + return -ENODEV; > + > + /* Platform driver register */ > + ret = platform_driver_register(&pf_driver); > + if (ret) > + goto fail_pfdrv_reg; > + > + /* Platform device register */ > + pf_device = platform_device_alloc(QUICKSTART_PF_DEVICE_NAME, -1); > + if (!pf_device) { > + ret = -ENOMEM; > + goto fail_pfdev_alloc; > + } > + > + ret = platform_device_register(pf_device); > + if (ret) > + goto fail_pfdev_reg; > + > + /* Create device sysfs file */ > + ret = device_create_file(&pf_device->dev, &dev_attr_pressed_button); > + if (ret) > + goto fail_dev_file; > + > + ret = device_create_file(&pf_device->dev, &dev_attr_buttons); > + if (ret) > + goto fail_dev_file2; > + > + quickstart_input_dev = input_allocate_device(); > + if (!quickstart_input_dev) > + goto fail_input_alloc; > + > + quickstart_input_dev->name = "ACPI Quickstart hotkeys"; > + quickstart_input_dev->phys = "quickstart/input0"; > + quickstart_input_dev->id.bustype = BUS_HOST; > + quickstart_input_dev->getkeycode = quickstart_getkeycode; > + quickstart_input_dev->setkeycode = quickstart_setkeycode; > + > + for (key = quickstart_keymap; key->type != KE_END; key++) { > + set_bit(EV_KEY, quickstart_input_dev->evbit); > + set_bit(key->keycode, quickstart_input_dev->evbit); > + } > + > + ret = input_register_device(quickstart_input_dev); > + if (ret) > + goto fail_input_register; > + > + printk("quickstart: ACPI Direct App Launch ver %s\n", > + QUICKSTART_VERSION); > + > + return 0; > + > +fail_input_register: > + input_free_device(quickstart_input_dev); > + > +fail_input_alloc: > + device_remove_file(&pf_device->dev, &dev_attr_buttons); > + > +fail_dev_file2: > + device_remove_file(&pf_device->dev, &dev_attr_pressed_button); > + > +fail_dev_file: > + platform_device_del(pf_device); > + > +fail_pfdev_reg: > + platform_device_put(pf_device); > + > +fail_pfdev_alloc: > + platform_driver_unregister(&pf_driver); > + > +fail_pfdrv_reg: > + acpi_bus_unregister_driver(&quickstart_acpi_driver); > + > + return ret; > +} > + > +module_init(quickstart_init); > +module_exit(quickstart_exit); > > -- > Matthew Garrett | mjg59@srcf.ucam.org > Can someone help me with the fix to that patch? ^ permalink raw reply [flat|nested] 5+ messages in thread
[parent not found: <28f715610811221340s5911bf20mf763f0e6990c7078@mail.gmail.com>]
* Re: HP WMI laptop extras driver [not found] <28f715610811221340s5911bf20mf763f0e6990c7078@mail.gmail.com> @ 2008-11-28 16:12 ` Matthew Garrett 0 siblings, 0 replies; 5+ messages in thread From: Matthew Garrett @ 2008-11-28 16:12 UTC (permalink / raw) To: Daniel Perzynski; +Cc: linux-kernel On Sat, Nov 22, 2008 at 10:40:17PM +0100, Daniel Perzynski wrote: > Nov 22 13:11:49 h3xu5 input: HP WMI hotkeys as /class/input/input9 > quickplay button -> Nov 22 13:13:10 h3xu5 HP WMI: Unknown key pressed - 22142 > quickplay dvd button -> Nov 22 13:14:22 h3xu5 HP WMI: Unknown key pressed - > 220e6 > quickplay TV button -> Nov 22 13:14:52 h3xu5 HP WMI: Unknown key pressed - > 22181 Hm. I /suspect/ that these would be better handled by a quickplay button driver. There's a patch for that lying around - I'll try to get it updated. > previous track button -> Nov 22 13:15:50 h3xu5 HP WMI: Unknown key pressed - > 32192 > stop button -> Nov 22 13:16:15 h3xu5 HP WMI: Unknown key pressed - 32191 > play/pause button -> Nov 22 13:16:30 h3xu5 HP WMI: Unknown key pressed - 32190 > next track button -> Nov 22 13:16:46 h3xu5 HP WMI: Unknown key pressed - 32193 > > 4 above buttons are working fine in x-windows Ok, so again handling them in hp-wmi is probably not a good idea. > As I understand wifi on/off is supported already by hp-wmi driver Yup. > sound mute button -> Nov 22 13:23:28 h3xu5 HP WMI: Unknown key pressed - 32190 > volume up -> Nov 22 13:24:02 h3xu5 HP WMI: Unknown key pressed - 32190 > volume down -> Nov 22 13:24:04 h3xu5 HP WMI: Unknown key pressed - 32190 > > above 3 are working fine in x-windows Since they're going through the keyboard controller, we should probably ignore them. > bass/treble switch button -> Nov 22 13:25:06 h3xu5 HP WMI: Unknown key pressed > - 22199 > bass/treble up button: > Nov 22 13:26:18 h3xu5 HP WMI: Unknown key pressed - 22197 > Nov 22 13:26:18 h3xu5 atkbd.c: Unknown key pressed (translated set 2, code 0xbe > on isa0060/serio0). > Nov 22 13:26:18 h3xu5 atkbd.c: Use 'setkeycodes e03e <keycode>' to make it > known. > bass/treble down button: > Nov 22 13:26:21 h3xu5 HP WMI: Unknown key pressed - 22198 > Nov 22 13:26:21 h3xu5 atkbd.c: Unknown key pressed (translated set 2, code 0xbf > on isa0060/serio0). > Nov 22 13:26:21 h3xu5 atkbd.c: Use 'setkeycodes e03f <keycode>' to make it > known. > cd eject button -> Nov 22 13:26:45 h3xu5 HP WMI: Unknown key pressed - 0 Again, looks like these are going through the keyboard controller. Thanks for the feedback, I'll try to work out a way of avoiding printing the messages. -- Matthew Garrett | mjg59@srcf.ucam.org ^ permalink raw reply [flat|nested] 5+ messages in thread
[parent not found: <28f715610810310624m67b86d10t76b21b2cbbf2a8ac@mail.gmail.com>]
* Re: HP WMI laptop extras driver [not found] <28f715610810310624m67b86d10t76b21b2cbbf2a8ac@mail.gmail.com> @ 2008-10-31 13:28 ` Matthew Garrett 0 siblings, 0 replies; 5+ messages in thread From: Matthew Garrett @ 2008-10-31 13:28 UTC (permalink / raw) To: Daniel Perzynski; +Cc: linu-acpi, linux-kernel, carlos On Fri, Oct 31, 2008 at 02:24:44PM +0100, Daniel Perzynski wrote: > I have HP Pavilion HDX9494nr. That laptop has many additional keys like CD > Eject, Treble and Bass regulation, Quick Play section (DVD,TV,Quick Play). When > I'm pressing those buttons (after loading hp-wmi driver) I see in kernel > messages that I've pressed a key with the code xxxxxx. How can I map those > events to actions (for example pressing CD Eject I would like to map to unmount > /dev/cdrom command). Do we need to add my key codes to hp-wmi.c program or > there is another program which can translate those key codes to actions? Can you include the exact messages that you get when pressing each button? Thanks, -- Matthew Garrett | mjg59@srcf.ucam.org ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-12-22 22:36 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-11-22 21:43 HP WMI laptop extras driver Daniel Perzynski 2008-11-28 17:19 ` Matthew Garrett [not found] ` <28f715610811301354l7b339acajeec24e9116409bef@mail.gmail.com> 2008-12-22 22:36 ` Fwd: " Daniel Perzynski [not found] <28f715610811221340s5911bf20mf763f0e6990c7078@mail.gmail.com> 2008-11-28 16:12 ` Matthew Garrett [not found] <28f715610810310624m67b86d10t76b21b2cbbf2a8ac@mail.gmail.com> 2008-10-31 13:28 ` Matthew Garrett
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).