Eject button for button driver
PATCH 1/1 Eject button for button driver
Background: Fujitsu is releasing currently small desktop systems like the ESPRIMO Q510 that have no direct accessible eject button for the optical drive.
http://www.fujitsu.com/fts/products/computing/pc/desktops/all-round/esprimo-q510/index.html
Instead of an eject button on the drive the system has a button on the mainboard that will send a notify event to the assigned device using the following ACPI code:
Scope(\_GPE)
{
Method(_L15, 0) // ODD Eject GPIO handler
{
Notify(\_SB.ODDE, 0x80) // Notify a ODD Eject Button event
to the OS
}
} //Scope(\_GPE)Scope(\_SB)
{
//
// Direct Application Launch Button definition used for Windows Vista, Windows 7, Linux ... //
Device(ODDE) // Eject Button Device
{
Name(_HID, EISAID("PNP0C32")) // HID ACPI button device
Name(_UID, 1) // Unique instance # of that device
Name(_STA, 0x0F) // Device is working properly
Method(GHID, 0) // Button "role" method
{
Return(Buffer(){1}) // Application Launch Button role
}
}
To implement this I modified the button.c driver by adding the eject button code. During testing it came out, that the button is constantly firing GPE15 events as long at is pressed, so I added some code that only handles one event per second and drops the other events.
To make the eject function work the user also needs to add a rule to acpid that triggers the eject command on the eject event.
---
drivers/acpi/button.c 2012-03-06 10:25:23.000000000 +0100 renamed from drivers/acpi/button.c 2012-03-06 10:12:04.000000000 +0100 +30 -3
@@ -31,6 +31,7 @@ #include <linux/seq_file.h> #include <linux/input.h> #include <linux/slab.h> +#include <linux/jiffies.h> /* for accepting only on eject event per second */ #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h>
@@ -57,6 +58,11 @@ #define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch" #define ACPI_BUTTON_TYPE_LID 0x05 +#define ACPI_BUTTON_SUBCLASS_EJECT "eject" +#define ACPI_BUTTON_HID_EJECT "PNP0C32" +#define ACPI_BUTTON_DEVICE_NAME_EJECT "Eject Button" +#define ACPI_BUTTON_TYPE_EJECT 0x07 + #define _COMPONENT ACPI_BUTTON_COMPONENT ACPI_MODULE_NAME("button");
@@ -70,6 +76,7 @@ {ACPI_BUTTON_HID_SLEEPF, 0}, {ACPI_BUTTON_HID_POWER, 0}, {ACPI_BUTTON_HID_POWERF, 0}, + {ACPI_BUTTON_HID_EJECT, 0}, {"", 0}, }; MODULE_DEVICE_TABLE(acpi, button_device_ids);
@@ -102,6 +109,8 @@ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); static struct acpi_device *lid_device; +static unsigned long eject_expire; /* when do the eject jiffies expire? */ + /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */
@@ -287,6 +296,16 @@ input = button->input; if (button->type == ACPI_BUTTON_TYPE_LID) { acpi_lid_send_state(device); + acpi_bus_generate_proc_event(device, event, ++button->pushed); + } else if (button->type == ACPI_BUTTON_TYPE_EJECT) { + if (time_is_before_jiffies(eject_expire)) { + eject_expire = jiffies+HZ; /* expire delay 1 second */ + input_report_key(input, KEY_EJECTCD, 1); + input_sync(input); + input_report_key(input, KEY_EJECTCD, 0); + input_sync(input); + acpi_bus_generate_proc_event(device, event, ++button->pushed); + } } else { int keycode = test_bit(KEY_SLEEP, input->keybit) ? KEY_SLEEP : KEY_POWER;
@@ -295,11 +314,9 @@ input_sync(input); input_report_key(input, keycode, 0); input_sync(input); - + acpi_bus_generate_proc_event(device, event, ++button->pushed); pm_wakeup_event(&device->dev, 0); } - - acpi_bus_generate_proc_event(device, event, ++button->pushed); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -357,6 +374,12 @@ strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID); sprintf(class, "%s/%s", ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID); + } else if (!strcmp(hid, ACPI_BUTTON_HID_EJECT)) { + button->type = ACPI_BUTTON_TYPE_EJECT; + strcpy(name, ACPI_BUTTON_DEVICE_NAME_EJECT); + sprintf(class, "%s/%s", + ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_EJECT); + eject_expire = jiffies; /* initial value for the eject delay */ } else { printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid); error = -ENODEV;
@@ -390,6 +413,10 @@ input->evbit[0] = BIT_MASK(EV_SW); set_bit(SW_LID, input->swbit); break; + case ACPI_BUTTON_TYPE_EJECT: + input->evbit[0] = BIT_MASK(EV_KEY); + set_bit(KEY_EJECTCD, input->keybit); + break; } error = input_register_device(input);
Signature · 19 lines
Dipl.-Inf. (FH) Rainer Koenig Project Manager Linux Clients Dept. TSP WPS R&D SW OSE Fujitsu Technology Solutions Bürgermeister-Ullrich-Str. 100 86199 Augsburg Germany Telephone: +49-821-804-3321 Telefax: +49-821-804-2131 Mail: mailto:[email protected] Internet ts.fujtsu.com Company Details ts.fujitsu.com/imprint.html -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 1 line · Rainer Koenig
Name(_HID, EISAID("PNP0C32"))// HID ACPI button device
PNP0C32 devices are documented in
http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/DirAppLaunch_Vista.doc
- binding this in the button driver would make it impossible to write a full driver. There's an existing driver floating around under the name "quickstart". A better approach would be to tidy that up and make sure it works for your case, and then submit that.
Signature · 1 line
Matthew Garrett | [email protected]
Matthew,
Am 07.03.2012 10:05, schrieb Matthew Garrett:
Quoted 4 lines
- binding this in the button driver would make it impossible to write a full driver. There's an existing driver floating around under the name "quickstart". A better approach would be to tidy that up and make sure it works for your case, and then submit that.
Thanks for that info. I will check that quickstart driver now.
Regards
Rainer
Signature · 19 lines
Dipl.-Inf. (FH) Rainer Koenig Project Manager Linux Clients Dept. PDG WPS R&D SW OSE Fujitsu Technology Solutions Bürgermeister-Ullrich-Str. 100 86199 Augsburg Germany Telephone: +49-821-804-3321 Telefax: +49-821-804-2131 Mail: mailto:[email protected] Internet ts.fujtsu.com Company Details ts.fujitsu.com/imprint.html -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html