Attached patch adds input keyboard reporting to the thinkpad_acpi
driver.
This works for me using evtest /dev/input/event7, although the events do
not get to X for some reason. KEY_POWER does get to X but not KEY_FN_F1,
so I assume X is filtering the keys at some stage.
This removes ugly userspace uevent schemes and allows us to assign the
correct keys using keymaps.
Comments please.
Richard Hughes.
--- origin/thinkpad_acpi.h 2007-05-16 16:03:53.000000000 +0100
+++ thinkpad_acpi.h 2007-05-16 22:59:41.000000000 +0100
@@ -31,6 +31,7 @@
#include <linux/string.h>
#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/input.h>
#include <linux/proc_fs.h>
#include <linux/sysfs.h>
@@ -197,6 +198,7 @@ struct ibm_struct {
int (*read) (char *);
int (*write) (char *);
void (*exit) (void);
+ struct input_dev *input;
struct list_head all_drivers;
@@ -206,6 +208,7 @@ struct ibm_struct {
u8 acpi_driver_registered:1;
u8 acpi_notify_installed:1;
u8 proc_created:1;
+ u8 using_input:1;
u8 init_called:1;
u8 experimental:1;
} flags;
--- origin/thinkpad_acpi.c 2007-05-16 16:03:51.000000000 +0100
+++ thinkpad_acpi.c 2007-05-16 23:03:58.000000000 +0100
@@ -808,6 +808,53 @@ static struct attribute *hotkey_mask_att
&dev_attr_hotkey_bios_mask.attr,
};
+static int __init hotkey_init_input(struct ibm_init_struct *iibm)
+{
+ int error;
+ struct input_dev *input;
+
+ dbg_printk(TPACPI_DBG_INIT, "Trying to allocate input device\n");
+ input = input_allocate_device();
+ if (!input) {
+ printk(IBM_ERR "could not allocate input device\n");
+ error = -ENOMEM;
+ goto err_no_mem;
+ }
+
+ /* we need this later to emit and deallocate */
+ iibm->data->input = input;
+ iibm->data->flags.using_input = 1;
+
+ /* create one 'keyboard' virtual input device for all the acpi events */
+ input->name = "ThinkPad Extra Buttons";
+ input->phys = "thinkpad/input0";
+ input->id.bustype = BUS_HOST;
+ input->id.product = 0x0001;
+ input->evbit[0] = BIT(EV_KEY);
+ set_bit(KEY_FN_F1, input->keybit);
+ set_bit(KEY_FN_F2, input->keybit);
+ set_bit(KEY_FN_F3, input->keybit);
+ set_bit(KEY_FN_F4, input->keybit);
+ set_bit(KEY_FN_F5, input->keybit);
+ set_bit(KEY_FN_F6, input->keybit);
+ set_bit(KEY_FN_F7, input->keybit);
+ set_bit(KEY_FN_F8, input->keybit);
+ set_bit(KEY_FN_F9, input->keybit);
+ set_bit(KEY_FN_F10, input->keybit);
+ set_bit(KEY_FN_F11, input->keybit);
+ set_bit(KEY_FN_F12, input->keybit);
+
+ error = input_register_device(input);
+ if (error)
+ goto err_free_input;
+ return 0;
+
+err_free_input:
+ input_free_device(input);
+err_no_mem:
+ return error;
+}
+
static int __init hotkey_init(struct ibm_init_struct *iibm)
{
int res;
@@ -824,6 +871,10 @@ static int __init hotkey_init(struct ibm
str_supported(tp_features.hotkey));
if (tp_features.hotkey) {
+
+ /* we should use INPUT rather than random acpi events */
+ hotkey_init_input (iibm);
+
hotkey_dev_attributes = create_attr_set(4,
TPACPI_HOTKEY_SYSFS_GROUP);
if (!hotkey_dev_attributes)
@@ -879,10 +930,63 @@ static void hotkey_exit(void)
static void hotkey_notify(struct ibm_struct *ibm, u32 event)
{
int hkey;
+ int keycode;
- if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d"))
+ if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
acpi_bus_generate_event(ibm->acpi->device, event, hkey);
- else {
+
+ switch (hkey) {
+ case 4097:
+ keycode = KEY_FN_F1;
+ break;
+ case 4098:
+ keycode = KEY_FN_F2;
+ break;
+ case 4099:
+ keycode = KEY_FN_F3;
+ break;
+ case 4100:
+ keycode = KEY_FN_F4;
+ break;
+ case 4101:
+ keycode = KEY_FN_F5;
+ break;
+ case 4102:
+ keycode = KEY_FN_F6;
+ break;
+ case 4103:
+ keycode = KEY_FN_F7;
+ break;
+ case 4104:
+ keycode = KEY_FN_F8;
+ break;
+ case 4105:
+ keycode = KEY_FN_F9;
+ break;
+ case 4106:
+ keycode = KEY_FN_F10;
+ break;
+ case 4107:
+ keycode = KEY_FN_F11;
+ break;
+ case 4108:
+ keycode = KEY_FN_F12;
+ break;
+ case 4112:
+ keycode = KEY_F13; /* really we want KEY_FN_HOME */
+ break;
+ default:
+ keycode = KEY_UNKNOWN;
+ }
+
+ dbg_printk(TPACPI_DBG_ALL, "mapped hkey %i to keycode %i\n", hkey, keycode);
+ if (keycode != KEY_UNKNOWN) {
+ input_report_key(ibm->input, keycode, 1);
+ input_sync(ibm->input);
+ input_report_key(ibm->input, keycode, 0);
+ }
+
+ } else {
printk(IBM_ERR "unknown hotkey event %d\n", event);
acpi_bus_generate_event(ibm->acpi->device, event, 0);
}
@@ -4013,6 +4117,15 @@ static void ibm_exit(struct ibm_struct *
ibm->flags.acpi_driver_registered = 0;
}
+ if (ibm->flags.using_input) {
+ dbg_printk(TPACPI_DBG_EXIT,
+ "%s: input_free_device\n", ibm->name);
+ BUG_ON(!ibm->input);
+ input_free_device(ibm->input);
+ ibm->input = NULL;
+ ibm->flags.using_input = FALSE;
+ }
+
if (ibm->flags.init_called && ibm->exit) {
ibm->exit();
ibm->flags.init_called = 0;
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
ibm-acpi-devel mailing list
ibm-acpi-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/ibm-acpi-devel