16da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano/* 26da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * quickstart.c - ACPI Direct App Launch driver 36da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * 46da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * 56da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * Copyright (C) 2007-2010 Angelo Arrifano <miknix@gmail.com> 66da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * 76da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * Information gathered from disassebled dsdt and from here: 8f94fdeaa58e54c41eb6a2d8b86585e858d44c88fTimo von Holtz * <http://www.microsoft.com/whdc/system/platform/firmware/DirAppLaunch.mspx> 96da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * 106da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * This program is free software; you can redistribute it and/or modify 116da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * it under the terms of the GNU General Public License as published by 126da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * the Free Software Foundation; either version 2 of the License, or 136da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * (at your option) any later version. 146da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * 156da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * This program is distributed in the hope that it will be useful, 166da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * but WITHOUT ANY WARRANTY; without even the implied warranty of 176da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 186da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * GNU General Public License for more details. 196da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * 206da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * You should have received a copy of the GNU General Public License 216da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * along with this program; if not, write to the Free Software 226da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 236da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * 246da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano */ 256da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 266da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#define QUICKSTART_VERSION "1.03" 276da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 286da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#include <linux/kernel.h> 296da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#include <linux/module.h> 306da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#include <linux/init.h> 316da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#include <linux/types.h> 326da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#include <acpi/acpi_drivers.h> 336da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#include <linux/platform_device.h> 346da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#include <linux/input.h> 356da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 366da4cd46902973f267fcc93325f65a93eca52ad5Angelo ArrifanoMODULE_AUTHOR("Angelo Arrifano"); 376da4cd46902973f267fcc93325f65a93eca52ad5Angelo ArrifanoMODULE_DESCRIPTION("ACPI Direct App Launch driver"); 386da4cd46902973f267fcc93325f65a93eca52ad5Angelo ArrifanoMODULE_LICENSE("GPL"); 396da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 406da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#define QUICKSTART_ACPI_DEVICE_NAME "quickstart" 416da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#define QUICKSTART_ACPI_CLASS "quickstart" 426da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#define QUICKSTART_ACPI_HID "PNP0C32" 436da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 446da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#define QUICKSTART_PF_DRIVER_NAME "quickstart" 456da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#define QUICKSTART_PF_DEVICE_NAME "quickstart" 466da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#define QUICKSTART_PF_DEVATTR_NAME "pressed_button" 476da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 486da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#define QUICKSTART_MAX_BTN_NAME_LEN 16 496da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 506da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano/* There will be two events: 516da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * 0x02 - A hot button was pressed while device was off/sleeping. 526da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * 0x80 - A hot button was pressed while device was up. */ 536da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#define QUICKSTART_EVENT_WAKE 0x02 546da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano#define QUICKSTART_EVENT_RUNTIME 0x80 556da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 566da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostruct quickstart_btn { 576da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano char *name; 586da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano unsigned int id; 596da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_btn *next; 606da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano}; 616da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 626da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic struct quickstart_driver_data { 636da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_btn *btn_lst; 646da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_btn *pressed; 656da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} quickstart_data; 666da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 676da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano/* ACPI driver Structs */ 686da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostruct quickstart_acpi { 696da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct acpi_device *device; 706da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_btn *btn; 716da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano}; 726da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic int quickstart_acpi_add(struct acpi_device *device); 736da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic int quickstart_acpi_remove(struct acpi_device *device, int type); 746da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic const struct acpi_device_id quickstart_device_ids[] = { 756da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano {QUICKSTART_ACPI_HID, 0}, 766da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano {"", 0}, 776da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano}; 786da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 796da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic struct acpi_driver quickstart_acpi_driver = { 806da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano .name = "quickstart", 816da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano .class = QUICKSTART_ACPI_CLASS, 826da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano .ids = quickstart_device_ids, 836da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano .ops = { 846da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano .add = quickstart_acpi_add, 856da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano .remove = quickstart_acpi_remove, 866da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano }, 876da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano}; 886da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 896da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano/* Input device structs */ 906da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostruct input_dev *quickstart_input; 916da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 926da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano/* Platform driver structs */ 936da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic ssize_t buttons_show(struct device *dev, 946da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct device_attribute *attr, 956da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano char *buf); 966da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic ssize_t pressed_button_show(struct device *dev, 976da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct device_attribute *attr, 986da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano char *buf); 996da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic ssize_t pressed_button_store(struct device *dev, 1006da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct device_attribute *attr, 1016da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano const char *buf, 1026da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano size_t count); 1036da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic DEVICE_ATTR(pressed_button, 0666, pressed_button_show, 1046da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano pressed_button_store); 1056da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic DEVICE_ATTR(buttons, 0444, buttons_show, NULL); 1066da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic struct platform_device *pf_device; 1076da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic struct platform_driver pf_driver = { 1086da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano .driver = { 1096da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano .name = QUICKSTART_PF_DRIVER_NAME, 1106da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano .owner = THIS_MODULE, 1116da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 1126da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano}; 1136da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1146da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano/* 1156da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * Platform driver functions 1166da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano */ 1176da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic ssize_t buttons_show(struct device *dev, 1186da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct device_attribute *attr, 1196da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano char *buf) 1206da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 1216da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano int count = 0; 1226da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_btn *ptr = quickstart_data.btn_lst; 1236da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1246da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!ptr) 1256da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return snprintf(buf, PAGE_SIZE, "none"); 1266da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1276da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano while (ptr && (count < PAGE_SIZE)) { 1286da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (ptr->name) { 1296da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano count += snprintf(buf + count, 1306da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano PAGE_SIZE - count, 1316da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano "%d\t%s\n", ptr->id, ptr->name); 1326da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 1336da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ptr = ptr->next; 1346da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 1356da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1366da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return count; 1376da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 1386da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1396da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic ssize_t pressed_button_show(struct device *dev, 1406da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct device_attribute *attr, 1416da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano char *buf) 1426da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 1436da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return snprintf(buf, PAGE_SIZE, "%s\n", 144f94fdeaa58e54c41eb6a2d8b86585e858d44c88fTimo von Holtz (quickstart_data.pressed ? 145f94fdeaa58e54c41eb6a2d8b86585e858d44c88fTimo von Holtz quickstart_data.pressed->name : "none")); 1466da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 1476da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1486da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1496da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic ssize_t pressed_button_store(struct device *dev, 1506da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct device_attribute *attr, 1516da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano const char *buf, size_t count) 1526da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 1536da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (count < 2) 1546da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return -EINVAL; 1556da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1566da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (strncasecmp(buf, "none", 4) != 0) 1576da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return -EINVAL; 1586da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1596da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart_data.pressed = NULL; 1606da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return count; 1616da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 1626da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1636da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano/* Hotstart Helper functions */ 1646da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic int quickstart_btnlst_add(struct quickstart_btn **data) 1656da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 1666da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_btn **ptr = &quickstart_data.btn_lst; 1676da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1686da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano while (*ptr) 1696da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ptr = &((*ptr)->next); 1706da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1716da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano *ptr = kzalloc(sizeof(struct quickstart_btn), GFP_KERNEL); 1726da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!*ptr) { 1736da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano *data = NULL; 1746da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return -ENOMEM; 1756da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 1766da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano *data = *ptr; 1776da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1786da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return 0; 1796da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 1806da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1816da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic void quickstart_btnlst_del(struct quickstart_btn *data) 1826da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 1836da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_btn **ptr = &quickstart_data.btn_lst; 1846da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1856da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!data) 1866da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return; 1876da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1886da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano while (*ptr) { 1896da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (*ptr == data) { 1906da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano *ptr = (*ptr)->next; 1916da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano kfree(data); 1926da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return; 1936da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 1946da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ptr = &((*ptr)->next); 1956da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 1966da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 1976da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return; 1986da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 1996da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2006da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic void quickstart_btnlst_free(void) 2016da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 2026da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_btn *ptr = quickstart_data.btn_lst; 2036da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_btn *lptr = NULL; 2046da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2056da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano while (ptr) { 2066da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano lptr = ptr; 2076da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ptr = ptr->next; 2086da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano kfree(lptr->name); 2096da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano kfree(lptr); 2106da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 2116da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2126da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return; 2136da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 2146da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2156da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano/* ACPI Driver functions */ 2166da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data) 2176da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 2186da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_acpi *quickstart = data; 2196da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2206da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!quickstart) 2216da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return; 2226da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2236da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (event == QUICKSTART_EVENT_WAKE) 2246da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart_data.pressed = quickstart->btn; 2256da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano else if (event == QUICKSTART_EVENT_RUNTIME) { 2266da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano input_report_key(quickstart_input, quickstart->btn->id, 1); 2276da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano input_sync(quickstart_input); 2286da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano input_report_key(quickstart_input, quickstart->btn->id, 0); 2296da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano input_sync(quickstart_input); 2306da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 2316da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return; 2326da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 2336da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2346da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic void quickstart_acpi_ghid(struct quickstart_acpi *quickstart) 2356da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 2366da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano acpi_status status; 2376da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 2386da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano uint32_t usageid = 0; 2396da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2406da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!quickstart) 2416da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return; 2426da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2436da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano /* This returns a buffer telling the button usage ID, 2446da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * and triggers pending notify events (The ones before booting). */ 2456da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano status = acpi_evaluate_object(quickstart->device->handle, 2466da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano "GHID", NULL, &buffer); 2476da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (ACPI_FAILURE(status) || !buffer.pointer) { 2486da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano printk(KERN_ERR "quickstart: %s GHID method failed.\n", 2496da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart->btn->name); 2506da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return; 2516da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 2526da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2536da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (buffer.length < 8) 2546da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return; 2556da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2566da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano /* <<The GHID method can return a BYTE, WORD, or DWORD. 2576da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * The value must be encoded in little-endian byte 2586da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano * order (least significant byte first).>> */ 2596da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano usageid = *((uint32_t *)(buffer.pointer + (buffer.length - 8))); 2606da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart->btn->id = usageid; 2616da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2626da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano kfree(buffer.pointer); 2636da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 2646da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2656da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic int quickstart_acpi_config(struct quickstart_acpi *quickstart, char *bid) 2666da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 2676da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano int len = strlen(bid); 2686da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano int ret; 2696da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2706da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano /* Add button to list */ 2716da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ret = quickstart_btnlst_add(&quickstart->btn); 2726da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (ret) 2736da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return ret; 2746da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2756da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart->btn->name = kzalloc(len + 1, GFP_KERNEL); 2766da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!quickstart->btn->name) { 2776da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart_btnlst_free(); 2786da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return -ENOMEM; 2796da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 2806da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano strcpy(quickstart->btn->name, bid); 2816da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2826da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return 0; 2836da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 2846da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2856da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic int quickstart_acpi_add(struct acpi_device *device) 2866da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 2876da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano int ret = 0; 2886da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano acpi_status status = AE_OK; 2896da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_acpi *quickstart = NULL; 2906da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2916da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!device) 2926da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return -EINVAL; 2936da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2946da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart = kzalloc(sizeof(struct quickstart_acpi), GFP_KERNEL); 2956da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!quickstart) 2966da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return -ENOMEM; 2976da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 2986da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart->device = device; 2996da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano strcpy(acpi_device_name(device), QUICKSTART_ACPI_DEVICE_NAME); 3006da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano strcpy(acpi_device_class(device), QUICKSTART_ACPI_CLASS); 3016da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano device->driver_data = quickstart; 3026da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3036da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano /* Add button to list and initialize some stuff */ 3046da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ret = quickstart_acpi_config(quickstart, acpi_device_bid(device)); 3056da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (ret) 3066da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano goto fail_config; 3076da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3086da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano status = acpi_install_notify_handler(device->handle, 3096da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ACPI_ALL_NOTIFY, 3106da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart_acpi_notify, 3116da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart); 3126da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (ACPI_FAILURE(status)) { 3136da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano printk(KERN_ERR "quickstart: Notify handler install error\n"); 3146da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ret = -ENODEV; 3156da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano goto fail_installnotify; 3166da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 3176da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3186da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart_acpi_ghid(quickstart); 3196da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3206da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return 0; 3216da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3226da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanofail_installnotify: 3236da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart_btnlst_del(quickstart->btn); 3246da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3256da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanofail_config: 3266da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3276da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano kfree(quickstart); 3286da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3296da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return ret; 3306da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 3316da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3326da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic int quickstart_acpi_remove(struct acpi_device *device, int type) 3336da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 3346da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano acpi_status status = 0; 3356da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_acpi *quickstart = NULL; 3366da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3376da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!device || !acpi_driver_data(device)) 3386da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return -EINVAL; 3396da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3406da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart = acpi_driver_data(device); 3416da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3426da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano status = acpi_remove_notify_handler(device->handle, 3436da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ACPI_ALL_NOTIFY, 3446da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart_acpi_notify); 3456da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (ACPI_FAILURE(status)) 3466da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano printk(KERN_ERR "quickstart: Error removing notify handler\n"); 3476da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3486da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3496da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano kfree(quickstart); 3506da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3516da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return 0; 3526da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 3536da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3546da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano/* Module functions */ 3556da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3566da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic void quickstart_exit(void) 3576da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 3586da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano input_unregister_device(quickstart_input); 3596da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3606da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano device_remove_file(&pf_device->dev, &dev_attr_pressed_button); 3616da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano device_remove_file(&pf_device->dev, &dev_attr_buttons); 3626da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3636da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano platform_device_unregister(pf_device); 3646da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3656da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano platform_driver_unregister(&pf_driver); 3666da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3676da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano acpi_bus_unregister_driver(&quickstart_acpi_driver); 3686da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3696da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart_btnlst_free(); 3706da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3716da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return; 3726da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 3736da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3746da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic int __init quickstart_init_input(void) 3756da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 3766da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano struct quickstart_btn **ptr = &quickstart_data.btn_lst; 3776da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano int count; 378ebba26f4a8d0c137a2d365b6bded2a0d7fcd1d06Dan Carpenter int ret; 3796da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3806da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart_input = input_allocate_device(); 3816da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3826da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!quickstart_input) 3836da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return -ENOMEM; 3846da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3856da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart_input->name = "Quickstart ACPI Buttons"; 3866da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano quickstart_input->id.bustype = BUS_HOST; 3876da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 3886da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano while (*ptr) { 3896da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano count++; 3906da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano set_bit(EV_KEY, quickstart_input->evbit); 3916da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano set_bit((*ptr)->id, quickstart_input->keybit); 3926da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ptr = &((*ptr)->next); 3936da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 3946da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 395ebba26f4a8d0c137a2d365b6bded2a0d7fcd1d06Dan Carpenter ret = input_register_device(quickstart_input); 396ebba26f4a8d0c137a2d365b6bded2a0d7fcd1d06Dan Carpenter if (ret) { 397ebba26f4a8d0c137a2d365b6bded2a0d7fcd1d06Dan Carpenter input_free_device(quickstart_input); 398ebba26f4a8d0c137a2d365b6bded2a0d7fcd1d06Dan Carpenter return ret; 399ebba26f4a8d0c137a2d365b6bded2a0d7fcd1d06Dan Carpenter } 400ebba26f4a8d0c137a2d365b6bded2a0d7fcd1d06Dan Carpenter 401ebba26f4a8d0c137a2d365b6bded2a0d7fcd1d06Dan Carpenter return 0; 4026da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 4036da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4046da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanostatic int __init quickstart_init(void) 4056da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano{ 4066da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano int ret; 4076da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4086da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano /* ACPI Check */ 4096da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (acpi_disabled) 4106da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return -ENODEV; 4116da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4126da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano /* ACPI driver register */ 413f0903863099668d6b03c7ea90b2e58a7ad1be6a3Dan Carpenter ret = acpi_bus_register_driver(&quickstart_acpi_driver); 414f0903863099668d6b03c7ea90b2e58a7ad1be6a3Dan Carpenter if (ret) 415f0903863099668d6b03c7ea90b2e58a7ad1be6a3Dan Carpenter return ret; 4166da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4176da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano /* If existing bus with no devices */ 4186da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!quickstart_data.btn_lst) { 4196da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ret = -ENODEV; 4206da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano goto fail_pfdrv_reg; 4216da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 4226da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4236da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano /* Platform driver register */ 4246da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ret = platform_driver_register(&pf_driver); 4256da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (ret) 4266da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano goto fail_pfdrv_reg; 4276da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4286da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano /* Platform device register */ 4296da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano pf_device = platform_device_alloc(QUICKSTART_PF_DEVICE_NAME, -1); 4306da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (!pf_device) { 4316da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ret = -ENOMEM; 4326da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano goto fail_pfdev_alloc; 4336da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano } 4346da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ret = platform_device_add(pf_device); 4356da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (ret) 4366da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano goto fail_pfdev_add; 4376da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4386da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano /* Create device sysfs file */ 4396da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ret = device_create_file(&pf_device->dev, &dev_attr_pressed_button); 4406da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (ret) 4416da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano goto fail_dev_file; 4426da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4436da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ret = device_create_file(&pf_device->dev, &dev_attr_buttons); 4446da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (ret) 4456da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano goto fail_dev_file2; 4466da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4476da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4486da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano /* Input device */ 4496da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano ret = quickstart_init_input(); 4506da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano if (ret) 4516da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano goto fail_input; 4526da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4536da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano printk(KERN_INFO "quickstart: ACPI Direct App Launch ver %s\n", 4546da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano QUICKSTART_VERSION); 4556da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4566da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return 0; 4576da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanofail_input: 4586da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano device_remove_file(&pf_device->dev, &dev_attr_buttons); 4596da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4606da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanofail_dev_file2: 4616da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano device_remove_file(&pf_device->dev, &dev_attr_pressed_button); 4626da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4636da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanofail_dev_file: 4646da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano platform_device_del(pf_device); 4656da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4666da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanofail_pfdev_add: 4676da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano platform_device_put(pf_device); 4686da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4696da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanofail_pfdev_alloc: 4706da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano platform_driver_unregister(&pf_driver); 4716da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4726da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanofail_pfdrv_reg: 4736da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano acpi_bus_unregister_driver(&quickstart_acpi_driver); 4746da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4756da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano return ret; 4766da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano} 4776da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifano 4786da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanomodule_init(quickstart_init); 4796da4cd46902973f267fcc93325f65a93eca52ad5Angelo Arrifanomodule_exit(quickstart_exit); 480