eeepc-wmi: add an eeepc_wmi context structure

Add an eeepc_wmi context structure to manage all the sub-devices
that will be implemented later on. Put input device into it first.

Signed-off-by: Yong Wang <yong.y.wang@intel.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Reviewed-by: Corentin Chary <corentincj@iksaif.net>
This commit is contained in:
Yong Wang 2010-04-11 09:26:33 +08:00 committed by Matthew Garrett
parent 0eddb519b9
commit 8124888940
1 changed files with 46 additions and 23 deletions

View File

@ -23,6 +23,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
@ -58,10 +60,15 @@ static const struct key_entry eeepc_wmi_keymap[] = {
{ KE_END, 0}, { KE_END, 0},
}; };
static struct input_dev *eeepc_wmi_input_dev; struct eeepc_wmi {
struct input_dev *inputdev;
};
static struct eeepc_wmi *eeepc;
static void eeepc_wmi_notify(u32 value, void *context) static void eeepc_wmi_notify(u32 value, void *context)
{ {
struct eeepc_wmi *eeepc = context;
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj; union acpi_object *obj;
acpi_status status; acpi_status status;
@ -69,7 +76,7 @@ static void eeepc_wmi_notify(u32 value, void *context)
status = wmi_get_event_data(value, &response); status = wmi_get_event_data(value, &response);
if (status != AE_OK) { if (status != AE_OK) {
pr_err("EEEPC WMI: bad event status 0x%x\n", status); pr_err("bad event status 0x%x\n", status);
return; return;
} }
@ -83,64 +90,80 @@ static void eeepc_wmi_notify(u32 value, void *context)
else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX) else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
code = NOTIFY_BRNDOWN_MIN; code = NOTIFY_BRNDOWN_MIN;
if (!sparse_keymap_report_event(eeepc_wmi_input_dev, if (!sparse_keymap_report_event(eeepc->inputdev,
code, 1, true)) code, 1, true))
pr_info("EEEPC WMI: Unknown key %x pressed\n", code); pr_info("Unknown key %x pressed\n", code);
} }
kfree(obj); kfree(obj);
} }
static int eeepc_wmi_input_setup(void) static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc)
{ {
int err; int err;
eeepc_wmi_input_dev = input_allocate_device(); eeepc->inputdev = input_allocate_device();
if (!eeepc_wmi_input_dev) if (!eeepc->inputdev)
return -ENOMEM; return -ENOMEM;
eeepc_wmi_input_dev->name = "Eee PC WMI hotkeys"; eeepc->inputdev->name = "Eee PC WMI hotkeys";
eeepc_wmi_input_dev->phys = "wmi/input0"; eeepc->inputdev->phys = "wmi/input0";
eeepc_wmi_input_dev->id.bustype = BUS_HOST; eeepc->inputdev->id.bustype = BUS_HOST;
err = sparse_keymap_setup(eeepc_wmi_input_dev, eeepc_wmi_keymap, NULL); err = sparse_keymap_setup(eeepc->inputdev, eeepc_wmi_keymap, NULL);
if (err) if (err)
goto err_free_dev; goto err_free_dev;
err = input_register_device(eeepc_wmi_input_dev); err = input_register_device(eeepc->inputdev);
if (err) if (err)
goto err_free_keymap; goto err_free_keymap;
return 0; return 0;
err_free_keymap: err_free_keymap:
sparse_keymap_free(eeepc_wmi_input_dev); sparse_keymap_free(eeepc->inputdev);
err_free_dev: err_free_dev:
input_free_device(eeepc_wmi_input_dev); input_free_device(eeepc->inputdev);
return err; return err;
} }
static void eeepc_wmi_input_exit(struct eeepc_wmi *eeepc)
{
if (eeepc->inputdev) {
sparse_keymap_free(eeepc->inputdev);
input_unregister_device(eeepc->inputdev);
}
eeepc->inputdev = NULL;
}
static int __init eeepc_wmi_init(void) static int __init eeepc_wmi_init(void)
{ {
int err; int err;
acpi_status status; acpi_status status;
if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID)) { if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID)) {
pr_warning("EEEPC WMI: No known WMI GUID found\n"); pr_warning("No known WMI GUID found\n");
return -ENODEV; return -ENODEV;
} }
err = eeepc_wmi_input_setup(); eeepc = kzalloc(sizeof(struct eeepc_wmi), GFP_KERNEL);
if (err) if (!eeepc)
return -ENOMEM;
err = eeepc_wmi_input_init(eeepc);
if (err) {
kfree(eeepc);
return err; return err;
}
status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID, status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID,
eeepc_wmi_notify, NULL); eeepc_wmi_notify, eeepc);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
sparse_keymap_free(eeepc_wmi_input_dev); pr_err("Unable to register notify handler - %d\n",
input_unregister_device(eeepc_wmi_input_dev);
pr_err("EEEPC WMI: Unable to register notify handler - %d\n",
status); status);
eeepc_wmi_input_exit(eeepc);
kfree(eeepc);
return -ENODEV; return -ENODEV;
} }
@ -150,8 +173,8 @@ static int __init eeepc_wmi_init(void)
static void __exit eeepc_wmi_exit(void) static void __exit eeepc_wmi_exit(void)
{ {
wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID); wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
sparse_keymap_free(eeepc_wmi_input_dev); eeepc_wmi_input_exit(eeepc);
input_unregister_device(eeepc_wmi_input_dev); kfree(eeepc);
} }
module_init(eeepc_wmi_init); module_init(eeepc_wmi_init);