/****************************************************************************
  ****************************************************************************
  *
- * Device model: hwmon and platform
+ * Device model: input, hwmon and platform
  *
  ****************************************************************************
  ****************************************************************************/
 
 static struct platform_device *tpacpi_pdev;
 static struct class_device *tpacpi_hwmon;
+static struct input_dev *tpacpi_inputdev;
 
 static struct platform_driver tpacpi_pdriver = {
        .driver = {
                thinkpad_acpi_module_exit();
                return ret;
        }
+       tpacpi_inputdev = input_allocate_device();
+       if (!tpacpi_inputdev) {
+               printk(IBM_ERR "unable to allocate input device\n");
+               thinkpad_acpi_module_exit();
+               return -ENOMEM;
+       } else {
+               /* Prepare input device, but don't register */
+               tpacpi_inputdev->name = "ThinkPad Extra Buttons";
+               tpacpi_inputdev->phys = IBM_DRVR_NAME "/input0";
+               tpacpi_inputdev->id.bustype = BUS_HOST;
+               tpacpi_inputdev->id.vendor = TPACPI_HKEY_INPUT_VENDOR;
+               tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
+               tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
+       }
        for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
                ret = ibm_init(&ibms_init[i]);
                if (ret >= 0 && *ibms_init[i].param)
                        return ret;
                }
        }
+       ret = input_register_device(tpacpi_inputdev);
+       if (ret < 0) {
+               printk(IBM_ERR "unable to register input device\n");
+               thinkpad_acpi_module_exit();
+               return ret;
+       } else {
+               tp_features.input_device_registered = 1;
+       }
 
        return 0;
 }
 
        dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
 
+       if (tpacpi_inputdev) {
+               if (tp_features.input_device_registered)
+                       input_unregister_device(tpacpi_inputdev);
+               else
+                       input_free_device(tpacpi_inputdev);
+       }
+
        if (tpacpi_hwmon)
                hwmon_device_unregister(tpacpi_hwmon);
 
 
 #include <linux/platform_device.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/input.h>
 #include <asm/uaccess.h>
 
 #include <linux/dmi.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acnamesp.h>
 
+#include <linux/pci_ids.h>
 
 /****************************************************************************
  * Main driver
 #define vdbg_printk(a_dbg_level, format, arg...)
 #endif
 
+/* Input IDs */
+#define TPACPI_HKEY_INPUT_VENDOR       PCI_VENDOR_ID_IBM
+#define TPACPI_HKEY_INPUT_PRODUCT      0x5054 /* "TP" */
+#define TPACPI_HKEY_INPUT_VERSION      0x4101
+
 /* ACPI HIDs */
 #define IBM_HKEY_HID    "IBM0068"
 #define IBM_PCI_HID     "PNP0A03"
 static struct platform_device *tpacpi_pdev;
 static struct class_device *tpacpi_hwmon;
 static struct platform_driver tpacpi_pdriver;
+static struct input_dev *tpacpi_inputdev;
 static int tpacpi_create_driver_attributes(struct device_driver *drv);
 static void tpacpi_remove_driver_attributes(struct device_driver *drv);
 
        u16 light_status:1;
        u16 wan:1;
        u16 fan_ctrl_status_undef:1;
+       u16 input_device_registered:1;
 } tp_features;
 
 static struct list_head tpacpi_all_drivers;