diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-10 10:58:25 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-10 10:58:25 -0800 |
commit | b91867f2ee5c84b550f95ce54c91b180f70f48cb (patch) | |
tree | bd7a5be4484d539af13e6b345320455e989612cf /drivers/staging/quickstart/quickstart.c | |
parent | b05ee6bf9e6c7acc38dca1466b63bb24ae5df6f3 (diff) | |
parent | 9196dc1129fbb3ecf93027224a6bdbc86d086e3a (diff) |
Merge tag 'staging-3.3-rc3' into staging-next
This was done to resolve some merge issues with the following files that
had changed in both branches:
drivers/staging/rtl8712/rtl871x_sta_mgt.c
drivers/staging/tidspbridge/rmgr/drv_interface.c
drivers/staging/zcache/zcache-main.c
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/quickstart/quickstart.c')
-rw-r--r-- | drivers/staging/quickstart/quickstart.c | 365 |
1 files changed, 175 insertions, 190 deletions
diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index c60911c6ab3..88f8ff38662 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -4,7 +4,7 @@ * * Copyright (C) 2007-2010 Angelo Arrifano <miknix@gmail.com> * - * Information gathered from disassebled dsdt and from here: + * Information gathered from disassembled dsdt and from here: * <http://www.microsoft.com/whdc/system/platform/firmware/DirAppLaunch.mspx> * * This program is free software; you can redistribute it and/or modify @@ -25,6 +25,8 @@ #define QUICKSTART_VERSION "1.03" +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -37,118 +39,73 @@ 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_ACPI_DEVICE_NAME "quickstart" +#define QUICKSTART_ACPI_CLASS "quickstart" +#define QUICKSTART_ACPI_HID "PNP0C32" -#define QUICKSTART_MAX_BTN_NAME_LEN 16 +#define QUICKSTART_PF_DRIVER_NAME "quickstart" +#define QUICKSTART_PF_DEVICE_NAME "quickstart" -/* 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 +/* + * 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 { +struct quickstart_button { char *name; unsigned int id; - struct quickstart_btn *next; + struct list_head list; }; -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}, + struct quickstart_button *button; }; -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, - }, -}; +static LIST_HEAD(buttons); +static struct quickstart_button *pressed; -/* Input device structs */ -struct input_dev *quickstart_input; +static 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, +/* Platform driver functions */ +static ssize_t quickstart_buttons_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) + char *buf) { int count = 0; - struct quickstart_btn *ptr = quickstart_data.btn_lst; + struct quickstart_button *b; - if (!ptr) + if (list_empty(&buttons)) 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); + list_for_each_entry(b, &buttons, list) { + count += snprintf(buf + count, PAGE_SIZE - count, "%u\t%s\n", + b->id, b->name); + + if (count >= PAGE_SIZE) { + count = PAGE_SIZE; + break; } - ptr = ptr->next; } return count; } -static ssize_t pressed_button_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t quickstart_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")); + (pressed ? pressed->name : "none")); } -static ssize_t pressed_button_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t quickstart_pressed_button_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { if (count < 2) return -EINVAL; @@ -156,60 +113,40 @@ static ssize_t pressed_button_store(struct device *dev, if (strncasecmp(buf, "none", 4) != 0) return -EINVAL; - quickstart_data.pressed = NULL; + pressed = NULL; return count; } -/* Hotstart Helper functions */ -static int quickstart_btnlst_add(struct quickstart_btn **data) +/* Helper functions */ +static struct quickstart_button *quickstart_buttons_add(void) { - struct quickstart_btn **ptr = &quickstart_data.btn_lst; + struct quickstart_button *b; - while (*ptr) - ptr = &((*ptr)->next); + b = kzalloc(sizeof(*b), GFP_KERNEL); + if (!b) + return NULL; - *ptr = kzalloc(sizeof(struct quickstart_btn), GFP_KERNEL); - if (!*ptr) { - *data = NULL; - return -ENOMEM; - } - *data = *ptr; + list_add_tail(&b->list, &buttons); - return 0; + return b; } -static void quickstart_btnlst_del(struct quickstart_btn *data) +static void quickstart_button_del(struct quickstart_button *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; + list_del(&data->list); + kfree(data->name); + kfree(data); } -static void quickstart_btnlst_free(void) +static void quickstart_buttons_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); - } + struct quickstart_button *b, *n; - return; + list_for_each_entry_safe(b, n, &buttons, list) + quickstart_button_del(b); } /* ACPI Driver functions */ @@ -220,107 +157,136 @@ static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *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); + switch (event) { + case QUICKSTART_EVENT_WAKE: + pressed = quickstart->button; + break; + case QUICKSTART_EVENT_RUNTIME: + input_report_key(quickstart_input, quickstart->button->id, 1); input_sync(quickstart_input); - input_report_key(quickstart_input, quickstart->btn->id, 0); + input_report_key(quickstart_input, quickstart->button->id, 0); input_sync(quickstart_input); + break; + default: + pr_err("Unexpected ACPI event notify (%u)\n", event); + break; } - return; } -static void quickstart_acpi_ghid(struct quickstart_acpi *quickstart) +static int quickstart_acpi_ghid(struct quickstart_acpi *quickstart) { acpi_status status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - uint32_t usageid = 0; - - if (!quickstart) - return; + int ret = 0; - /* 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 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)) { + pr_err("%s GHID method failed\n", quickstart->button->name); + return -EINVAL; } - if (buffer.length < 8) - return; - - /* <<The GHID method can return a BYTE, WORD, or DWORD. + /* + * <<The GHID method can return a BYTE, WORD, or DWORD. * The value must be encoded in little-endian byte - * order (least significant byte first).>> */ - usageid = *((uint32_t *)(buffer.pointer + (buffer.length - 8))); - quickstart->btn->id = usageid; + * order (least significant byte first).>> + */ + switch (buffer.length) { + case 1: + quickstart->button->id = *(uint8_t *)buffer.pointer; + break; + case 2: + quickstart->button->id = *(uint16_t *)buffer.pointer; + break; + case 4: + quickstart->button->id = *(uint32_t *)buffer.pointer; + break; + case 8: + quickstart->button->id = *(uint64_t *)buffer.pointer; + break; + default: + pr_err("%s GHID method returned buffer of unexpected length %u\n", + quickstart->button->name, buffer.length); + ret = -EINVAL; + break; + } kfree(buffer.pointer); + + return ret; } -static int quickstart_acpi_config(struct quickstart_acpi *quickstart, char *bid) +static int quickstart_acpi_config(struct quickstart_acpi *quickstart) { - int len = strlen(bid); - int ret; + char *bid = acpi_device_bid(quickstart->device); + char *name; - /* Add button to list */ - ret = quickstart_btnlst_add(&quickstart->btn); - if (ret) - return ret; + name = kmalloc(strlen(bid) + 1, GFP_KERNEL); + if (!name) + return -ENOMEM; - quickstart->btn->name = kzalloc(len + 1, GFP_KERNEL); - if (!quickstart->btn->name) { - quickstart_btnlst_free(); + /* Add new button to list */ + quickstart->button = quickstart_buttons_add(); + if (!quickstart->button) { + kfree(name); return -ENOMEM; } - strcpy(quickstart->btn->name, bid); + + quickstart->button->name = name; + strcpy(quickstart->button->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; + int ret; + acpi_status status; + struct quickstart_acpi *quickstart; if (!device) return -EINVAL; - quickstart = kzalloc(sizeof(struct quickstart_acpi), GFP_KERNEL); + quickstart = kzalloc(sizeof(*quickstart), 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); device->driver_data = quickstart; /* Add button to list and initialize some stuff */ - ret = quickstart_acpi_config(quickstart, acpi_device_bid(device)); - if (ret) + ret = quickstart_acpi_config(quickstart); + if (ret < 0) goto fail_config; - status = acpi_install_notify_handler(device->handle, - ACPI_ALL_NOTIFY, + 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"); + pr_err("Notify handler install error\n"); ret = -ENODEV; goto fail_installnotify; } - quickstart_acpi_ghid(quickstart); + ret = quickstart_acpi_ghid(quickstart); + if (ret < 0) + goto fail_ghid; return 0; +fail_ghid: + acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, + quickstart_acpi_notify); + fail_installnotify: - quickstart_btnlst_del(quickstart->btn); + quickstart_button_del(quickstart->button); fail_config: @@ -331,28 +297,54 @@ fail_config: static int quickstart_acpi_remove(struct acpi_device *device, int type) { - acpi_status status = 0; - struct quickstart_acpi *quickstart = NULL; + acpi_status status; + struct quickstart_acpi *quickstart; - if (!device || !acpi_driver_data(device)) + if (!device) return -EINVAL; quickstart = acpi_driver_data(device); + if (!quickstart) + return -EINVAL; - status = acpi_remove_notify_handler(device->handle, - ACPI_ALL_NOTIFY, - quickstart_acpi_notify); + 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"); - + pr_err("Error removing notify handler\n"); kfree(quickstart); return 0; } -/* Module functions */ +/* Platform driver structs */ +static DEVICE_ATTR(pressed_button, 0666, quickstart_pressed_button_show, + quickstart_pressed_button_store); +static DEVICE_ATTR(buttons, 0444, quickstart_buttons_show, NULL); +static struct platform_device *pf_device; +static struct platform_driver pf_driver = { + .driver = { + .name = QUICKSTART_PF_DRIVER_NAME, + .owner = THIS_MODULE, + } +}; + +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, + }, +}; +/* Module functions */ static void quickstart_exit(void) { input_unregister_device(quickstart_input); @@ -366,15 +358,12 @@ static void quickstart_exit(void) acpi_bus_unregister_driver(&quickstart_acpi_driver); - quickstart_btnlst_free(); - - return; + quickstart_buttons_free(); } static int __init quickstart_init_input(void) { - struct quickstart_btn **ptr = &quickstart_data.btn_lst; - int count; + struct quickstart_button *b; int ret; quickstart_input = input_allocate_device(); @@ -385,11 +374,9 @@ static int __init quickstart_init_input(void) quickstart_input->name = "Quickstart ACPI Buttons"; quickstart_input->id.bustype = BUS_HOST; - while (*ptr) { - count++; + list_for_each_entry(b, &buttons, list) { set_bit(EV_KEY, quickstart_input->evbit); - set_bit((*ptr)->id, quickstart_input->keybit); - ptr = &((*ptr)->next); + set_bit(b->id, quickstart_input->keybit); } ret = input_register_device(quickstart_input); @@ -415,7 +402,7 @@ static int __init quickstart_init(void) return ret; /* If existing bus with no devices */ - if (!quickstart_data.btn_lst) { + if (list_empty(&buttons)) { ret = -ENODEV; goto fail_pfdrv_reg; } @@ -444,14 +431,12 @@ static int __init quickstart_init(void) 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); + pr_info("ACPI Direct App Launch ver %s\n", QUICKSTART_VERSION); return 0; fail_input: |