* [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
@ 2008-03-14 15:17 Ângelo Miguel Arrifano
2008-03-25 6:59 ` Zhang, Rui
0 siblings, 1 reply; 18+ messages in thread
From: Ângelo Miguel Arrifano @ 2008-03-14 15:17 UTC (permalink / raw)
To: rui.zhang; +Cc: linux-acpi
Here is the patch made from the today linux-acpi tree.
Thanks,
Angelo Arrifano
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index f688c21..fb096ee 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -196,6 +196,14 @@ config ACPI_THERMAL
recommended that this option be enabled, as your processor(s)
may be damaged without it.
+config ACPI_QUICKSTART
+ tristate "Quickstart"
+ default y
+ help
+ This driver add support for ACPI Direct Application Launch
+ also known as Hotstart(TM). Say yes here to have a entry in
+ sysfs telling which button was used to turn on the system.
+
config ACPI_NUMA
bool "NUMA support"
depends on NUMA
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index f29812a..badb0a6 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -62,3 +62,4 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += sbs.o
obj-$(CONFIG_ACPI_SBS) += sbshc.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..a4726f8
--- /dev/null
+++ b/drivers/acpi/quickstart.c
@@ -0,0 +1,418 @@
+/*
+ * 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>
+
+MODULE_AUTHOR("Angelo Arrifano");
+MODULE_DESCRIPTION("ACPI Direct App Launch driver");
+MODULE_LICENSE("GPL");
+
+static int enable_runtime_btns;
+module_param(enable_runtime_btns, int, 0);
+MODULE_PARM_DESC(enable_runtime_btns,
+ "Enable reporting of runtime button presses (hotkeys).\n");
+
+#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,
+};
+
+/*
+ * 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,
+ }
+};
+
+/*
+ * 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;
+}
+
+/* ACPI Driver functions */
+static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct quickstart_acpi *quickstart = data;
+
+ if (!quickstart)
+ return;
+
+ /* There will be two events:
+ * 0x02 - A quickstart button was pressed while device was off/sleeping.
+ * 0x08 - A quickstart button was pressed while device was up. */
+ if((event|0x02) == event){
+ quickstart_data.pressed = quickstart->btn;
+ printk("quickstart: Quickbutton %s pressed.\n",
+ acpi_device_bid(quickstart->device));
+ }
+
+ if(enable_runtime_btns && (event|0x08) == event){
+ printk("quickstart: Hotkey %s pressed.\n",
+ acpi_device_bid(quickstart->device));
+ }
+
+ return;
+}
+
+static void quickstart_acpi_raise_notify(struct quickstart_acpi *quickstart)
+{
+ acpi_status status;
+
+ /* TODO:
+ * We should receive a buffer telling the kind of button,
+ * eg: dvd, printer, www, ...
+ * but we dont care about it now. The important is to trigger
+ * pending notify events (The ones before booting). */
+ status = acpi_evaluate_object(quickstart->device->handle,
+ "GHID", NULL, NULL);
+ if(ACPI_FAILURE(status))
+ printk("quickstart: Warning: GHID method failed, events of pressed buttons may have been lost.\n");
+
+ 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);
+ acpi_driver_data(device) = 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_raise_notify(quickstart);
+
+ 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);
+
+ 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;
+
+ /* ACPI Check */
+ if(acpi_disabled)
+ return -ENODEV;
+
+ /* ACPI driver register */
+ status = acpi_bus_register_driver(&quickstart_acpi_driver);
+ if (!quickstart_data.btn_lst || 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;
+
+ printk("quickstart: ACPI Direct App Launch ver %s\n", QUICKSTART_VERSION);
+ if(enable_runtime_btns)
+ printk("quickstart: Runtime button reporting is enabled.");
+
+ return 0;
+
+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);
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-03-14 15:17 [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32) Ângelo Miguel Arrifano
@ 2008-03-25 6:59 ` Zhang, Rui
2008-03-26 17:51 ` Ângelo Miguel Arrifano
0 siblings, 1 reply; 18+ messages in thread
From: Zhang, Rui @ 2008-03-25 6:59 UTC (permalink / raw)
To: Ângelo Miguel Arrifano; +Cc: linux-acpi
Hi, Angelo,
On Fri, 2008-03-14 at 23:17 +0800, Ângelo Miguel Arrifano wrote:
> Here is the patch made from the today linux-acpi tree.
>
> Thanks,
> Angelo Arrifano
we'd better add the change log here.
Some introductions about PNP0C32 device would be great.
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index f688c21..fb096ee 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -196,6 +196,14 @@ config ACPI_THERMAL
> recommended that this option be enabled, as your
> processor(s)
> may be damaged without it.
>
> +config ACPI_QUICKSTART
> + tristate "Quickstart"
> + default y
> + help
> + This driver add support for ACPI Direct Application Launch
> + also known as Hotstart(TM). Say yes here to have a entry in
> + sysfs telling which button was used to turn on the system.
> +
> config ACPI_NUMA
> bool "NUMA support"
> depends on NUMA
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index f29812a..badb0a6 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -62,3 +62,4 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) +=
> acpi_memhotplug.o
> obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
> obj-$(CONFIG_ACPI_SBS) += sbs.o
> obj-$(CONFIG_ACPI_SBS) += sbshc.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..a4726f8
> --- /dev/null
> +++ b/drivers/acpi/quickstart.c
> @@ -0,0 +1,418 @@
> +/*
> + * 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>
> +
> +MODULE_AUTHOR("Angelo Arrifano");
> +MODULE_DESCRIPTION("ACPI Direct App Launch driver");
> +MODULE_LICENSE("GPL");
> +
> +static int enable_runtime_btns;
> +module_param(enable_runtime_btns, int, 0);
> +MODULE_PARM_DESC(enable_runtime_btns,
> + "Enable reporting of runtime button presses
> (hotkeys).\n");
"enable_runtime_btns" is useless in this patch.
> +
> +#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,
> +};
> +
> +/*
> + * 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,
> + }
> +};
> +
> +/*
> + * 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;
> +}
> +
> +/* ACPI Driver functions */
> +static void quickstart_acpi_notify(acpi_handle handle, u32 event,
> void *data)
> +{
> + struct quickstart_acpi *quickstart = data;
> +
> + if (!quickstart)
> + return;
> +
> + /* There will be two events:
> + * 0x02 - A quickstart button was pressed while device was
> off/sleeping.
> + * 0x08 - A quickstart button was pressed while device was up.
> */
> + if((event|0x02) == event){
This is wrong.
If only two events are supported, it should be either 0x02 or 0x08.
Checking bit 1 doesn't make sense here.
> + quickstart_data.pressed = quickstart->btn;
> + printk("quickstart: Quickbutton %s pressed.\n",
> +
> acpi_device_bid(quickstart->device));
> + }
> +
> + if(enable_runtime_btns && (event|0x08) == event){
...
> + printk("quickstart: Hotkey %s pressed.\n",
> +
> acpi_device_bid(quickstart->device));
> + }
> +
>
> + return;
> +}
> +
at least we should export a notification to user space in the notify
handler.
> +static void quickstart_acpi_raise_notify(struct quickstart_acpi
> *quickstart)
> +{
> + acpi_status status;
> +
> + /* TODO:
> + * We should receive a buffer telling the kind of button,
> + * eg: dvd, printer, www, ...
> + * but we dont care about it now. The important is to trigger
> + * pending notify events (The ones before booting). */
> + status = acpi_evaluate_object(quickstart->device->handle,
> + "GHID", NULL, NULL);
It's wrong as GHID returns a buffer.
> + if(ACPI_FAILURE(status))
> + printk("quickstart: Warning: GHID method failed,
> events of pressed buttons may have been lost.\n");
> +
> + 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);
> + acpi_driver_data(device) = 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_raise_notify(quickstart);
> +
> + 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);
> +
> + 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;
> +
> + /* ACPI Check */
> + if(acpi_disabled)
> + return -ENODEV;
> +
> + /* ACPI driver register */
> + status = acpi_bus_register_driver(&quickstart_acpi_driver);
> + if (!quickstart_data.btn_lst || status < 0)
> + return -ENODEV;
> +
we should not register platform devices and sys attributes if no PNP0C32
device is available.
A simple way is to set a flag in the acpi driver's .add method which
means PNP0C32 device is found.
And return -ENODEV if the flag is not set after
acpi_bus_register_driver.
> + /* 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);
kobject (f7808880): tried to init an initialized object, something is
seriously wrong.
Pid: 1, comm: swapper Not tainted 2.6.25-rc6 #1
[<c04dad4f>] kobject_init+0x29/0x53
[<c05475fc>] device_initialize+0x1b/0x8b
[<c054ab62>] platform_device_register+0xb/0x13
[<c073dd50>] quickstart_init+0x5d/0xff
[<c0725427>] kernel_init+0x12b/0x265
[<c041eb8d>] schedule_tail+0x16/0x43
[<c040481e>] ret_from_fork+0x6/0x1c
[<c07252fc>] kernel_init+0x0/0x265
[<c07252fc>] kernel_init+0x0/0x265
[<c0405523>] kernel_thread_helper+0x7/0x10
=======================
quickstart: ACPI Direct App Launch ver 1.00
platform_device_add should be called here.
I suspect the patch is not well tested.
> + 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;
> +
> + printk("quickstart: ACPI Direct App Launch ver %s\n",
> QUICKSTART_VERSION);
> + if(enable_runtime_btns)
> + printk("quickstart: Runtime button reporting is
> enabled.");
> +
> + return 0;
> +
> +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);
There are some coding style problems.
Please run checkpatch before submitting the patch.
thanks,
rui
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-03-25 6:59 ` Zhang, Rui
@ 2008-03-26 17:51 ` Ângelo Miguel Arrifano
2008-03-27 2:30 ` Shaohua Li
0 siblings, 1 reply; 18+ messages in thread
From: Ângelo Miguel Arrifano @ 2008-03-26 17:51 UTC (permalink / raw)
To: Zhang, Rui; +Cc: linux-acpi
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On Tue, 25 Mar 2008 14:59:33 +0800
"Zhang, Rui" <rui.zhang@intel.com> wrote:
> Hi, Angelo,
>
> On Fri, 2008-03-14 at 23:17 +0800, Ângelo Miguel Arrifano wrote:
> > Here is the patch made from the today linux-acpi tree.
> >
> > Thanks,
> > Angelo Arrifano
> we'd better add the change log here.
> Some introductions about PNP0C32 device would be great.
Documentation (from README)
- -----------------------------------------------------------------
**********************************************************
* quickstart.c - ACPI Direct App Launch Driver for Linux *
* Vista(TM) calls this Hotstart(TM) *
* http://quickstart.sourceforge.net *
**********************************************************
WHAT IS IT?
<<The Windows Vista(TM) operating system provides built-in support
for a fast system startup experience that boots or resumes directly
into media or other applications.
This support, called direct application launch, is possible on PCs
that are running Windows Vista by making simple changes to platform
firmware and underlying platform wake circuitry.>>
* With the introduction of Vista Microsoft launched a new ACPI
?specification? to allow computers in sleep/off states to boot
directly into multimedia applications by only pressing buttons.
* This driver provides support to these devices allowing userspace
scripts to launch multimedia applications based on which button
was pressed.
HOW IT WORKS:
* When the system boots, the driver receives an ACPI event telling
which button was used to power the system on. Then, the driver exports
this information to sysfs allowing userspace scripts to know the
button name. This also applies to memory suspend and other power
saving states.
EXAMPLE:
* File buttons shows a list of supported hot buttons.
$ cat /sys/devices/platform/quickstart/buttons
QBTN
DBTN
MUBN
PIBN
WEBN
LVBN
VOBN
* File pressed_button shows the hot button name used to power/resume the system.
You can also write "none" to it to reset.
$ cat /sys/devices/platform/quickstart/pressed_button
none
WHAT FOR?
* Mobile and Media Center Linux distributors could use this to enrich
their linux experience.
* It's easy to make an alternate init script that checks if some button
was pressed and launch the appropriate application without having to
load the entire system.
REFERENCES
* http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/DirAppLaunch_Vista.doc
CHANGELOG
- -----------------------------------------------------------------
* version 1.00-r1 2008/03/06
- Fixed Makefile for linux-2.6.24
* version 1.00 2008/03/03
- Little changes to support linux-2.6.23 and newer.
- Added example autostart scripts.
- Going stable, version bump.
* version 0.04 2007/11/17
- Added reporting of runtime key presses (hotkeys) for testing.
* version 0.03 2007/11/13
- Method GHID is now called under its device scope.
- Code cleanup.
* version 0.02 2007/11/12
- Project renamed to quickstart to prevent conflict with Microsoft
trademark Hotstart(TM).
- Removed procfs support since /proc/acpi will be removed from kernel soon.
- Added sysfs support.
- Button states are now unified into a single attribute file which displays
the button name used to power the system on.
- Added attribute file to show all suported buttons.
- Code cleanups.
* version 0.01 2007/11/10
- Detects button devices and creates proc entries to each device.
- Proc entries can be written.
- Workaround to raise device
PATCH
- -----------------------------------------------------------------
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index f688c21..fb096ee 100644
- --- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -196,6 +196,14 @@ config ACPI_THERMAL
recommended that this option be enabled, as your processor(s)
may be damaged without it.
+config ACPI_QUICKSTART
+ tristate "Quickstart"
+ default y
+ help
+ This driver add support for ACPI Direct Application Launch
+ also known as Hotstart(TM). Say yes here to have a entry in
+ sysfs telling which button was used to turn on the system.
+
config ACPI_NUMA
bool "NUMA support"
depends on NUMA
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index f29812a..badb0a6 100644
- --- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -62,3 +62,4 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += sbs.o
obj-$(CONFIG_ACPI_SBS) += sbshc.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..05c98f2
- --- /dev/null
+++ b/drivers/acpi/quickstart.c
@@ -0,0 +1,416 @@
+/*
+ * 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.01"
+
+#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>
+
+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
+
+/* There will be two events:
+ * 0x02 - A hot button was pressed while device was off/sleeping.
+ * 0x08 - A hot button was pressed while device was up. */
+#define QUICKSTART_EVENT_WAKE 0x02
+#define QUICKSTART_EVENT_RUNTIME 0x80
+
+struct quickstart_btn {
+ char *name;
+ struct quickstart_btn *next;
+};
+
+static struct quickstart_driver_data {
+ struct quickstart_btn *btn_lst;
+ struct quickstart_btn *pressed;
+} quickstart_data = {
+ .btn_lst = NULL,
+ .pressed = NULL,
+};
+
+/*
+ * ACPI driver Structs
+ */
+
+struct quickstart_acpi {
+ struct acpi_device *device;
+ struct quickstart_btn *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,
+ }
+};
+
+/*
+ * 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 *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 **data)
+{
+ struct quickstart_btn **ptr = &quickstart_data.btn_lst;
+
+ while (*ptr)
+ ptr = &((*ptr)->next);
+
+ *ptr = kzalloc(sizeof(struct quickstart_btn), GFP_KERNEL);
+ if (!*ptr) {
+ *data = NULL;
+ return(-ENOMEM);
+ }
+ *data = *ptr;
+
+ return 0;
+}
+
+static void quickstart_btnlst_free(void)
+{
+ struct quickstart_btn *ptr = quickstart_data.btn_lst;
+ struct quickstart_btn *lptr = NULL;
+
+ if (!ptr)
+ return;
+
+ while (ptr) {
+ lptr = ptr;
+ ptr = ptr->next;
+ kfree(lptr->name);
+ kfree(lptr);
+ }
+
+ return;
+}
+
+/* ACPI Driver functions */
+static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct quickstart_acpi *quickstart = data;
+
+ if (!quickstart)
+ return;
+
+ if (event == QUICKSTART_EVENT_WAKE) {
+ quickstart_data.pressed = quickstart->btn;
+ printk(KERN_ERR "quickstart: Quickbutton %s pressed.\n",
+ acpi_device_bid(quickstart->device));
+ } else if (event == QUICKSTART_EVENT_RUNTIME) {
+ printk(KERN_ERR "quickstart: Runtime button %s pressed.\n\t"
+ "please report on linux-acpi@vger.kernel.org",
+ acpi_device_bid(quickstart->device));
+ }
+
+ return;
+}
+
+static void quickstart_acpi_raise_notify(struct quickstart_acpi *quickstart)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ if (!quickstart)
+ return;
+
+ /* This returns a buffer telling the button usage ID (useless),
+ * we dont care about it now. The important is to trigger
+ * pending notify events (The ones before booting). */
+ status = acpi_evaluate_object(quickstart->device->handle,
+ "GHID", NULL, &buffer);
+ if (ACPI_FAILURE(status) || !buffer.pointer) {
+ printk(KERN_ERR "quickstart: %s GHID method failed.\n",
+ quickstart->btn->name);
+ return;
+ }
+
+ kfree(buffer.pointer);
+ 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);
+ acpi_driver_data(device) = 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(KERN_ERR "quickstart: Notify handler install error\n");
+ ret = -ENODEV;
+ goto fail_installnotify;
+ }
+
+ quickstart_acpi_raise_notify(quickstart);
+
+ 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(KERN_ERR "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);
+
+ 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;
+
+ /* ACPI Check */
+ if (acpi_disabled)
+ return -ENODEV;
+
+ /* ACPI driver register */
+ status = acpi_bus_register_driver(&quickstart_acpi_driver);
+ if (!quickstart_data.btn_lst || 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;
+
+ printk(KERN_ERR "quickstart: ACPI Direct App Launch ver %s\n",
+ QUICKSTART_VERSION);
+
+ return 0;
+
+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);
>
> > diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> > index f688c21..fb096ee 100644
> > --- a/drivers/acpi/Kconfig
> > +++ b/drivers/acpi/Kconfig
> > @@ -196,6 +196,14 @@ config ACPI_THERMAL
> > recommended that this option be enabled, as your
> > processor(s)
> > may be damaged without it.
> >
> > +config ACPI_QUICKSTART
> > + tristate "Quickstart"
> > + default y
> > + help
> > + This driver add support for ACPI Direct Application Launch
> > + also known as Hotstart(TM). Say yes here to have a entry in
> > + sysfs telling which button was used to turn on the system.
> > +
> > config ACPI_NUMA
> > bool "NUMA support"
> > depends on NUMA
> > diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> > index f29812a..badb0a6 100644
> > --- a/drivers/acpi/Makefile
> > +++ b/drivers/acpi/Makefile
> > @@ -62,3 +62,4 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) +=
> > acpi_memhotplug.o
> > obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
> > obj-$(CONFIG_ACPI_SBS) += sbs.o
> > obj-$(CONFIG_ACPI_SBS) += sbshc.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..a4726f8
> > --- /dev/null
> > +++ b/drivers/acpi/quickstart.c
> > @@ -0,0 +1,418 @@
> > +/*
> > + * 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>
> > +
> > +MODULE_AUTHOR("Angelo Arrifano");
> > +MODULE_DESCRIPTION("ACPI Direct App Launch driver");
> > +MODULE_LICENSE("GPL");
> > +
> > +static int enable_runtime_btns;
> > +module_param(enable_runtime_btns, int, 0);
> > +MODULE_PARM_DESC(enable_runtime_btns,
> > + "Enable reporting of runtime button presses
> > (hotkeys).\n");
> "enable_runtime_btns" is useless in this patch.
FIXED on the patch above
>
> > +
> > +#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,
> > +};
> > +
> > +/*
> > + * 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,
> > + }
> > +};
> > +
> > +/*
> > + * 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;
> > +}
> > +
> > +/* ACPI Driver functions */
> > +static void quickstart_acpi_notify(acpi_handle handle, u32 event,
> > void *data)
> > +{
> > + struct quickstart_acpi *quickstart = data;
> > +
> > + if (!quickstart)
> > + return;
> > +
> > + /* There will be two events:
> > + * 0x02 - A quickstart button was pressed while device was
> > off/sleeping.
> > + * 0x08 - A quickstart button was pressed while device was up.
> > */
> > + if((event|0x02) == event){
> This is wrong.
> If only two events are supported, it should be either 0x02 or 0x08.
> Checking bit 1 doesn't make sense here.
FIXED on the patch above
>
> > + quickstart_data.pressed = quickstart->btn;
> > + printk("quickstart: Quickbutton %s pressed.\n",
> > +
> > acpi_device_bid(quickstart->device));
> > + }
> > +
> > + if(enable_runtime_btns && (event|0x08) == event){
> ...
>
> > + printk("quickstart: Hotkey %s pressed.\n",
> > +
> > acpi_device_bid(quickstart->device));
> > + }
> > +
> >
> > + return;
> > +}
> > +
> at least we should export a notification to user space in the notify
> handler.
According to the Microsoft paper, runtime hot button reporting is optional. And
my laptop doesn't report them, so I don't have a way to test this..
>
> > +static void quickstart_acpi_raise_notify(struct quickstart_acpi
> > *quickstart)
> > +{
> > + acpi_status status;
> > +
> > + /* TODO:
> > + * We should receive a buffer telling the kind of button,
> > + * eg: dvd, printer, www, ...
> > + * but we dont care about it now. The important is to trigger
> > + * pending notify events (The ones before booting). */
> > + status = acpi_evaluate_object(quickstart->device->handle,
> > + "GHID", NULL, NULL);
> It's wrong as GHID returns a buffer.
FIXED on the patch above
The returned buffer is a BYTE/WORD/DWORD with a decimal number telling the button
usage ID.
IMHO, the button usage ID is useless.
>
> > + if(ACPI_FAILURE(status))
> > + printk("quickstart: Warning: GHID method failed,
> > events of pressed buttons may have been lost.\n");
> > +
> > + 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);
> > + acpi_driver_data(device) = 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_raise_notify(quickstart);
> > +
> > + 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);
> > +
> > + 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;
> > +
> > + /* ACPI Check */
> > + if(acpi_disabled)
> > + return -ENODEV;
> > +
> > + /* ACPI driver register */
> > + status = acpi_bus_register_driver(&quickstart_acpi_driver);
> > + if (!quickstart_data.btn_lst || status < 0)
> > + return -ENODEV;
> > +
> we should not register platform devices and sys attributes if no PNP0C32
> device is available.
> A simple way is to set a flag in the acpi driver's .add method which
> means PNP0C32 device is found.
> And return -ENODEV if the flag is not set after
> acpi_bus_register_driver.
That is exactly whats going on here.
acpi_bus_register_driver() is called with quickstart_data.btn_lst=NULL . If no
devices are detected, the quickstart_data.btn_lst is not touched and continues
to be null.
So we can consider quickstart_data.btn_lst as the flag you were talking.
>
> > + /* 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);
> kobject (f7808880): tried to init an initialized object, something is
> seriously wrong.
> Pid: 1, comm: swapper Not tainted 2.6.25-rc6 #1
> [<c04dad4f>] kobject_init+0x29/0x53
> [<c05475fc>] device_initialize+0x1b/0x8b
> [<c054ab62>] platform_device_register+0xb/0x13
> [<c073dd50>] quickstart_init+0x5d/0xff
> [<c0725427>] kernel_init+0x12b/0x265
> [<c041eb8d>] schedule_tail+0x16/0x43
> [<c040481e>] ret_from_fork+0x6/0x1c
> [<c07252fc>] kernel_init+0x0/0x265
> [<c07252fc>] kernel_init+0x0/0x265
> [<c0405523>] kernel_thread_helper+0x7/0x10
> =======================
> quickstart: ACPI Direct App Launch ver 1.00
>
> platform_device_add should be called here.
> I suspect the patch is not well tested.
I don't understand this one.
pf_device is initialized twice? How?
>
> > + 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;
> > +
> > + printk("quickstart: ACPI Direct App Launch ver %s\n",
> > QUICKSTART_VERSION);
> > + if(enable_runtime_btns)
> > + printk("quickstart: Runtime button reporting is
> > enabled.");
> > +
> > + return 0;
> > +
> > +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);
> There are some coding style problems.
> Please run checkpatch before submitting the patch.
FIXED on the patch above
>
> thanks,
> rui
>
>
Thanks,
- --
Angelo Arrifano AKA MiKNiX
CSE Student at UBI, Portugal
Gentoo Linux AMD64 Arch Tester
Linwizard Developer
http://miknix.homelinux.com
PGP Pubkey 0x3D92BB0B
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.7 (GNU/Linux)
iD8DBQFH6o0rNahyoD2SuwsRAvhDAJ9NJoi5c5tEOHaj+wlRi9S4lEhHrwCfdyhr
IAShcu6win9qeoSrhi6lYc8=
=7Uap
-----END PGP SIGNATURE-----
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-03-26 17:51 ` Ângelo Miguel Arrifano
@ 2008-03-27 2:30 ` Shaohua Li
2008-03-27 16:03 ` Ângelo Miguel Arrifano
0 siblings, 1 reply; 18+ messages in thread
From: Shaohua Li @ 2008-03-27 2:30 UTC (permalink / raw)
To: Ângelo Miguel Arrifano; +Cc: Zhang, Rui, linux-acpi
On Thu, 2008-03-27 at 01:51 +0800, Ângelo Miguel Arrifano wrote:
> PATCH
> - -----------------------------------------------------------------
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index f688c21..fb096ee 100644
> - --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -196,6 +196,14 @@ config ACPI_THERMAL
> recommended that this option be enabled, as your
> processor(s)
> may be damaged without it.
>
> +config ACPI_QUICKSTART
> + tristate "Quickstart"
> + default y
default m?
> +
> +static struct quickstart_driver_data {
> + struct quickstart_btn *btn_lst;
> + struct quickstart_btn *pressed;
> +} quickstart_data = {
> + .btn_lst = NULL,
> + .pressed = NULL,
> +};
They are NULL, you don't need initialize them.
> + * 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);
this file can be changed by non-root?
> +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 *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);
we could simplify:
snprintf(buf + count, PAGE_SIZE -count, "%s\n", ptr->name);
> + }
> + ptr = ptr->next;
> + }
> +
> + return count;
> +}
> +
> +
> +/* ACPI Driver functions */
> +static void quickstart_acpi_notify(acpi_handle handle, u32 event,
> void *data)
> +{
> + struct quickstart_acpi *quickstart = data;
> +
> + if (!quickstart)
> + return;
> +
> + if (event == QUICKSTART_EVENT_WAKE) {
> + quickstart_data.pressed = quickstart->btn;
> + printk(KERN_ERR "quickstart: Quickbutton %s
> pressed.\n",
> +
> acpi_device_bid(quickstart->device));
> + } else if (event == QUICKSTART_EVENT_RUNTIME) {
> + printk(KERN_ERR "quickstart: Runtime button %s
> pressed.\n\t"
> + "please report on linux-acpi@vger.kernel.org",
> +
> acpi_device_bid(quickstart->device));
> + }
Please remove above printks. they are misleading, which isn't an error.
please send an ACPI event to userspace in the notify, we need it for
runtime.
> + return;
> +}
> +
> +static void quickstart_acpi_raise_notify(struct quickstart_acpi
> *quickstart)
> +{
> + acpi_status status;
> + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +
> + if (!quickstart)
> + return;
> +
> + /* This returns a buffer telling the button usage ID
> (useless),
> + * we dont care about it now. The important is to trigger
> + * pending notify events (The ones before booting). */
> + status = acpi_evaluate_object(quickstart->device->handle,
> + "GHID", NULL, &buffer);
> + if (ACPI_FAILURE(status) || !buffer.pointer) {
> + printk(KERN_ERR "quickstart: %s GHID method
> failed.\n",
> + quickstart->btn->name);
> + return;
> + }
I'd suggest the GHID info should be exported to sysfs too. It's hard to
judge what a button is just per its name. You know it but an
inexperienced user doesn't.
> + kfree(buffer.pointer);
> + return;
> +}
> +
> +
> +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);
> + acpi_driver_data(device) = 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(KERN_ERR "quickstart: Notify handler install
> error\n");
> + ret = -ENODEV;
> + goto fail_installnotify;
memory is freed but it's still in the list.
Thanks,
Shaohua
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-03-27 2:30 ` Shaohua Li
@ 2008-03-27 16:03 ` Ângelo Miguel Arrifano
2008-03-28 1:36 ` Shaohua Li
0 siblings, 1 reply; 18+ messages in thread
From: Ângelo Miguel Arrifano @ 2008-03-27 16:03 UTC (permalink / raw)
To: Shaohua Li; +Cc: rui.zhang, linux-acpi
On Thu, 27 Mar 2008 10:30:13 +0800
Shaohua Li <shaohua.li@intel.com> wrote:
>
> On Thu, 2008-03-27 at 01:51 +0800, Ângelo Miguel Arrifano wrote:
> > PATCH
> > - -----------------------------------------------------------------
> > diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> > index f688c21..fb096ee 100644
> > - --- a/drivers/acpi/Kconfig
> > +++ b/drivers/acpi/Kconfig
> > @@ -196,6 +196,14 @@ config ACPI_THERMAL
> > recommended that this option be enabled, as your
> > processor(s)
> > may be damaged without it.
> >
> > +config ACPI_QUICKSTART
> > + tristate "Quickstart"
> > + default y
> default m?
>
>
> > +
> > +static struct quickstart_driver_data {
> > + struct quickstart_btn *btn_lst;
> > + struct quickstart_btn *pressed;
> > +} quickstart_data = {
> > + .btn_lst = NULL,
> > + .pressed = NULL,
> > +};
> They are NULL, you don't need initialize them.
>
>
> > + * 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);
> this file can be changed by non-root?
The only thing that writing to this file does is clearing the
pressed button.
Is it a bad idea that can be changed by non-root?
>
>
> > +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 *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);
> we could simplify:
> snprintf(buf + count, PAGE_SIZE -count, "%s\n", ptr->name);
:)
> > + }
> > + ptr = ptr->next;
> > + }
> > +
> > + return count;
> > +}
>
> > +
>
> > +
> > +/* ACPI Driver functions */
> > +static void quickstart_acpi_notify(acpi_handle handle, u32 event,
> > void *data)
> > +{
> > + struct quickstart_acpi *quickstart = data;
> > +
> > + if (!quickstart)
> > + return;
> > +
> > + if (event == QUICKSTART_EVENT_WAKE) {
> > + quickstart_data.pressed = quickstart->btn;
> > + printk(KERN_ERR "quickstart: Quickbutton %s
> > pressed.\n",
> > +
> > acpi_device_bid(quickstart->device));
> > + } else if (event == QUICKSTART_EVENT_RUNTIME) {
> > + printk(KERN_ERR "quickstart: Runtime button %s
> > pressed.\n\t"
> > + "please report on linux-acpi@vger.kernel.org",
> > +
> > acpi_device_bid(quickstart->device));
> > + }
> Please remove above printks. they are misleading, which isn't an error.
> please send an ACPI event to userspace in the notify, we need it for
> runtime.
According to the Microsoft paper, runtime hot button reporting is optional.
My laptop doesn't report them and on the SF.net project page there was no
reports of people with hardware supporting this.
Sorry, I don't have a way to test this..
>
> > + return;
> > +}
> > +
> > +static void quickstart_acpi_raise_notify(struct quickstart_acpi
> > *quickstart)
> > +{
> > + acpi_status status;
> > + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> > +
> > + if (!quickstart)
> > + return;
> > +
> > + /* This returns a buffer telling the button usage ID
> > (useless),
> > + * we dont care about it now. The important is to trigger
> > + * pending notify events (The ones before booting). */
> > + status = acpi_evaluate_object(quickstart->device->handle,
> > + "GHID", NULL, &buffer);
> > + if (ACPI_FAILURE(status) || !buffer.pointer) {
> > + printk(KERN_ERR "quickstart: %s GHID method
> > failed.\n",
> > + quickstart->btn->name);
> > + return;
> > + }
> I'd suggest the GHID info should be exported to sysfs too. It's hard to
> judge what a button is just per its name. You know it but an
> inexperienced user doesn't.
I also would like to have a more descriptive information about the button but
the returned buffer is a BYTE/WORD/DWORD with a decimal number telling the button
usage ID.
Looking at my DSDT piece of code:
Method (GHID, 0, NotSerialized)
{
If (LEqual (HOTB, 0x05))
{
Notify (DBTN, 0x02)
Store (0x00, HOTB)
}
Return (Buffer (0x01)
{
/* 0000 */ 0x04
})
}
IMHO, a value like 0x04 for button usageID is totally useless..
>
> > + kfree(buffer.pointer);
> > + return;
> > +}
> > +
>
> > +
> > +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);
> > + acpi_driver_data(device) = 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(KERN_ERR "quickstart: Notify handler install
> > error\n");
> > + ret = -ENODEV;
> > + goto fail_installnotify;
> memory is freed but it's still in the list.
I got it now, big mistake here.
I hope to have this fixed on the patch below
>
> Thanks,
> Shaohua
>
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index f688c21..fd65e36 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -196,6 +196,14 @@ config ACPI_THERMAL
recommended that this option be enabled, as your processor(s)
may be damaged without it.
+config ACPI_QUICKSTART
+ tristate "Quickstart"
+ default m
+ help
+ This driver add support for ACPI Direct Application Launch
+ also known as Hotstart(TM). Say yes here to have a entry in
+ sysfs telling which button was used to turn on the system.
+
config ACPI_NUMA
bool "NUMA support"
depends on NUMA
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index f29812a..badb0a6 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -62,3 +62,4 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += sbs.o
obj-$(CONFIG_ACPI_SBS) += sbshc.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..b8ebb93
--- /dev/null
+++ b/drivers/acpi/quickstart.c
@@ -0,0 +1,427 @@
+/*
+ * 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.01"
+
+#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>
+
+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
+
+/* There will be two events:
+ * 0x02 - A hot button was pressed while device was off/sleeping.
+ * 0x08 - A hot button was pressed while device was up. */
+#define QUICKSTART_EVENT_WAKE 0x02
+#define QUICKSTART_EVENT_RUNTIME 0x80
+
+struct quickstart_btn {
+ char *name;
+ struct quickstart_btn *next;
+};
+
+static struct quickstart_driver_data {
+ struct quickstart_btn *btn_lst;
+ struct quickstart_btn *pressed;
+} quickstart_data;
+
+/*
+ * ACPI driver Structs
+ */
+
+struct quickstart_acpi {
+ struct acpi_device *device;
+ struct quickstart_btn *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,
+ }
+};
+
+/*
+ * Platform driver functions
+ */
+static ssize_t buttons_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int count = 0;
+ struct quickstart_btn *ptr = quickstart_data.btn_lst;
+
+ if (!ptr)
+ return snprintf(buf, PAGE_SIZE, "none");
+
+ while (ptr && (count < PAGE_SIZE)) {
+ if (ptr->name) {
+ count += snprintf(buf + count,
+ PAGE_SIZE - count,
+ "%s\n", ptr->name);
+ }
+ 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 **data)
+{
+ struct quickstart_btn **ptr = &quickstart_data.btn_lst;
+
+ while (*ptr)
+ ptr = &((*ptr)->next);
+
+ *ptr = kzalloc(sizeof(struct quickstart_btn), GFP_KERNEL);
+ if (!*ptr) {
+ *data = NULL;
+ return(-ENOMEM);
+ }
+ *data = *ptr;
+
+ return 0;
+}
+
+static void quickstart_btnlst_del(struct quickstart_btn *data)
+{
+ struct quickstart_btn **ptr = &quickstart_data.btn_lst;
+
+ if (!data)
+ return;
+
+ while (*ptr) {
+ if (*ptr == data) {
+ *ptr = (*ptr)->next;
+ kfree(data);
+ return;
+ }
+ ptr = &((*ptr)->next);
+ }
+
+ return;
+}
+
+static void quickstart_btnlst_free(void)
+{
+ struct quickstart_btn *ptr = quickstart_data.btn_lst;
+ struct quickstart_btn *lptr = NULL;
+
+ while (ptr) {
+ lptr = ptr;
+ ptr = ptr->next;
+ kfree(lptr->name);
+ kfree(lptr);
+ }
+
+ return;
+}
+
+/* ACPI Driver functions */
+static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct quickstart_acpi *quickstart = data;
+
+ if (!quickstart)
+ return;
+
+ if (event == QUICKSTART_EVENT_WAKE)
+ quickstart_data.pressed = quickstart->btn;
+
+ return;
+}
+
+static void quickstart_acpi_raise_notify(struct quickstart_acpi *quickstart)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ if (!quickstart)
+ return;
+
+ /* This returns a buffer telling the button usage ID (useless),
+ * we dont care about it now. The important is to trigger
+ * pending notify events (The ones before booting). */
+ status = acpi_evaluate_object(quickstart->device->handle,
+ "GHID", NULL, &buffer);
+ if (ACPI_FAILURE(status) || !buffer.pointer) {
+ printk(KERN_ERR "quickstart: %s GHID method failed.\n",
+ quickstart->btn->name);
+ return;
+ }
+
+ kfree(buffer.pointer);
+ 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);
+ acpi_driver_data(device) = 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(KERN_ERR "quickstart: Notify handler install error\n");
+ ret = -ENODEV;
+ goto fail_installnotify;
+ }
+
+ quickstart_acpi_raise_notify(quickstart);
+
+ return 0;
+
+fail_installnotify:
+ quickstart_btnlst_del(quickstart->btn);
+
+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(KERN_ERR "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);
+
+ 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;
+
+ /* ACPI Check */
+ if (acpi_disabled)
+ return -ENODEV;
+
+ /* ACPI driver register */
+ status = acpi_bus_register_driver(&quickstart_acpi_driver);
+ if (status < 0)
+ return -ENODEV;
+
+ /* If existing bus with no devices */
+ if (!quickstart_data.btn_lst) {
+ ret = -ENODEV;
+ goto fail_pfdrv_reg;
+ }
+
+ /* 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;
+
+ printk(KERN_INFO "quickstart: ACPI Direct App Launch ver %s\n",
+ QUICKSTART_VERSION);
+
+ return 0;
+
+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);
Thanks all,
--
Angelo Arrifano AKA MiKNiX
CSE Student at UBI, Portugal
Gentoo Linux AMD64 Arch Tester
Linwizard Developer
http://miknix.homelinux.com
PGP Pubkey 0x3D92BB0B
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-03-27 16:03 ` Ângelo Miguel Arrifano
@ 2008-03-28 1:36 ` Shaohua Li
2008-03-28 19:39 ` Ângelo Miguel Arrifano
0 siblings, 1 reply; 18+ messages in thread
From: Shaohua Li @ 2008-03-28 1:36 UTC (permalink / raw)
To: Ângelo Miguel Arrifano; +Cc: rui.zhang, linux-acpi
On Thu, 2008-03-27 at 16:03 +0000, Ângelo Miguel Arrifano wrote:
> On Thu, 27 Mar 2008 10:30:13 +0800
> Shaohua Li <shaohua.li@intel.com> wrote:
>
> >
> > On Thu, 2008-03-27 at 01:51 +0800, Ângelo Miguel Arrifano wrote:
> > > PATCH
> > > - -----------------------------------------------------------------
> > > diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> > > index f688c21..fb096ee 100644
> > > - --- a/drivers/acpi/Kconfig
> > > +++ b/drivers/acpi/Kconfig
> > > @@ -196,6 +196,14 @@ config ACPI_THERMAL
> > > recommended that this option be enabled, as your
> > > processor(s)
> > > may be damaged without it.
> > >
> > > +config ACPI_QUICKSTART
> > > + tristate "Quickstart"
> > > + default y
> > default m?
> >
> >
> > > +
> > > +static struct quickstart_driver_data {
> > > + struct quickstart_btn *btn_lst;
> > > + struct quickstart_btn *pressed;
> > > +} quickstart_data = {
> > > + .btn_lst = NULL,
> > > + .pressed = NULL,
> > > +};
> > They are NULL, you don't need initialize them.
> >
> >
> > > + * 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);
> > this file can be changed by non-root?
>
> The only thing that writing to this file does is clearing the
> pressed button.
> Is it a bad idea that can be changed by non-root?
Just abnormal, eg. non-root can clear it but root might not read it
(though it doesn't happen in current case but possible if runtime event
support).
> > > +
> > > +/* ACPI Driver functions */
> > > +static void quickstart_acpi_notify(acpi_handle handle, u32 event,
> > > void *data)
> > > +{
> > > + struct quickstart_acpi *quickstart = data;
> > > +
> > > + if (!quickstart)
> > > + return;
> > > +
> > > + if (event == QUICKSTART_EVENT_WAKE) {
> > > + quickstart_data.pressed = quickstart->btn;
> > > + printk(KERN_ERR "quickstart: Quickbutton %s
> > > pressed.\n",
> > > +
> > > acpi_device_bid(quickstart->device));
> > > + } else if (event == QUICKSTART_EVENT_RUNTIME) {
> > > + printk(KERN_ERR "quickstart: Runtime button %s
> > > pressed.\n\t"
> > > + "please report on linux-acpi@vger.kernel.org",
> > > +
> > > acpi_device_bid(quickstart->device));
> > > + }
> > Please remove above printks. they are misleading, which isn't an error.
> > please send an ACPI event to userspace in the notify, we need it for
> > runtime.
>
> According to the Microsoft paper, runtime hot button reporting is optional.
> My laptop doesn't report them and on the SF.net project page there was no
> reports of people with hardware supporting this.
> Sorry, I don't have a way to test this..
Did you tried suspend/resume. From the doc, resume can send a
notification too. Just calling acpi event eject routines, an event eject
model can be well integrated into existing acpi daemons.
> > > + }
> > I'd suggest the GHID info should be exported to sysfs too. It's hard to
> > judge what a button is just per its name. You know it but an
> > inexperienced user doesn't.
>
> I also would like to have a more descriptive information about the button but
> the returned buffer is a BYTE/WORD/DWORD with a decimal number telling the button
> usage ID.
>
> Looking at my DSDT piece of code:
>
> Method (GHID, 0, NotSerialized)
> {
> If (LEqual (HOTB, 0x05))
> {
> Notify (DBTN, 0x02)
> Store (0x00, HOTB)
> }
>
> Return (Buffer (0x01)
> {
> /* 0000 */ 0x04
> })
> }
>
> IMHO, a value like 0x04 for button usageID is totally useless..
Ok, I got it. Maybe we need tool to help user identify what purpose a
button is, but sounds impossible till the button can trigger runtime
event.
Thanks,
Shaohua
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-03-28 1:36 ` Shaohua Li
@ 2008-03-28 19:39 ` Ângelo Miguel Arrifano
2008-08-24 16:39 ` Ângelo Miguel Arrifano
0 siblings, 1 reply; 18+ messages in thread
From: Ângelo Miguel Arrifano @ 2008-03-28 19:39 UTC (permalink / raw)
To: Shaohua Li; +Cc: rui.zhang, linux-acpi
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On Fri, 28 Mar 2008 09:36:55 +0800
Shaohua Li <shaohua.li@intel.com> wrote:
>
> On Thu, 2008-03-27 at 16:03 +0000, Ângelo Miguel Arrifano wrote:
> > On Thu, 27 Mar 2008 10:30:13 +0800
> > Shaohua Li <shaohua.li@intel.com> wrote:
> >
> > >
> > > On Thu, 2008-03-27 at 01:51 +0800, Ângelo Miguel Arrifano wrote:
> > > > PATCH
> > > > - -----------------------------------------------------------------
> > > > diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> > > > index f688c21..fb096ee 100644
> > > > - --- a/drivers/acpi/Kconfig
> > > > +++ b/drivers/acpi/Kconfig
> > > > @@ -196,6 +196,14 @@ config ACPI_THERMAL
> > > > recommended that this option be enabled, as your
> > > > processor(s)
> > > > may be damaged without it.
> > > >
> > > > +config ACPI_QUICKSTART
> > > > + tristate "Quickstart"
> > > > + default y
> > > default m?
> > >
> > >
> > > > +
> > > > +static struct quickstart_driver_data {
> > > > + struct quickstart_btn *btn_lst;
> > > > + struct quickstart_btn *pressed;
> > > > +} quickstart_data = {
> > > > + .btn_lst = NULL,
> > > > + .pressed = NULL,
> > > > +};
> > > They are NULL, you don't need initialize them.
> > >
> > >
> > > > + * 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);
> > > this file can be changed by non-root?
> >
> > The only thing that writing to this file does is clearing the
> > pressed button.
> > Is it a bad idea that can be changed by non-root?
> Just abnormal, eg. non-root can clear it but root might not read it
> (though it doesn't happen in current case but possible if runtime event
> support).
>
> > > > +
> > > > +/* ACPI Driver functions */
> > > > +static void quickstart_acpi_notify(acpi_handle handle, u32 event,
> > > > void *data)
> > > > +{
> > > > + struct quickstart_acpi *quickstart = data;
> > > > +
> > > > + if (!quickstart)
> > > > + return;
> > > > +
> > > > + if (event == QUICKSTART_EVENT_WAKE) {
> > > > + quickstart_data.pressed = quickstart->btn;
> > > > + printk(KERN_ERR "quickstart: Quickbutton %s
> > > > pressed.\n",
> > > > +
> > > > acpi_device_bid(quickstart->device));
> > > > + } else if (event == QUICKSTART_EVENT_RUNTIME) {
> > > > + printk(KERN_ERR "quickstart: Runtime button %s
> > > > pressed.\n\t"
> > > > + "please report on linux-acpi@vger.kernel.org",
> > > > +
> > > > acpi_device_bid(quickstart->device));
> > > > + }
> > > Please remove above printks. they are misleading, which isn't an error.
> > > please send an ACPI event to userspace in the notify, we need it for
> > > runtime.
> >
> > According to the Microsoft paper, runtime hot button reporting is optional.
> > My laptop doesn't report them and on the SF.net project page there was no
> > reports of people with hardware supporting this.
> > Sorry, I don't have a way to test this..
> Did you tried suspend/resume. From the doc, resume can send a
> notification too. Just calling acpi event eject routines, an event eject
> model can be well integrated into existing acpi daemons.
Yes, suspend to mem works.
When the laptop is in suspend state, if DVD button is pressed the laptop resumes
and the platform driver receives a notify. The driver then exports the
button name to the sysfs pressed_button file.
>
> > > > + }
> > > I'd suggest the GHID info should be exported to sysfs too. It's hard to
> > > judge what a button is just per its name. You know it but an
> > > inexperienced user doesn't.
> >
> > I also would like to have a more descriptive information about the button but
> > the returned buffer is a BYTE/WORD/DWORD with a decimal number telling the button
> > usage ID.
> >
> > Looking at my DSDT piece of code:
> >
> > Method (GHID, 0, NotSerialized)
> > {
> > If (LEqual (HOTB, 0x05))
> > {
> > Notify (DBTN, 0x02)
> > Store (0x00, HOTB)
> > }
> >
> > Return (Buffer (0x01)
> > {
> > /* 0000 */ 0x04
> > })
> > }
> >
> > IMHO, a value like 0x04 for button usageID is totally useless..
> Ok, I got it. Maybe we need tool to help user identify what purpose a
> button is, but sounds impossible till the button can trigger runtime
> event.
I've noticed that HP laptops have the same names for button
devices (at least dv6k, dv8k and tx series). Maybe other vendors do this as well?
If this holds true, maybe building a vendor table for getting
button name -> description correspondence? .. just an idea ..
>
> Thanks,
> Shaohua
>
Thanks all,
- --
Angelo Arrifano AKA MiKNiX
CSE Student at UBI, Portugal
Gentoo Linux AMD64 Arch Tester
Linwizard Developer
http://miknix.homelinux.com
PGP Pubkey 0x3D92BB0B
- - -
Computers are like air conditioners. Both stop working, if you open windows.
-- Adam Heath
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.7 (GNU/Linux)
iD8DBQFH7UlnNahyoD2SuwsRApPtAJ9GcFwvwuAgCyCnS87XaGI+nHAbYgCeM65K
lvOIGf01TPFzAgqFbSoFJYY=
=vrGR
-----END PGP SIGNATURE-----
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-03-28 19:39 ` Ângelo Miguel Arrifano
@ 2008-08-24 16:39 ` Ângelo Miguel Arrifano
2008-08-25 1:29 ` Zhang Rui
0 siblings, 1 reply; 18+ messages in thread
From: Ângelo Miguel Arrifano @ 2008-08-24 16:39 UTC (permalink / raw)
To: Shaohua Li, rui.zhang; +Cc: linux-acpi
On Fri, 28 Mar 2008 19:39:19 +0000
Ângelo Miguel Arrifano <miknix@gmail.com> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On Fri, 28 Mar 2008 09:36:55 +0800
> Shaohua Li <shaohua.li@intel.com> wrote:
>
> >
> > On Thu, 2008-03-27 at 16:03 +0000, Ângelo Miguel Arrifano wrote:
> > > On Thu, 27 Mar 2008 10:30:13 +0800
> > > Shaohua Li <shaohua.li@intel.com> wrote:
> > >
> > > >
> > > > On Thu, 2008-03-27 at 01:51 +0800, Ângelo Miguel Arrifano wrote:
> > > > > PATCH
> > > > > - -----------------------------------------------------------------
> > > > > diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> > > > > index f688c21..fb096ee 100644
> > > > > - --- a/drivers/acpi/Kconfig
> > > > > +++ b/drivers/acpi/Kconfig
> > > > > @@ -196,6 +196,14 @@ config ACPI_THERMAL
> > > > > recommended that this option be enabled, as your
> > > > > processor(s)
> > > > > may be damaged without it.
> > > > >
> > > > > +config ACPI_QUICKSTART
> > > > > + tristate "Quickstart"
> > > > > + default y
> > > > default m?
> > > >
> > > >
> > > > > +
> > > > > +static struct quickstart_driver_data {
> > > > > + struct quickstart_btn *btn_lst;
> > > > > + struct quickstart_btn *pressed;
> > > > > +} quickstart_data = {
> > > > > + .btn_lst = NULL,
> > > > > + .pressed = NULL,
> > > > > +};
> > > > They are NULL, you don't need initialize them.
> > > >
> > > >
> > > > > + * 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);
> > > > this file can be changed by non-root?
> > >
> > > The only thing that writing to this file does is clearing the
> > > pressed button.
> > > Is it a bad idea that can be changed by non-root?
> > Just abnormal, eg. non-root can clear it but root might not read it
> > (though it doesn't happen in current case but possible if runtime event
> > support).
> >
> > > > > +
> > > > > +/* ACPI Driver functions */
> > > > > +static void quickstart_acpi_notify(acpi_handle handle, u32 event,
> > > > > void *data)
> > > > > +{
> > > > > + struct quickstart_acpi *quickstart = data;
> > > > > +
> > > > > + if (!quickstart)
> > > > > + return;
> > > > > +
> > > > > + if (event == QUICKSTART_EVENT_WAKE) {
> > > > > + quickstart_data.pressed = quickstart->btn;
> > > > > + printk(KERN_ERR "quickstart: Quickbutton %s
> > > > > pressed.\n",
> > > > > +
> > > > > acpi_device_bid(quickstart->device));
> > > > > + } else if (event == QUICKSTART_EVENT_RUNTIME) {
> > > > > + printk(KERN_ERR "quickstart: Runtime button %s
> > > > > pressed.\n\t"
> > > > > + "please report on linux-acpi@vger.kernel.org",
> > > > > +
> > > > > acpi_device_bid(quickstart->device));
> > > > > + }
> > > > Please remove above printks. they are misleading, which isn't an error.
> > > > please send an ACPI event to userspace in the notify, we need it for
> > > > runtime.
> > >
> > > According to the Microsoft paper, runtime hot button reporting is optional.
> > > My laptop doesn't report them and on the SF.net project page there was no
> > > reports of people with hardware supporting this.
> > > Sorry, I don't have a way to test this..
> > Did you tried suspend/resume. From the doc, resume can send a
> > notification too. Just calling acpi event eject routines, an event eject
> > model can be well integrated into existing acpi daemons.
>
> Yes, suspend to mem works.
> When the laptop is in suspend state, if DVD button is pressed the laptop resumes
> and the platform driver receives a notify. The driver then exports the
> button name to the sysfs pressed_button file.
>
> >
> > > > > + }
> > > > I'd suggest the GHID info should be exported to sysfs too. It's hard to
> > > > judge what a button is just per its name. You know it but an
> > > > inexperienced user doesn't.
> > >
> > > I also would like to have a more descriptive information about the button but
> > > the returned buffer is a BYTE/WORD/DWORD with a decimal number telling the button
> > > usage ID.
> > >
> > > Looking at my DSDT piece of code:
> > >
> > > Method (GHID, 0, NotSerialized)
> > > {
> > > If (LEqual (HOTB, 0x05))
> > > {
> > > Notify (DBTN, 0x02)
> > > Store (0x00, HOTB)
> > > }
> > >
> > > Return (Buffer (0x01)
> > > {
> > > /* 0000 */ 0x04
> > > })
> > > }
> > >
> > > IMHO, a value like 0x04 for button usageID is totally useless..
> > Ok, I got it. Maybe we need tool to help user identify what purpose a
> > button is, but sounds impossible till the button can trigger runtime
> > event.
>
> I've noticed that HP laptops have the same names for button
> devices (at least dv6k, dv8k and tx series). Maybe other vendors do this as well?
> If this holds true, maybe building a vendor table for getting
> button name -> description correspondence? .. just an idea ..
>
> >
> > Thanks,
> > Shaohua
> >
>
> Thanks all,
> - --
> Angelo Arrifano AKA MiKNiX
> CSE Student at UBI, Portugal
> Gentoo Linux AMD64 Arch Tester
> Linwizard Developer
> http://miknix.homelinux.com
> PGP Pubkey 0x3D92BB0B
>
> - - -
> Computers are like air conditioners. Both stop working, if you open windows.
> -- Adam Heath
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v2.0.7 (GNU/Linux)
>
> iD8DBQFH7UlnNahyoD2SuwsRApPtAJ9GcFwvwuAgCyCnS87XaGI+nHAbYgCeM65K
> lvOIGf01TPFzAgqFbSoFJYY=
> =vrGR
> -----END PGP SIGNATURE-----
Hello,
I have been testing the driver against latest trees. The driver still
works without changes.
I would like to ask if, is this driver eligible for inclusion on the acpi-test branch?
Best regards,
--
Angelo Arrifano AKA MiKNiX
CSE Student at UBI, Portugal
Gentoo Linux AMD64 Arch Tester
Linwizard Developer
http://miknix.homelinux.com
PGP Pubkey 0x3D92BB0B
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-08-24 16:39 ` Ângelo Miguel Arrifano
@ 2008-08-25 1:29 ` Zhang Rui
2008-08-26 18:43 ` Andi Kleen
0 siblings, 1 reply; 18+ messages in thread
From: Zhang Rui @ 2008-08-25 1:29 UTC (permalink / raw)
To: Ângelo Miguel Arrifano, Len Brown; +Cc: Li, Shaohua, linux-acpi
On Mon, 2008-08-25 at 00:39 +0800, Ângelo Miguel Arrifano wrote:
> On Fri, 28 Mar 2008 19:39:19 +0000
> Ângelo Miguel Arrifano <miknix@gmail.com> wrote:
>
> > -----BEGIN PGP SIGNED MESSAGE-----
> > Hash: SHA1
> >
> > On Fri, 28 Mar 2008 09:36:55 +0800
> > Shaohua Li <shaohua.li@intel.com> wrote:
> >
> > >
> > > On Thu, 2008-03-27 at 16:03 +0000, Ângelo Miguel Arrifano wrote:
> > > > On Thu, 27 Mar 2008 10:30:13 +0800
> > > > Shaohua Li <shaohua.li@intel.com> wrote:
> > > >
> > > > >
> > > > > On Thu, 2008-03-27 at 01:51 +0800, Ângelo Miguel Arrifano
> wrote:
> > > > > > PATCH
> > > > > > -
> -----------------------------------------------------------------
> > > > > > diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> > > > > > index f688c21..fb096ee 100644
> > > > > > - --- a/drivers/acpi/Kconfig
> > > > > > +++ b/drivers/acpi/Kconfig
> > > > > > @@ -196,6 +196,14 @@ config ACPI_THERMAL
> > > > > > recommended that this option be enabled, as your
> > > > > > processor(s)
> > > > > > may be damaged without it.
> > > > > >
> > > > > > +config ACPI_QUICKSTART
> > > > > > + tristate "Quickstart"
> > > > > > + default y
> > > > > default m?
> > > > >
> > > > >
> > > > > > +
> > > > > > +static struct quickstart_driver_data {
> > > > > > + struct quickstart_btn *btn_lst;
> > > > > > + struct quickstart_btn *pressed;
> > > > > > +} quickstart_data = {
> > > > > > + .btn_lst = NULL,
> > > > > > + .pressed = NULL,
> > > > > > +};
> > > > > They are NULL, you don't need initialize them.
> > > > >
> > > > >
> > > > > > + * 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);
> > > > > this file can be changed by non-root?
> > > >
> > > > The only thing that writing to this file does is clearing the
> > > > pressed button.
> > > > Is it a bad idea that can be changed by non-root?
> > > Just abnormal, eg. non-root can clear it but root might not read
> it
> > > (though it doesn't happen in current case but possible if runtime
> event
> > > support).
> > >
> > > > > > +
> > > > > > +/* ACPI Driver functions */
> > > > > > +static void quickstart_acpi_notify(acpi_handle handle, u32
> event,
> > > > > > void *data)
> > > > > > +{
> > > > > > + struct quickstart_acpi *quickstart = data;
> > > > > > +
> > > > > > + if (!quickstart)
> > > > > > + return;
> > > > > > +
> > > > > > + if (event == QUICKSTART_EVENT_WAKE) {
> > > > > > + quickstart_data.pressed = quickstart->btn;
> > > > > > + printk(KERN_ERR "quickstart: Quickbutton %s
> > > > > > pressed.\n",
> > > > > > +
> > > > > > acpi_device_bid(quickstart->device));
> > > > > > + } else if (event == QUICKSTART_EVENT_RUNTIME) {
> > > > > > + printk(KERN_ERR "quickstart: Runtime button
> %s
> > > > > > pressed.\n\t"
> > > > > > + "please report on
> linux-acpi@vger.kernel.org",
> > > > > > +
> > > > > > acpi_device_bid(quickstart->device));
> > > > > > + }
> > > > > Please remove above printks. they are misleading, which isn't
> an error.
> > > > > please send an ACPI event to userspace in the notify, we need
> it for
> > > > > runtime.
> > > >
> > > > According to the Microsoft paper, runtime hot button reporting
> is optional.
> > > > My laptop doesn't report them and on the SF.net project page
> there was no
> > > > reports of people with hardware supporting this.
> > > > Sorry, I don't have a way to test this..
> > > Did you tried suspend/resume. From the doc, resume can send a
> > > notification too. Just calling acpi event eject routines, an event
> eject
> > > model can be well integrated into existing acpi daemons.
> >
> > Yes, suspend to mem works.
> > When the laptop is in suspend state, if DVD button is pressed the
> laptop resumes
> > and the platform driver receives a notify. The driver then exports
> the
> > button name to the sysfs pressed_button file.
> >
> > >
> > > > > > + }
> > > > > I'd suggest the GHID info should be exported to sysfs too.
> It's hard to
> > > > > judge what a button is just per its name. You know it but an
> > > > > inexperienced user doesn't.
> > > >
> > > > I also would like to have a more descriptive information about
> the button but
> > > > the returned buffer is a BYTE/WORD/DWORD with a decimal number
> telling the button
> > > > usage ID.
> > > >
> > > > Looking at my DSDT piece of code:
> > > >
> > > > Method (GHID, 0, NotSerialized)
> > > > {
> > > > If (LEqual (HOTB, 0x05))
> > > > {
> > > > Notify (DBTN, 0x02)
> > > > Store (0x00, HOTB)
> > > > }
> > > >
> > > > Return (Buffer (0x01)
> > > > {
> > > > /* 0000 */ 0x04
> > > > })
> > > > }
> > > >
> > > > IMHO, a value like 0x04 for button usageID is totally useless..
> > > Ok, I got it. Maybe we need tool to help user identify what
> purpose a
> > > button is, but sounds impossible till the button can trigger
> runtime
> > > event.
> >
> > I've noticed that HP laptops have the same names for button
> > devices (at least dv6k, dv8k and tx series). Maybe other vendors do
> this as well?
> > If this holds true, maybe building a vendor table for getting
> > button name -> description correspondence? .. just an idea ..
> >
> > >
> > > Thanks,
> > > Shaohua
> > >
> >
> > Thanks all,
> > - --
> > Angelo Arrifano AKA MiKNiX
> > CSE Student at UBI, Portugal
> > Gentoo Linux AMD64 Arch Tester
> > Linwizard Developer
> > http://miknix.homelinux.com
> > PGP Pubkey 0x3D92BB0B
> >
> > - - -
> > Computers are like air conditioners. Both stop working, if you open
> windows.
> > -- Adam Heath
> > -----BEGIN PGP SIGNATURE-----
> > Version: GnuPG v2.0.7 (GNU/Linux)
> >
> > iD8DBQFH7UlnNahyoD2SuwsRApPtAJ9GcFwvwuAgCyCnS87XaGI+nHAbYgCeM65K
> > lvOIGf01TPFzAgqFbSoFJYY=
> > =vrGR
> > -----END PGP SIGNATURE-----
>
> Hello,
>
> I have been testing the driver against latest trees. The driver still
> works without changes.
> I would like to ask if, is this driver eligible for inclusion on the
> acpi-test branch?
>
oops, sorry that we lost track of this patch, but it should be somewhere
in Len's tree.
cc len. :)
thanks,
rui
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-08-25 1:29 ` Zhang Rui
@ 2008-08-26 18:43 ` Andi Kleen
2008-08-28 12:37 ` Ângelo Miguel Arrifano
0 siblings, 1 reply; 18+ messages in thread
From: Andi Kleen @ 2008-08-26 18:43 UTC (permalink / raw)
To: Zhang Rui; +Cc: Ângelo Miguel Arrifano, Len Brown, Li, Shaohua, linux-acpi
Zhang Rui <rui.zhang@intel.com> writes:
>>
>> I have been testing the driver against latest trees. The driver still
>> works without changes.
>> I would like to ask if, is this driver eligible for inclusion on the
>> acpi-test branch?
>>
> oops, sorry that we lost track of this patch, but it should be somewhere
> in Len's tree.
> cc len. :)
I don't think we have it anywhere. Best to resubmit it.
-Andi
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-08-26 18:43 ` Andi Kleen
@ 2008-08-28 12:37 ` Ângelo Miguel Arrifano
2008-08-28 13:08 ` Andi Kleen
2008-08-28 13:40 ` Matthew Garrett
0 siblings, 2 replies; 18+ messages in thread
From: Ângelo Miguel Arrifano @ 2008-08-28 12:37 UTC (permalink / raw)
To: andi; +Cc: Zhang Rui, Len Brown, Li, Shaohua, linux-acpi
On Tue, 26 Aug 2008 20:43:45 +0200
Andi Kleen <andi@firstfloor.org> wrote:
> Zhang Rui <rui.zhang@intel.com> writes:
> >>
> >> I have been testing the driver against latest trees. The driver still
> >> works without changes.
> >> I would like to ask if, is this driver eligible for inclusion on the
> >> acpi-test branch?
> >>
> > oops, sorry that we lost track of this patch, but it should be somewhere
> > in Len's tree.
> > cc len. :)
>
> I don't think we have it anywhere. Best to resubmit it.
>
> -Andi
>
Ok thanks, here it is.
-Angelo
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index c52fca8..ed48a56 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -199,6 +199,14 @@ config ACPI_THERMAL
recommended that this option be enabled, as your processor(s)
may be damaged without it.
+config ACPI_QUICKSTART
+ tristate "Quickstart"
+ default m
+ help
+ This driver add support for ACPI Direct Application Launch
+ also known as Hotstart(TM). Say yes here to have a entry in
+ sysfs telling which button was used to turn on the system.
+
config ACPI_NUMA
bool "NUMA support"
depends on NUMA
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 40b0fca..df74d57 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -62,3 +62,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..b8ebb93
--- /dev/null
+++ b/drivers/acpi/quickstart.c
@@ -0,0 +1,427 @@
+/*
+ * 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.01"
+
+#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>
+
+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
+
+/* There will be two events:
+ * 0x02 - A hot button was pressed while device was off/sleeping.
+ * 0x08 - A hot button was pressed while device was up. */
+#define QUICKSTART_EVENT_WAKE 0x02
+#define QUICKSTART_EVENT_RUNTIME 0x80
+
+struct quickstart_btn {
+ char *name;
+ struct quickstart_btn *next;
+};
+
+static struct quickstart_driver_data {
+ struct quickstart_btn *btn_lst;
+ struct quickstart_btn *pressed;
+} quickstart_data;
+
+/*
+ * ACPI driver Structs
+ */
+
+struct quickstart_acpi {
+ struct acpi_device *device;
+ struct quickstart_btn *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,
+ }
+};
+
+/*
+ * Platform driver functions
+ */
+static ssize_t buttons_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int count = 0;
+ struct quickstart_btn *ptr = quickstart_data.btn_lst;
+
+ if (!ptr)
+ return snprintf(buf, PAGE_SIZE, "none");
+
+ while (ptr && (count < PAGE_SIZE)) {
+ if (ptr->name) {
+ count += snprintf(buf + count,
+ PAGE_SIZE - count,
+ "%s\n", ptr->name);
+ }
+ 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 **data)
+{
+ struct quickstart_btn **ptr = &quickstart_data.btn_lst;
+
+ while (*ptr)
+ ptr = &((*ptr)->next);
+
+ *ptr = kzalloc(sizeof(struct quickstart_btn), GFP_KERNEL);
+ if (!*ptr) {
+ *data = NULL;
+ return(-ENOMEM);
+ }
+ *data = *ptr;
+
+ return 0;
+}
+
+static void quickstart_btnlst_del(struct quickstart_btn *data)
+{
+ struct quickstart_btn **ptr = &quickstart_data.btn_lst;
+
+ if (!data)
+ return;
+
+ while (*ptr) {
+ if (*ptr == data) {
+ *ptr = (*ptr)->next;
+ kfree(data);
+ return;
+ }
+ ptr = &((*ptr)->next);
+ }
+
+ return;
+}
+
+static void quickstart_btnlst_free(void)
+{
+ struct quickstart_btn *ptr = quickstart_data.btn_lst;
+ struct quickstart_btn *lptr = NULL;
+
+ while (ptr) {
+ lptr = ptr;
+ ptr = ptr->next;
+ kfree(lptr->name);
+ kfree(lptr);
+ }
+
+ return;
+}
+
+/* ACPI Driver functions */
+static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct quickstart_acpi *quickstart = data;
+
+ if (!quickstart)
+ return;
+
+ if (event == QUICKSTART_EVENT_WAKE)
+ quickstart_data.pressed = quickstart->btn;
+
+ return;
+}
+
+static void quickstart_acpi_raise_notify(struct quickstart_acpi *quickstart)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ if (!quickstart)
+ return;
+
+ /* This returns a buffer telling the button usage ID (useless),
+ * we dont care about it now. The important is to trigger
+ * pending notify events (The ones before booting). */
+ status = acpi_evaluate_object(quickstart->device->handle,
+ "GHID", NULL, &buffer);
+ if (ACPI_FAILURE(status) || !buffer.pointer) {
+ printk(KERN_ERR "quickstart: %s GHID method failed.\n",
+ quickstart->btn->name);
+ return;
+ }
+
+ kfree(buffer.pointer);
+ 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);
+ acpi_driver_data(device) = 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(KERN_ERR "quickstart: Notify handler install error\n");
+ ret = -ENODEV;
+ goto fail_installnotify;
+ }
+
+ quickstart_acpi_raise_notify(quickstart);
+
+ return 0;
+
+fail_installnotify:
+ quickstart_btnlst_del(quickstart->btn);
+
+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(KERN_ERR "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);
+
+ 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;
+
+ /* ACPI Check */
+ if (acpi_disabled)
+ return -ENODEV;
+
+ /* ACPI driver register */
+ status = acpi_bus_register_driver(&quickstart_acpi_driver);
+ if (status < 0)
+ return -ENODEV;
+
+ /* If existing bus with no devices */
+ if (!quickstart_data.btn_lst) {
+ ret = -ENODEV;
+ goto fail_pfdrv_reg;
+ }
+
+ /* 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;
+
+ printk(KERN_INFO "quickstart: ACPI Direct App Launch ver %s\n",
+ QUICKSTART_VERSION);
+
+ return 0;
+
+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);
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-08-28 12:37 ` Ângelo Miguel Arrifano
@ 2008-08-28 13:08 ` Andi Kleen
2008-08-28 13:47 ` Ângelo Miguel Arrifano
2008-08-28 13:40 ` Matthew Garrett
1 sibling, 1 reply; 18+ messages in thread
From: Andi Kleen @ 2008-08-28 13:08 UTC (permalink / raw)
To: Ângelo Miguel Arrifano
Cc: andi, Zhang Rui, Len Brown, Li, Shaohua, linux-acpi
> Ok thanks, here it is.
Please submit it with proper description and Signed-off-by lines.
(see Documentation/SubmittingPatches)
-Andi
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-08-28 12:37 ` Ângelo Miguel Arrifano
2008-08-28 13:08 ` Andi Kleen
@ 2008-08-28 13:40 ` Matthew Garrett
2008-08-31 22:38 ` Ângelo Miguel Arrifano
1 sibling, 1 reply; 18+ messages in thread
From: Matthew Garrett @ 2008-08-28 13:40 UTC (permalink / raw)
To: Ângelo Miguel Arrifano
Cc: andi, Zhang Rui, Len Brown, Li, Shaohua, linux-acpi
On Thu, Aug 28, 2008 at 02:37:08PM +0200, Ângelo Miguel Arrifano wrote:
> +/* There will be two events:
> + * 0x02 - A hot button was pressed while device was off/sleeping.
> + * 0x08 - A hot button was pressed while device was up. */
Are you sure? The spec seems to say 0x80, not 0x08.
> +#define QUICKSTART_EVENT_RUNTIME 0x80
As you have here :)
Could you add an input device for runtime button notification? Use the
GHID value as a scancode, then provide functions to do scancode->keycode
mappings (see wistron_btns.c or hp_wmi.c for examples of this). That
way, hal or whatever can be used to map them to machine-specific values.
--
Matthew Garrett | mjg59@srcf.ucam.org
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-08-28 13:08 ` Andi Kleen
@ 2008-08-28 13:47 ` Ângelo Miguel Arrifano
2008-08-28 15:36 ` Andi Kleen
0 siblings, 1 reply; 18+ messages in thread
From: Ângelo Miguel Arrifano @ 2008-08-28 13:47 UTC (permalink / raw)
To: Andi Kleen; +Cc: Zhang Rui, Len Brown, Li, Shaohua, linux-acpi
On Thu, 28 Aug 2008 15:08:05 +0200
Andi Kleen <andi@firstfloor.org> wrote:
> > Ok thanks, here it is.
>
> Please submit it with proper description and Signed-off-by lines.
> (see Documentation/SubmittingPatches)
>
> -Andi
Description:
With the introduction of Vista, Microsoft launched a new ACPI
?specification? to allow computers in sleep/off states to boot
directly into multimedia applications by only pressing buttons.
This driver provides support to these devices allowing userspace
scripts to launch multimedia applications based on which button
was used to turn on the system.
How it works:
When the system boots, the driver receives an ACPI event telling
which button was used to power the system on. Then, the driver exports
this information to sysfs allowing userspace scripts to know the
button name. This also applies to memory suspend and other power
saving states.
Example:
* File buttons shows a list of supported hot buttons.
$ cat /sys/devices/platform/quickstart/buttons
QBTN
DBTN
MUBN
PIBN
WEBN
LVBN
VOBN
* File pressed_button shows the hot button name used to power/resume the system.
You can also write "none" to it to reset.
$ cat /sys/devices/platform/quickstart/pressed_button
none
References:
* http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/DirAppLaunch_Vista.doc
----------------------------------------
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index c52fca8..ed48a56 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -199,6 +199,14 @@ config ACPI_THERMAL
recommended that this option be enabled, as your processor(s)
may be damaged without it.
+config ACPI_QUICKSTART
+ tristate "Quickstart"
+ default m
+ help
+ This driver add support for ACPI Direct Application Launch
+ also known as Hotstart(TM). Say yes here to have a entry in
+ sysfs telling which button was used to turn on the system.
+
config ACPI_NUMA
bool "NUMA support"
depends on NUMA
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 40b0fca..df74d57 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -62,3 +62,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..b8ebb93
--- /dev/null
+++ b/drivers/acpi/quickstart.c
@@ -0,0 +1,427 @@
+/*
+ * 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.01"
+
+#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>
+
+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
+
+/* There will be two events:
+ * 0x02 - A hot button was pressed while device was off/sleeping.
+ * 0x08 - A hot button was pressed while device was up. */
+#define QUICKSTART_EVENT_WAKE 0x02
+#define QUICKSTART_EVENT_RUNTIME 0x80
+
+struct quickstart_btn {
+ char *name;
+ struct quickstart_btn *next;
+};
+
+static struct quickstart_driver_data {
+ struct quickstart_btn *btn_lst;
+ struct quickstart_btn *pressed;
+} quickstart_data;
+
+/*
+ * ACPI driver Structs
+ */
+
+struct quickstart_acpi {
+ struct acpi_device *device;
+ struct quickstart_btn *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,
+ }
+};
+
+/*
+ * Platform driver functions
+ */
+static ssize_t buttons_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int count = 0;
+ struct quickstart_btn *ptr = quickstart_data.btn_lst;
+
+ if (!ptr)
+ return snprintf(buf, PAGE_SIZE, "none");
+
+ while (ptr && (count < PAGE_SIZE)) {
+ if (ptr->name) {
+ count += snprintf(buf + count,
+ PAGE_SIZE - count,
+ "%s\n", ptr->name);
+ }
+ 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 **data)
+{
+ struct quickstart_btn **ptr = &quickstart_data.btn_lst;
+
+ while (*ptr)
+ ptr = &((*ptr)->next);
+
+ *ptr = kzalloc(sizeof(struct quickstart_btn), GFP_KERNEL);
+ if (!*ptr) {
+ *data = NULL;
+ return(-ENOMEM);
+ }
+ *data = *ptr;
+
+ return 0;
+}
+
+static void quickstart_btnlst_del(struct quickstart_btn *data)
+{
+ struct quickstart_btn **ptr = &quickstart_data.btn_lst;
+
+ if (!data)
+ return;
+
+ while (*ptr) {
+ if (*ptr == data) {
+ *ptr = (*ptr)->next;
+ kfree(data);
+ return;
+ }
+ ptr = &((*ptr)->next);
+ }
+
+ return;
+}
+
+static void quickstart_btnlst_free(void)
+{
+ struct quickstart_btn *ptr = quickstart_data.btn_lst;
+ struct quickstart_btn *lptr = NULL;
+
+ while (ptr) {
+ lptr = ptr;
+ ptr = ptr->next;
+ kfree(lptr->name);
+ kfree(lptr);
+ }
+
+ return;
+}
+
+/* ACPI Driver functions */
+static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct quickstart_acpi *quickstart = data;
+
+ if (!quickstart)
+ return;
+
+ if (event == QUICKSTART_EVENT_WAKE)
+ quickstart_data.pressed = quickstart->btn;
+
+ return;
+}
+
+static void quickstart_acpi_raise_notify(struct quickstart_acpi *quickstart)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ if (!quickstart)
+ return;
+
+ /* This returns a buffer telling the button usage ID (useless),
+ * we dont care about it now. The important is to trigger
+ * pending notify events (The ones before booting). */
+ status = acpi_evaluate_object(quickstart->device->handle,
+ "GHID", NULL, &buffer);
+ if (ACPI_FAILURE(status) || !buffer.pointer) {
+ printk(KERN_ERR "quickstart: %s GHID method failed.\n",
+ quickstart->btn->name);
+ return;
+ }
+
+ kfree(buffer.pointer);
+ 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);
+ acpi_driver_data(device) = 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(KERN_ERR "quickstart: Notify handler install error\n");
+ ret = -ENODEV;
+ goto fail_installnotify;
+ }
+
+ quickstart_acpi_raise_notify(quickstart);
+
+ return 0;
+
+fail_installnotify:
+ quickstart_btnlst_del(quickstart->btn);
+
+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(KERN_ERR "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);
+
+ 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;
+
+ /* ACPI Check */
+ if (acpi_disabled)
+ return -ENODEV;
+
+ /* ACPI driver register */
+ status = acpi_bus_register_driver(&quickstart_acpi_driver);
+ if (status < 0)
+ return -ENODEV;
+
+ /* If existing bus with no devices */
+ if (!quickstart_data.btn_lst) {
+ ret = -ENODEV;
+ goto fail_pfdrv_reg;
+ }
+
+ /* 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;
+
+ printk(KERN_INFO "quickstart: ACPI Direct App Launch ver %s\n",
+ QUICKSTART_VERSION);
+
+ return 0;
+
+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);
Signed-off-by: Angelo Miguel Arrifano <miknix@gmail.com>
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-08-28 13:47 ` Ângelo Miguel Arrifano
@ 2008-08-28 15:36 ` Andi Kleen
0 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2008-08-28 15:36 UTC (permalink / raw)
To: Ângelo Miguel Arrifano
Cc: Andi Kleen, Zhang Rui, Len Brown, Li, Shaohua, linux-acpi
On Thu, Aug 28, 2008 at 03:47:45PM +0200, Ângelo Miguel Arrifano wrote:
> On Thu, 28 Aug 2008 15:08:05 +0200
> Andi Kleen <andi@firstfloor.org> wrote:
>
> > > Ok thanks, here it is.
> >
> > Please submit it with proper description and Signed-off-by lines.
> > (see Documentation/SubmittingPatches)
> >
> > -Andi
Quick review:
Need a title (one line description)
Best probably you run it through checkpatch.pl and fix the warnings
and possibly also Lindent.
> index c52fca8..ed48a56 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -199,6 +199,14 @@ config ACPI_THERMAL
> recommended that this option be enabled, as your processor(s)
> may be damaged without it.
>
> +config ACPI_QUICKSTART
> + tristate "Quickstart"
> + default m
Please remove the default m
Also I think the position is wrong, this should be further down with
other misc ACPI drivers.
> +
> +#define QUICKSTART_PF_DRIVER_NAME "quickstart"
> +#define QUICKSTART_PF_DEVICE_NAME "quickstart"
> +#define QUICKSTART_PF_DEVATTR_NAME "pressed_button"
I don't see the point of these defines. Can you just expand
them please?
> +
> +/*
> + * ACPI driver Structs
> + */
> +
> +struct quickstart_acpi {
> + struct acpi_device *device;
> + struct quickstart_btn *btn;
> +};
There should be a new line here.
> +static int quickstart_acpi_add(struct acpi_device *device);
> +static int quickstart_acpi_remove(struct acpi_device *device, int type);
Standard practice is to reorder the file that forward declarations
are not needed.
> +
> +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,
Unusual indentation.
> + },
> +};
> +
> +/*
> + * 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);
See above for forward declarations.
> + */
> +static ssize_t buttons_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + int count = 0;
> + struct quickstart_btn *ptr = quickstart_data.btn_lst;
> +
> + if (!ptr)
> + return snprintf(buf, PAGE_SIZE, "none");
> +
> + while (ptr && (count < PAGE_SIZE)) {
> + if (ptr->name) {
> + count += snprintf(buf + count,
> + PAGE_SIZE - count,
> + "%s\n", ptr->name);
> + }
> + ptr = ptr->next;
> + }
Is it guaranteed that list is always shorter than
PAGE_SIZE? PAGE_SIZE - count might go negative otherwise
and snprintf will not handle that. Should be some proper limit.
> +
> +
> +static ssize_t pressed_button_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + if (count < 2)
> + return -EINVAL;
Check is redundant.
> +
> + 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 **data)
> +{
> + struct quickstart_btn **ptr = &quickstart_data.btn_lst;
> +
> + while (*ptr)
> + ptr = &((*ptr)->next);
Would be all clearer if you used standard list.h lists.
> + 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);
Use kstrndup()
> +
> + platform_device_unregister(pf_device);
> +
> + platform_driver_unregister(&pf_driver);
> +
> + acpi_bus_unregister_driver(&quickstart_acpi_driver);
> +
> + quickstart_btnlst_free();
> +
> + return;
You have a lot of stray such returns; Remove them all.
> Signed-off-by: Angelo Miguel Arrifano <miknix@gmail.com>
That should be at the bottom of the description.
-Andi
--
ak@linux.intel.com
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-08-31 22:38 ` Ângelo Miguel Arrifano
@ 2008-08-31 22:00 ` Matthew Garrett
2008-08-31 23:21 ` Ângelo Miguel Arrifano
0 siblings, 1 reply; 18+ messages in thread
From: Matthew Garrett @ 2008-08-31 22:00 UTC (permalink / raw)
To: Ângelo Miguel Arrifano
Cc: andi, Zhang Rui, Len Brown, Li, Shaohua, linux-acpi
On Mon, Sep 01, 2008 at 12:38:56AM +0200, Ângelo Miguel Arrifano wrote:
> On Thu, 28 Aug 2008 14:40:55 +0100
> Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> + else if (event == QUICKSTART_EVENT_RUNTIME) {
> + input_report_key(quickstart_input, quickstart->btn->id, 1);
> + input_sync(quickstart_input);
> + input_report_key(quickstart_input, quickstart->btn->id, 0);
> + input_sync(quickstart_input);
>
> The button usage ID is used as key code.
Right, that's probably not how you want to do it. Keycodes should be the
things in include/linux/input.h. The problem you have is that there's no
way of mapping the usage ID to the keycode without knowing the specific
laptop layout. The right way of doing this is to use the usage ID as a
scancode, and then implement the get and setkeycode functions. Userspace
can then alter the keymap. Check the wistron_btns driver for an example
of this.
> Buffer dump:
> QBTN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
> DBTN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00
> MUBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00
> PIBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00
> WEBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00
> LVBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00
> VOBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 07 00 00 00 00 00 00 00
> +---------------------+
> Does it return a QWORD?? Why is it at the end of the buffer?
This is the raw dump of what GHID returns? I'm not quite clear on what's
going on here.
> + /* <<The GHID method can return a BYTE, WORD, or DWORD.
> + * The value must be encoded in little-endian byte
> + * order (least significant byte first).>> */
> + ACPI_MOVE_32_TO_32(&usageid, buffer.pointer + (buffer.length - 8));
> + quickstart->btn->id = usageid;
>
> I need your help in here, I doubt this code runs for anyone but me.
Right. For instance, GHID on another system I have here is just:
Method (GHID, 0, NotSerialized)
{
Acquire (MUT1, 0xFFFF)
And (MBTB, 0x02, Local0)
Release (MUT1)
If (Local0)
{
Notify (DAL2, 0x02)
}
Return (Buffer (One)
{
0x02
})
which doesn't look like your code would cope at all.
--
Matthew Garrett | mjg59@srcf.ucam.org
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-08-28 13:40 ` Matthew Garrett
@ 2008-08-31 22:38 ` Ângelo Miguel Arrifano
2008-08-31 22:00 ` Matthew Garrett
0 siblings, 1 reply; 18+ messages in thread
From: Ângelo Miguel Arrifano @ 2008-08-31 22:38 UTC (permalink / raw)
To: Matthew Garrett; +Cc: andi, Zhang Rui, Len Brown, Li, Shaohua, linux-acpi
On Thu, 28 Aug 2008 14:40:55 +0100
Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> On Thu, Aug 28, 2008 at 02:37:08PM +0200, Ângelo Miguel Arrifano wrote:
>
> > +/* There will be two events:
> > + * 0x02 - A hot button was pressed while device was off/sleeping.
> > + * 0x08 - A hot button was pressed while device was up. */
>
> Are you sure? The spec seems to say 0x80, not 0x08.
>
> > +#define QUICKSTART_EVENT_RUNTIME 0x80
>
> As you have here :)
>
> Could you add an input device for runtime button notification? Use the
> GHID value as a scancode, then provide functions to do scancode->keycode
> mappings (see wistron_btns.c or hp_wmi.c for examples of this). That
> way, hal or whatever can be used to map them to machine-specific values.
>
> --
> Matthew Garrett | mjg59@srcf.ucam.org
Patch below includes proposed changes for runtime button notification.
I could not fully test it since my laptop doesn't report runtime key presses.
NOTE: There are some inline comments in the patch below.
-- Thanks, Angelo Arrifano
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index c52fca8..ed48a56 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -199,6 +199,14 @@ config ACPI_THERMAL
recommended that this option be enabled, as your processor(s)
may be damaged without it.
+config ACPI_QUICKSTART
+ tristate "Quickstart"
+ default m
+ help
+ This driver add support for ACPI Direct Application Launch
+ also known as Hotstart(TM). Say yes here to have a entry in
+ sysfs telling which button was used to turn on the system.
+
config ACPI_NUMA
bool "NUMA support"
depends on NUMA
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 40b0fca..df74d57 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -62,3 +62,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..1e6d928
--- /dev/null
+++ b/drivers/acpi/quickstart.c
@@ -0,0 +1,474 @@
+/*
+ * 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.01"
+
+#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
+
+/* There will be two events:
+ * 0x02 - A hot button was pressed while device was off/sleeping.
+ * 0x80 - A hot button was pressed while device was up. */
+#define QUICKSTART_EVENT_WAKE 0x02
+#define QUICKSTART_EVENT_RUNTIME 0x80
+
+struct quickstart_btn {
+ char *name;
+ unsigned int id;
+ struct quickstart_btn *next;
+};
+
+static struct quickstart_driver_data {
+ struct quickstart_btn *btn_lst;
+ struct quickstart_btn *pressed;
+} quickstart_data;
+
+/* ACPI driver Structs */
+struct quickstart_acpi {
+ struct acpi_device *device;
+ struct quickstart_btn *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,
+ },
+};
+
+/* Input device structs */
+struct input_dev *quickstart_input;
+
+/* 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,
+ }
+};
+
+/*
+ * Platform driver functions
+ */
+static ssize_t buttons_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int count = 0;
+ struct quickstart_btn *ptr = quickstart_data.btn_lst;
+
+ if (!ptr)
+ return snprintf(buf, PAGE_SIZE, "none");
+
+ while (ptr && (count < PAGE_SIZE)) {
+ if (ptr->name) {
+ count += snprintf(buf + count,
+ PAGE_SIZE - count,
+ "%d\t%s\n", ptr->id, ptr->name);
Added the button usage ID to the button list.
The button usage ID is returned by the GHID method.
Ex:
cat /sys/ . . . /buttons
1 QBTN
2 DBTN
3 MUBN
6 PIBN
4 WEBN
8 LVBN
7 VOBN
+ }
+ 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 **data)
+{
+ struct quickstart_btn **ptr = &quickstart_data.btn_lst;
+
+ while (*ptr)
+ ptr = &((*ptr)->next);
+
+ *ptr = kzalloc(sizeof(struct quickstart_btn), GFP_KERNEL);
+ if (!*ptr) {
+ *data = NULL;
+ return -ENOMEM;
+ }
+ *data = *ptr;
+
+ return 0;
+}
+
+static void quickstart_btnlst_del(struct quickstart_btn *data)
+{
+ struct quickstart_btn **ptr = &quickstart_data.btn_lst;
+
+ if (!data)
+ return;
+
+ while (*ptr) {
+ if (*ptr == data) {
+ *ptr = (*ptr)->next;
+ kfree(data);
+ return;
+ }
+ ptr = &((*ptr)->next);
+ }
+
+ return;
+}
+
+static void quickstart_btnlst_free(void)
+{
+ struct quickstart_btn *ptr = quickstart_data.btn_lst;
+ struct quickstart_btn *lptr = NULL;
+
+ while (ptr) {
+ lptr = ptr;
+ ptr = ptr->next;
+ kfree(lptr->name);
+ kfree(lptr);
+ }
+
+ return;
+}
+
+/* ACPI Driver functions */
+static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct quickstart_acpi *quickstart = data;
+
+ if (!quickstart)
+ return;
+
+ if (event == QUICKSTART_EVENT_WAKE)
+ quickstart_data.pressed = quickstart->btn;
+ else if (event == QUICKSTART_EVENT_RUNTIME) {
+ input_report_key(quickstart_input, quickstart->btn->id, 1);
+ input_sync(quickstart_input);
+ input_report_key(quickstart_input, quickstart->btn->id, 0);
+ input_sync(quickstart_input);
The button usage ID is used as key code.
+ }
+ return;
+}
+
+static void quickstart_acpi_ghid(struct quickstart_acpi *quickstart)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ unsigned int usageid = 0;
+
+ if (!quickstart)
+ return;
+
+ /* This returns a buffer telling the button usage ID,
+ * and triggers pending notify events (The ones before booting). */
+ status = acpi_evaluate_object(quickstart->device->handle,
+ "GHID", NULL, &buffer);
+ if (ACPI_FAILURE(status) || !buffer.pointer) {
+ printk(KERN_ERR "quickstart: %s GHID method failed.\n",
+ quickstart->btn->name);
+ return;
+ }
This _GHID method can return a BYTE, WORD or DWORD. I guess each vendor chooses which they like most.
On my laptop, the returned buffer.length is 32.
Buffer dump:
QBTN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
DBTN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00
MUBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00
PIBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00
WEBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00
LVBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00
VOBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 07 00 00 00 00 00 00 00
+---------------------+
Does it return a QWORD?? Why is it at the end of the buffer?
+
+ if (buffer.length < 8)
+ return;
+
+ /* <<The GHID method can return a BYTE, WORD, or DWORD.
+ * The value must be encoded in little-endian byte
+ * order (least significant byte first).>> */
+ ACPI_MOVE_32_TO_32(&usageid, buffer.pointer + (buffer.length - 8));
+ quickstart->btn->id = usageid;
I need your help in here, I doubt this code runs for anyone but me.
+
+ kfree(buffer.pointer);
+}
+
+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);
+ acpi_driver_data(device) = 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(KERN_ERR "quickstart: Notify handler install error\n");
+ ret = -ENODEV;
+ goto fail_installnotify;
+ }
+
+ quickstart_acpi_ghid(quickstart);
+
+ return 0;
+
+fail_installnotify:
+ quickstart_btnlst_del(quickstart->btn);
+
+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(KERN_ERR "quickstart: Error removing notify handler\n");
+
+
+ kfree(quickstart);
+
+ return 0;
+}
+
+/* Module functions */
+
+static void quickstart_exit(void)
+{
+ input_unregister_device(quickstart_input);
+ input_free_device(quickstart_input);
+
+ device_remove_file(&pf_device->dev, &dev_attr_pressed_button);
+ device_remove_file(&pf_device->dev, &dev_attr_buttons);
+
+ 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_input(void)
+{
+ struct quickstart_btn **ptr = &quickstart_data.btn_lst;
+ int count;
+
+ quickstart_input = input_allocate_device();
+
+ if (!quickstart_input)
+ return -ENOMEM;
+
+ quickstart_input->name = "Quickstart ACPI Buttons";
+ quickstart_input->id.bustype = BUS_HOST;
+
+ while (*ptr) {
+ count++;
+ set_bit(EV_KEY, quickstart_input->evbit);
+ set_bit((*ptr)->id, quickstart_input->keybit);
+ ptr = &((*ptr)->next);
+ }
+
+ return input_register_device(quickstart_input);
+}
+
+static int __init quickstart_init(void)
+{
+ int ret;
+ acpi_status status = 0;
+
+ /* ACPI Check */
+ if (acpi_disabled)
+ return -ENODEV;
+
+ /* ACPI driver register */
+ status = acpi_bus_register_driver(&quickstart_acpi_driver);
+ if (status < 0)
+ return -ENODEV;
+
+ /* If existing bus with no devices */
+ if (!quickstart_data.btn_lst) {
+ ret = -ENODEV;
+ goto fail_pfdrv_reg;
+ }
+
+ /* 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;
+
+
+ /* Input device */
+ ret = quickstart_init_input();
+ if (ret)
+ goto fail_input;
+
+ printk(KERN_INFO "quickstart: ACPI Direct App Launch ver %s\n",
+ QUICKSTART_VERSION);
+
+ return 0;
+fail_input:
+ 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);
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32)
2008-08-31 22:00 ` Matthew Garrett
@ 2008-08-31 23:21 ` Ângelo Miguel Arrifano
0 siblings, 0 replies; 18+ messages in thread
From: Ângelo Miguel Arrifano @ 2008-08-31 23:21 UTC (permalink / raw)
To: Matthew Garrett; +Cc: andi, Zhang Rui, Len Brown, Li, Shaohua, linux-acpi
On Sun, 31 Aug 2008 23:00:38 +0100
Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> On Mon, Sep 01, 2008 at 12:38:56AM +0200, Ângelo Miguel Arrifano wrote:
> > On Thu, 28 Aug 2008 14:40:55 +0100
> > Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> > + else if (event == QUICKSTART_EVENT_RUNTIME) {
> > + input_report_key(quickstart_input, quickstart->btn->id, 1);
> > + input_sync(quickstart_input);
> > + input_report_key(quickstart_input, quickstart->btn->id, 0);
> > + input_sync(quickstart_input);
> >
> > The button usage ID is used as key code.
>
> Right, that's probably not how you want to do it. Keycodes should be the
> things in include/linux/input.h. The problem you have is that there's no
> way of mapping the usage ID to the keycode without knowing the specific
> laptop layout. The right way of doing this is to use the usage ID as a
> scancode, and then implement the get and setkeycode functions. Userspace
> can then alter the keymap. Check the wistron_btns driver for an example
> of this.
>
> > Buffer dump:
> > QBTN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
> > DBTN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00
> > MUBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00
> > PIBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00
> > WEBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00
> > LVBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00
> > VOBN: 03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 07 00 00 00 00 00 00 00
> > +---------------------+
> > Does it return a QWORD?? Why is it at the end of the buffer?
>
> This is the raw dump of what GHID returns? I'm not quite clear on what's
> going on here.
Yes, GHID returns a auto-allocated buffer of 32bytes.
For instance, the returned buffer for WEBN device is:
03 00 00 00 01 00 00 00 58 78 6c 4c 00 81 ff ff 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00
/\
4 is the button usage ID (see bellow). I don't know why is in that place and why the rest of the garbage.
>
> > + /* <<The GHID method can return a BYTE, WORD, or DWORD.
> > + * The value must be encoded in little-endian byte
> > + * order (least significant byte first).>> */
> > + ACPI_MOVE_32_TO_32(&usageid, buffer.pointer + (buffer.length - 8));
> > + quickstart->btn->id = usageid;
> >
> > I need your help in here, I doubt this code runs for anyone but me.
>
> Right. For instance, GHID on another system I have here is just:
>
> Method (GHID, 0, NotSerialized)
> {
> Acquire (MUT1, 0xFFFF)
> And (MBTB, 0x02, Local0)
> Release (MUT1)
> If (Local0)
> {
> Notify (DAL2, 0x02)
> }
>
> Return (Buffer (One)
> {
> 0x02
> })
>
> which doesn't look like your code would cope at all.
The GHID method here is also similar:
Method (GHID, 0, NotSerialized)
{
If (LEqual (HOTB, 0x10))
{
Notify (WEBN, 0x02)
Store (Zero, HOTB)
}
Return (Buffer (One)
{
/* 0000 */ 0x04
})
}
Shouldn't GHID be returning a 1 byte buffer?
>
> --
> Matthew Garrett | mjg59@srcf.ucam.org
Are you able to dump the returned buffer somewhere?
Thanks,
Angelo Arrifano
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2008-08-31 22:21 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-14 15:17 [PATCH] ACPI: Platform driver to support App Hot Startup (PNP0C32) Ângelo Miguel Arrifano
2008-03-25 6:59 ` Zhang, Rui
2008-03-26 17:51 ` Ângelo Miguel Arrifano
2008-03-27 2:30 ` Shaohua Li
2008-03-27 16:03 ` Ângelo Miguel Arrifano
2008-03-28 1:36 ` Shaohua Li
2008-03-28 19:39 ` Ângelo Miguel Arrifano
2008-08-24 16:39 ` Ângelo Miguel Arrifano
2008-08-25 1:29 ` Zhang Rui
2008-08-26 18:43 ` Andi Kleen
2008-08-28 12:37 ` Ângelo Miguel Arrifano
2008-08-28 13:08 ` Andi Kleen
2008-08-28 13:47 ` Ângelo Miguel Arrifano
2008-08-28 15:36 ` Andi Kleen
2008-08-28 13:40 ` Matthew Garrett
2008-08-31 22:38 ` Ângelo Miguel Arrifano
2008-08-31 22:00 ` Matthew Garrett
2008-08-31 23:21 ` Ângelo Miguel Arrifano
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox