mirror of
https://github.com/fbelavenuto/arpl.git
synced 2025-12-24 14:52:05 +08:00
first commit
This commit is contained in:
BIN
addons/acpid/all/addons/acpid.tgz
Normal file
BIN
addons/acpid/all/addons/acpid.tgz
Normal file
Binary file not shown.
12
addons/acpid/install.sh
Normal file
12
addons/acpid/install.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
if [ "${1}" = "sys" ]; then
|
||||
echo "Installing module and daemon for ACPI button"
|
||||
if [ ! -f /tmpRoot/lib/modules/button.ko ]; then
|
||||
cp /modules/button.ko /tmpRoot/lib/modules/
|
||||
fi
|
||||
tar -zxvf /addons/acpid.tgz -C /tmpRoot/
|
||||
chmod 755 /tmpRoot/usr/sbin/acpid
|
||||
chmod 644 /tmpRoot/etc/acpi/events/power
|
||||
chmod 744 /tmpRoot/etc/acpi/power.sh
|
||||
chmod 744 /tmpRoot/usr/lib/systemd/system/acpid.service
|
||||
ln -sf /usr/lib/systemd/system/acpid.service /tmpRoot/etc/systemd/system/multi-user.target.wants/acpid.service
|
||||
fi
|
||||
36
addons/acpid/manifest.yml
Normal file
36
addons/acpid/manifest.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
version: 1
|
||||
name: acpid
|
||||
description: "Flexible and extensible daemon for delivering ACPI events"
|
||||
available-for:
|
||||
bromolow-3.10.108:
|
||||
install-script: "install.sh"
|
||||
copy: "all"
|
||||
modules: true
|
||||
apollolake-4.4.180:
|
||||
install-script: "install.sh"
|
||||
copy: "all"
|
||||
modules: true
|
||||
broadwell-4.4.180:
|
||||
install-script: "install.sh"
|
||||
copy: "all"
|
||||
modules: true
|
||||
broadwellnk-4.4.180:
|
||||
install-script: "install.sh"
|
||||
copy: "all"
|
||||
modules: true
|
||||
denverton-4.4.180:
|
||||
install-script: "install.sh"
|
||||
copy: "all"
|
||||
modules: true
|
||||
geminilake-4.4.180:
|
||||
install-script: "install.sh"
|
||||
copy: "all"
|
||||
modules: true
|
||||
v1000-4.4.180:
|
||||
install-script: "install.sh"
|
||||
copy: "all"
|
||||
modules: true
|
||||
purley-4.4.180:
|
||||
install-script: "install.sh"
|
||||
copy: "all"
|
||||
modules: false
|
||||
46
addons/acpid/src/3.10.108/Makefile
Normal file
46
addons/acpid/src/3.10.108/Makefile
Normal file
@@ -0,0 +1,46 @@
|
||||
#
|
||||
# Makefile for the Linux ACPI interpreter
|
||||
#
|
||||
|
||||
#
|
||||
# ACPI Boot-Time Table Parsing
|
||||
#
|
||||
#obj-$(CONFIG_X86) += blacklist.o
|
||||
|
||||
# Power management related files
|
||||
#acpi-$(CONFIG_ACPI_SLEEP) += proc.o
|
||||
|
||||
|
||||
#
|
||||
# ACPI Bus and Device Drivers
|
||||
#
|
||||
#acpi-$(CONFIG_ACPI_DOCK) += dock.o
|
||||
#acpi-$(CONFIG_X86_INTEL_LPSS) += acpi_lpss.o
|
||||
#acpi-$(CONFIG_X86) += acpi_cmos_rtc.o
|
||||
#acpi-$(CONFIG_DEBUG_FS) += debugfs.o
|
||||
acpi-$(CONFIG_ACPI_NUMA) += numa.o
|
||||
#acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
|
||||
|
||||
# These are (potentially) separate modules
|
||||
|
||||
# IPMI may be used by other drivers, so it has to initialise before them
|
||||
#obj-$(CONFIG_ACPI_IPMI) += acpi_ipmi.o
|
||||
|
||||
#obj-$(CONFIG_ACPI_AC) += ac.o
|
||||
obj-$(CONFIG_ACPI_BUTTON) += button.o
|
||||
#obj-$(CONFIG_ACPI_FAN) += fan.o
|
||||
#obj-$(CONFIG_ACPI_VIDEO) += video.o
|
||||
#obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
|
||||
#obj-$(CONFIG_ACPI_CONTAINER) += container.o
|
||||
#obj-$(CONFIG_ACPI_THERMAL) += thermal.o
|
||||
#obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
|
||||
#obj-$(CONFIG_ACPI_BATTERY) += battery.o
|
||||
#obj-$(CONFIG_ACPI_SBS) += sbshc.o
|
||||
#obj-$(CONFIG_ACPI_SBS) += sbs.o
|
||||
#obj-$(CONFIG_ACPI_HED) += hed.o
|
||||
#obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
|
||||
#obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
|
||||
#obj-$(CONFIG_ACPI_BGRT) += bgrt.o
|
||||
#obj-$(CONFIG_ACPI_I2C) += acpi_i2c.o
|
||||
|
||||
#obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
|
||||
454
addons/acpid/src/3.10.108/button.c
Normal file
454
addons/acpid/src/3.10.108/button.c
Normal file
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
* button.c - ACPI Button Driver
|
||||
*
|
||||
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
|
||||
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <acpi/button.h>
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
#define ACPI_BUTTON_CLASS "button"
|
||||
#define ACPI_BUTTON_FILE_INFO "info"
|
||||
#define ACPI_BUTTON_FILE_STATE "state"
|
||||
#define ACPI_BUTTON_TYPE_UNKNOWN 0x00
|
||||
#define ACPI_BUTTON_NOTIFY_STATUS 0x80
|
||||
|
||||
#define ACPI_BUTTON_SUBCLASS_POWER "power"
|
||||
#define ACPI_BUTTON_HID_POWER "PNP0C0C"
|
||||
#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button"
|
||||
#define ACPI_BUTTON_TYPE_POWER 0x01
|
||||
|
||||
#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep"
|
||||
#define ACPI_BUTTON_HID_SLEEP "PNP0C0E"
|
||||
#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button"
|
||||
#define ACPI_BUTTON_TYPE_SLEEP 0x03
|
||||
|
||||
#define ACPI_BUTTON_SUBCLASS_LID "lid"
|
||||
#define ACPI_BUTTON_HID_LID "PNP0C0D"
|
||||
#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch"
|
||||
#define ACPI_BUTTON_TYPE_LID 0x05
|
||||
|
||||
#define _COMPONENT ACPI_BUTTON_COMPONENT
|
||||
ACPI_MODULE_NAME("button");
|
||||
|
||||
MODULE_AUTHOR("Paul Diefenbaugh");
|
||||
MODULE_DESCRIPTION("ACPI Button Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static const struct acpi_device_id button_device_ids[] = {
|
||||
{ACPI_BUTTON_HID_LID, 0},
|
||||
{ACPI_BUTTON_HID_SLEEP, 0},
|
||||
{ACPI_BUTTON_HID_SLEEPF, 0},
|
||||
{ACPI_BUTTON_HID_POWER, 0},
|
||||
{ACPI_BUTTON_HID_POWERF, 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, button_device_ids);
|
||||
|
||||
static int acpi_button_add(struct acpi_device *device);
|
||||
static int acpi_button_remove(struct acpi_device *device);
|
||||
static void acpi_button_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int acpi_button_resume(struct device *dev);
|
||||
#endif
|
||||
static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume);
|
||||
|
||||
static struct acpi_driver acpi_button_driver = {
|
||||
.name = "button",
|
||||
.class = ACPI_BUTTON_CLASS,
|
||||
.ids = button_device_ids,
|
||||
.ops = {
|
||||
.add = acpi_button_add,
|
||||
.remove = acpi_button_remove,
|
||||
.notify = acpi_button_notify,
|
||||
},
|
||||
.drv.pm = &acpi_button_pm,
|
||||
};
|
||||
|
||||
struct acpi_button {
|
||||
unsigned int type;
|
||||
struct input_dev *input;
|
||||
char phys[32]; /* for input device */
|
||||
unsigned long pushed;
|
||||
bool wakeup_enabled;
|
||||
};
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
|
||||
static struct acpi_device *lid_device;
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
FS Interface (/proc)
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
static struct proc_dir_entry *acpi_button_dir;
|
||||
static struct proc_dir_entry *acpi_lid_dir;
|
||||
|
||||
static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct acpi_device *device = seq->private;
|
||||
acpi_status status;
|
||||
unsigned long long state;
|
||||
|
||||
status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state);
|
||||
seq_printf(seq, "state: %s\n",
|
||||
ACPI_FAILURE(status) ? "unsupported" :
|
||||
(state ? "open" : "closed"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_button_state_open_fs(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, acpi_button_state_seq_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct file_operations acpi_button_state_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = acpi_button_state_open_fs,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int acpi_button_add_fs(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
struct proc_dir_entry *entry = NULL;
|
||||
int ret = 0;
|
||||
|
||||
/* procfs I/F for ACPI lid device only */
|
||||
if (button->type != ACPI_BUTTON_TYPE_LID)
|
||||
return 0;
|
||||
|
||||
if (acpi_button_dir || acpi_lid_dir) {
|
||||
printk(KERN_ERR PREFIX "More than one Lid device found!\n");
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
/* create /proc/acpi/button */
|
||||
acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
|
||||
if (!acpi_button_dir)
|
||||
return -ENODEV;
|
||||
|
||||
/* create /proc/acpi/button/lid */
|
||||
acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
|
||||
if (!acpi_lid_dir) {
|
||||
ret = -ENODEV;
|
||||
goto remove_button_dir;
|
||||
}
|
||||
|
||||
/* create /proc/acpi/button/lid/LID/ */
|
||||
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir);
|
||||
if (!acpi_device_dir(device)) {
|
||||
ret = -ENODEV;
|
||||
goto remove_lid_dir;
|
||||
}
|
||||
|
||||
/* create /proc/acpi/button/lid/LID/state */
|
||||
entry = proc_create_data(ACPI_BUTTON_FILE_STATE,
|
||||
S_IRUGO, acpi_device_dir(device),
|
||||
&acpi_button_state_fops, device);
|
||||
if (!entry) {
|
||||
ret = -ENODEV;
|
||||
goto remove_dev_dir;
|
||||
}
|
||||
|
||||
done:
|
||||
return ret;
|
||||
|
||||
remove_dev_dir:
|
||||
remove_proc_entry(acpi_device_bid(device),
|
||||
acpi_lid_dir);
|
||||
acpi_device_dir(device) = NULL;
|
||||
remove_lid_dir:
|
||||
remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
|
||||
remove_button_dir:
|
||||
remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
|
||||
goto done;
|
||||
}
|
||||
|
||||
static int acpi_button_remove_fs(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
if (button->type != ACPI_BUTTON_TYPE_LID)
|
||||
return 0;
|
||||
|
||||
remove_proc_entry(ACPI_BUTTON_FILE_STATE,
|
||||
acpi_device_dir(device));
|
||||
remove_proc_entry(acpi_device_bid(device),
|
||||
acpi_lid_dir);
|
||||
acpi_device_dir(device) = NULL;
|
||||
remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
|
||||
remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Driver Interface
|
||||
-------------------------------------------------------------------------- */
|
||||
int acpi_lid_notifier_register(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_register(&acpi_lid_notifier, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_lid_notifier_register);
|
||||
|
||||
int acpi_lid_notifier_unregister(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_unregister(&acpi_lid_notifier, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_lid_notifier_unregister);
|
||||
|
||||
int acpi_lid_open(void)
|
||||
{
|
||||
acpi_status status;
|
||||
unsigned long long state;
|
||||
|
||||
if (!lid_device)
|
||||
return -ENODEV;
|
||||
|
||||
status = acpi_evaluate_integer(lid_device->handle, "_LID", NULL,
|
||||
&state);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
return !!state;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_lid_open);
|
||||
|
||||
static int acpi_lid_send_state(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
unsigned long long state;
|
||||
acpi_status status;
|
||||
int ret;
|
||||
|
||||
status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
/* input layer checks if event is redundant */
|
||||
input_report_switch(button->input, SW_LID, !state);
|
||||
input_sync(button->input);
|
||||
|
||||
if (state)
|
||||
pm_wakeup_event(&device->dev, 0);
|
||||
|
||||
ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
|
||||
if (ret == NOTIFY_DONE)
|
||||
ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
|
||||
device);
|
||||
if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
|
||||
/*
|
||||
* It is also regarded as success if the notifier_chain
|
||||
* returns NOTIFY_OK or NOTIFY_DONE.
|
||||
*/
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void acpi_button_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
struct input_dev *input;
|
||||
|
||||
switch (event) {
|
||||
case ACPI_FIXED_HARDWARE_EVENT:
|
||||
event = ACPI_BUTTON_NOTIFY_STATUS;
|
||||
/* fall through */
|
||||
case ACPI_BUTTON_NOTIFY_STATUS:
|
||||
input = button->input;
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID) {
|
||||
acpi_lid_send_state(device);
|
||||
} else {
|
||||
int keycode = test_bit(KEY_SLEEP, input->keybit) ?
|
||||
KEY_SLEEP : KEY_POWER;
|
||||
|
||||
input_report_key(input, keycode, 1);
|
||||
input_sync(input);
|
||||
input_report_key(input, keycode, 0);
|
||||
input_sync(input);
|
||||
|
||||
pm_wakeup_event(&device->dev, 0);
|
||||
}
|
||||
|
||||
acpi_bus_generate_proc_event(device, event, ++button->pushed);
|
||||
break;
|
||||
default:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Unsupported event [0x%x]\n", event));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int acpi_button_resume(struct device *dev)
|
||||
{
|
||||
struct acpi_device *device = to_acpi_device(dev);
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID)
|
||||
return acpi_lid_send_state(device);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int acpi_button_add(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button;
|
||||
struct input_dev *input;
|
||||
const char *hid = acpi_device_hid(device);
|
||||
char *name, *class;
|
||||
int error;
|
||||
|
||||
button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
|
||||
if (!button)
|
||||
return -ENOMEM;
|
||||
|
||||
device->driver_data = button;
|
||||
|
||||
button->input = input = input_allocate_device();
|
||||
if (!input) {
|
||||
error = -ENOMEM;
|
||||
goto err_free_button;
|
||||
}
|
||||
|
||||
name = acpi_device_name(device);
|
||||
class = acpi_device_class(device);
|
||||
|
||||
if (!strcmp(hid, ACPI_BUTTON_HID_POWER) ||
|
||||
!strcmp(hid, ACPI_BUTTON_HID_POWERF)) {
|
||||
button->type = ACPI_BUTTON_TYPE_POWER;
|
||||
strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER);
|
||||
sprintf(class, "%s/%s",
|
||||
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
|
||||
} else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) ||
|
||||
!strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) {
|
||||
button->type = ACPI_BUTTON_TYPE_SLEEP;
|
||||
strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP);
|
||||
sprintf(class, "%s/%s",
|
||||
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
|
||||
} else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) {
|
||||
button->type = ACPI_BUTTON_TYPE_LID;
|
||||
strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
|
||||
sprintf(class, "%s/%s",
|
||||
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
|
||||
} else {
|
||||
printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
|
||||
error = -ENODEV;
|
||||
goto err_free_input;
|
||||
}
|
||||
|
||||
error = acpi_button_add_fs(device);
|
||||
if (error)
|
||||
goto err_free_input;
|
||||
|
||||
snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
|
||||
|
||||
input->name = name;
|
||||
input->phys = button->phys;
|
||||
input->id.bustype = BUS_HOST;
|
||||
input->id.product = button->type;
|
||||
input->dev.parent = &device->dev;
|
||||
|
||||
switch (button->type) {
|
||||
case ACPI_BUTTON_TYPE_POWER:
|
||||
input->evbit[0] = BIT_MASK(EV_KEY);
|
||||
set_bit(KEY_POWER, input->keybit);
|
||||
break;
|
||||
|
||||
case ACPI_BUTTON_TYPE_SLEEP:
|
||||
input->evbit[0] = BIT_MASK(EV_KEY);
|
||||
set_bit(KEY_SLEEP, input->keybit);
|
||||
break;
|
||||
|
||||
case ACPI_BUTTON_TYPE_LID:
|
||||
input->evbit[0] = BIT_MASK(EV_SW);
|
||||
set_bit(SW_LID, input->swbit);
|
||||
break;
|
||||
}
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error)
|
||||
goto err_remove_fs;
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID) {
|
||||
acpi_lid_send_state(device);
|
||||
/*
|
||||
* This assumes there's only one lid device, or if there are
|
||||
* more we only care about the last one...
|
||||
*/
|
||||
lid_device = device;
|
||||
}
|
||||
|
||||
if (device->wakeup.flags.valid) {
|
||||
/* Button's GPE is run-wake GPE */
|
||||
acpi_enable_gpe(device->wakeup.gpe_device,
|
||||
device->wakeup.gpe_number);
|
||||
if (!device_may_wakeup(&device->dev)) {
|
||||
device_set_wakeup_enable(&device->dev, true);
|
||||
button->wakeup_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
|
||||
return 0;
|
||||
|
||||
err_remove_fs:
|
||||
acpi_button_remove_fs(device);
|
||||
err_free_input:
|
||||
input_free_device(input);
|
||||
err_free_button:
|
||||
kfree(button);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int acpi_button_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
if (device->wakeup.flags.valid) {
|
||||
acpi_disable_gpe(device->wakeup.gpe_device,
|
||||
device->wakeup.gpe_number);
|
||||
if (button->wakeup_enabled)
|
||||
device_set_wakeup_enable(&device->dev, false);
|
||||
}
|
||||
|
||||
acpi_button_remove_fs(device);
|
||||
input_unregister_device(button->input);
|
||||
kfree(button);
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_acpi_driver(acpi_button_driver);
|
||||
1
addons/acpid/src/4.4.180/Makefile
Normal file
1
addons/acpid/src/4.4.180/Makefile
Normal file
@@ -0,0 +1 @@
|
||||
obj-$(CONFIG_ACPI_BUTTON) += button.o
|
||||
0
addons/acpid/src/4.4.180/Module.symvers
Normal file
0
addons/acpid/src/4.4.180/Module.symvers
Normal file
449
addons/acpid/src/4.4.180/button.c
Normal file
449
addons/acpid/src/4.4.180/button.c
Normal file
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* button.c - ACPI Button Driver
|
||||
*
|
||||
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
|
||||
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <acpi/button.h>
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
#define ACPI_BUTTON_CLASS "button"
|
||||
#define ACPI_BUTTON_FILE_INFO "info"
|
||||
#define ACPI_BUTTON_FILE_STATE "state"
|
||||
#define ACPI_BUTTON_TYPE_UNKNOWN 0x00
|
||||
#define ACPI_BUTTON_NOTIFY_STATUS 0x80
|
||||
|
||||
#define ACPI_BUTTON_SUBCLASS_POWER "power"
|
||||
#define ACPI_BUTTON_HID_POWER "PNP0C0C"
|
||||
#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button"
|
||||
#define ACPI_BUTTON_TYPE_POWER 0x01
|
||||
|
||||
#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep"
|
||||
#define ACPI_BUTTON_HID_SLEEP "PNP0C0E"
|
||||
#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button"
|
||||
#define ACPI_BUTTON_TYPE_SLEEP 0x03
|
||||
|
||||
#define ACPI_BUTTON_SUBCLASS_LID "lid"
|
||||
#define ACPI_BUTTON_HID_LID "PNP0C0D"
|
||||
#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch"
|
||||
#define ACPI_BUTTON_TYPE_LID 0x05
|
||||
|
||||
#define _COMPONENT ACPI_BUTTON_COMPONENT
|
||||
ACPI_MODULE_NAME("button");
|
||||
|
||||
MODULE_AUTHOR("Paul Diefenbaugh");
|
||||
MODULE_DESCRIPTION("ACPI Button Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static const struct acpi_device_id button_device_ids[] = {
|
||||
{ACPI_BUTTON_HID_LID, 0},
|
||||
{ACPI_BUTTON_HID_SLEEP, 0},
|
||||
{ACPI_BUTTON_HID_SLEEPF, 0},
|
||||
{ACPI_BUTTON_HID_POWER, 0},
|
||||
{ACPI_BUTTON_HID_POWERF, 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, button_device_ids);
|
||||
|
||||
static int acpi_button_add(struct acpi_device *device);
|
||||
static int acpi_button_remove(struct acpi_device *device);
|
||||
static void acpi_button_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int acpi_button_suspend(struct device *dev);
|
||||
static int acpi_button_resume(struct device *dev);
|
||||
#else
|
||||
#define acpi_button_suspend NULL
|
||||
#define acpi_button_resume NULL
|
||||
#endif
|
||||
static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume);
|
||||
|
||||
static struct acpi_driver acpi_button_driver = {
|
||||
.name = "button",
|
||||
.class = ACPI_BUTTON_CLASS,
|
||||
.ids = button_device_ids,
|
||||
.ops = {
|
||||
.add = acpi_button_add,
|
||||
.remove = acpi_button_remove,
|
||||
.notify = acpi_button_notify,
|
||||
},
|
||||
.drv.pm = &acpi_button_pm,
|
||||
};
|
||||
|
||||
struct acpi_button {
|
||||
unsigned int type;
|
||||
struct input_dev *input;
|
||||
char phys[32]; /* for input device */
|
||||
unsigned long pushed;
|
||||
bool suspended;
|
||||
};
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
|
||||
static struct acpi_device *lid_device;
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
FS Interface (/proc)
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
static struct proc_dir_entry *acpi_button_dir;
|
||||
static struct proc_dir_entry *acpi_lid_dir;
|
||||
|
||||
static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct acpi_device *device = seq->private;
|
||||
acpi_status status;
|
||||
unsigned long long state;
|
||||
|
||||
status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state);
|
||||
seq_printf(seq, "state: %s\n",
|
||||
ACPI_FAILURE(status) ? "unsupported" :
|
||||
(state ? "open" : "closed"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_button_state_open_fs(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, acpi_button_state_seq_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct file_operations acpi_button_state_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = acpi_button_state_open_fs,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int acpi_button_add_fs(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
struct proc_dir_entry *entry = NULL;
|
||||
int ret = 0;
|
||||
|
||||
/* procfs I/F for ACPI lid device only */
|
||||
if (button->type != ACPI_BUTTON_TYPE_LID)
|
||||
return 0;
|
||||
|
||||
if (acpi_button_dir || acpi_lid_dir) {
|
||||
printk(KERN_ERR PREFIX "More than one Lid device found!\n");
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
/* create /proc/acpi/button */
|
||||
acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
|
||||
if (!acpi_button_dir)
|
||||
return -ENODEV;
|
||||
|
||||
/* create /proc/acpi/button/lid */
|
||||
acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
|
||||
if (!acpi_lid_dir) {
|
||||
ret = -ENODEV;
|
||||
goto remove_button_dir;
|
||||
}
|
||||
|
||||
/* create /proc/acpi/button/lid/LID/ */
|
||||
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir);
|
||||
if (!acpi_device_dir(device)) {
|
||||
ret = -ENODEV;
|
||||
goto remove_lid_dir;
|
||||
}
|
||||
|
||||
/* create /proc/acpi/button/lid/LID/state */
|
||||
entry = proc_create_data(ACPI_BUTTON_FILE_STATE,
|
||||
S_IRUGO, acpi_device_dir(device),
|
||||
&acpi_button_state_fops, device);
|
||||
if (!entry) {
|
||||
ret = -ENODEV;
|
||||
goto remove_dev_dir;
|
||||
}
|
||||
|
||||
done:
|
||||
return ret;
|
||||
|
||||
remove_dev_dir:
|
||||
remove_proc_entry(acpi_device_bid(device),
|
||||
acpi_lid_dir);
|
||||
acpi_device_dir(device) = NULL;
|
||||
remove_lid_dir:
|
||||
remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
|
||||
remove_button_dir:
|
||||
remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
|
||||
goto done;
|
||||
}
|
||||
|
||||
static int acpi_button_remove_fs(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
if (button->type != ACPI_BUTTON_TYPE_LID)
|
||||
return 0;
|
||||
|
||||
remove_proc_entry(ACPI_BUTTON_FILE_STATE,
|
||||
acpi_device_dir(device));
|
||||
remove_proc_entry(acpi_device_bid(device),
|
||||
acpi_lid_dir);
|
||||
acpi_device_dir(device) = NULL;
|
||||
remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
|
||||
remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Driver Interface
|
||||
-------------------------------------------------------------------------- */
|
||||
int acpi_lid_notifier_register(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_register(&acpi_lid_notifier, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_lid_notifier_register);
|
||||
|
||||
int acpi_lid_notifier_unregister(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_unregister(&acpi_lid_notifier, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_lid_notifier_unregister);
|
||||
|
||||
int acpi_lid_open(void)
|
||||
{
|
||||
acpi_status status;
|
||||
unsigned long long state;
|
||||
|
||||
if (!lid_device)
|
||||
return -ENODEV;
|
||||
|
||||
status = acpi_evaluate_integer(lid_device->handle, "_LID", NULL,
|
||||
&state);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
return !!state;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_lid_open);
|
||||
|
||||
static int acpi_lid_send_state(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
unsigned long long state;
|
||||
acpi_status status;
|
||||
int ret;
|
||||
|
||||
status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
/* input layer checks if event is redundant */
|
||||
input_report_switch(button->input, SW_LID, !state);
|
||||
input_sync(button->input);
|
||||
|
||||
if (state)
|
||||
pm_wakeup_event(&device->dev, 0);
|
||||
|
||||
ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
|
||||
if (ret == NOTIFY_DONE)
|
||||
ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
|
||||
device);
|
||||
if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
|
||||
/*
|
||||
* It is also regarded as success if the notifier_chain
|
||||
* returns NOTIFY_OK or NOTIFY_DONE.
|
||||
*/
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void acpi_button_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
struct input_dev *input;
|
||||
|
||||
switch (event) {
|
||||
case ACPI_FIXED_HARDWARE_EVENT:
|
||||
event = ACPI_BUTTON_NOTIFY_STATUS;
|
||||
/* fall through */
|
||||
case ACPI_BUTTON_NOTIFY_STATUS:
|
||||
input = button->input;
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID) {
|
||||
acpi_lid_send_state(device);
|
||||
} else {
|
||||
int keycode;
|
||||
|
||||
pm_wakeup_event(&device->dev, 0);
|
||||
if (button->suspended)
|
||||
break;
|
||||
|
||||
keycode = test_bit(KEY_SLEEP, input->keybit) ?
|
||||
KEY_SLEEP : KEY_POWER;
|
||||
input_report_key(input, keycode, 1);
|
||||
input_sync(input);
|
||||
input_report_key(input, keycode, 0);
|
||||
input_sync(input);
|
||||
|
||||
acpi_bus_generate_netlink_event(
|
||||
device->pnp.device_class,
|
||||
dev_name(&device->dev),
|
||||
event, ++button->pushed);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Unsupported event [0x%x]\n", event));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int acpi_button_suspend(struct device *dev)
|
||||
{
|
||||
struct acpi_device *device = to_acpi_device(dev);
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
button->suspended = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_button_resume(struct device *dev)
|
||||
{
|
||||
struct acpi_device *device = to_acpi_device(dev);
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
button->suspended = false;
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID)
|
||||
return acpi_lid_send_state(device);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int acpi_button_add(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button;
|
||||
struct input_dev *input;
|
||||
const char *hid = acpi_device_hid(device);
|
||||
char *name, *class;
|
||||
int error;
|
||||
|
||||
button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
|
||||
if (!button)
|
||||
return -ENOMEM;
|
||||
|
||||
device->driver_data = button;
|
||||
|
||||
button->input = input = input_allocate_device();
|
||||
if (!input) {
|
||||
error = -ENOMEM;
|
||||
goto err_free_button;
|
||||
}
|
||||
|
||||
name = acpi_device_name(device);
|
||||
class = acpi_device_class(device);
|
||||
|
||||
if (!strcmp(hid, ACPI_BUTTON_HID_POWER) ||
|
||||
!strcmp(hid, ACPI_BUTTON_HID_POWERF)) {
|
||||
button->type = ACPI_BUTTON_TYPE_POWER;
|
||||
strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER);
|
||||
sprintf(class, "%s/%s",
|
||||
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
|
||||
} else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) ||
|
||||
!strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) {
|
||||
button->type = ACPI_BUTTON_TYPE_SLEEP;
|
||||
strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP);
|
||||
sprintf(class, "%s/%s",
|
||||
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
|
||||
} else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) {
|
||||
button->type = ACPI_BUTTON_TYPE_LID;
|
||||
strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
|
||||
sprintf(class, "%s/%s",
|
||||
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
|
||||
} else {
|
||||
printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
|
||||
error = -ENODEV;
|
||||
goto err_free_input;
|
||||
}
|
||||
|
||||
error = acpi_button_add_fs(device);
|
||||
if (error)
|
||||
goto err_free_input;
|
||||
|
||||
snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
|
||||
|
||||
input->name = name;
|
||||
input->phys = button->phys;
|
||||
input->id.bustype = BUS_HOST;
|
||||
input->id.product = button->type;
|
||||
input->dev.parent = &device->dev;
|
||||
|
||||
switch (button->type) {
|
||||
case ACPI_BUTTON_TYPE_POWER:
|
||||
input_set_capability(input, EV_KEY, KEY_POWER);
|
||||
break;
|
||||
|
||||
case ACPI_BUTTON_TYPE_SLEEP:
|
||||
input_set_capability(input, EV_KEY, KEY_SLEEP);
|
||||
break;
|
||||
|
||||
case ACPI_BUTTON_TYPE_LID:
|
||||
input_set_capability(input, EV_SW, SW_LID);
|
||||
break;
|
||||
}
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error)
|
||||
goto err_remove_fs;
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID) {
|
||||
acpi_lid_send_state(device);
|
||||
/*
|
||||
* This assumes there's only one lid device, or if there are
|
||||
* more we only care about the last one...
|
||||
*/
|
||||
lid_device = device;
|
||||
}
|
||||
|
||||
printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
|
||||
return 0;
|
||||
|
||||
err_remove_fs:
|
||||
acpi_button_remove_fs(device);
|
||||
err_free_input:
|
||||
input_free_device(input);
|
||||
err_free_button:
|
||||
kfree(button);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int acpi_button_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
acpi_button_remove_fs(device);
|
||||
input_unregister_device(button->input);
|
||||
kfree(button);
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_acpi_driver(acpi_button_driver);
|
||||
0
addons/acpid/src/4.4.180/modules.order
Normal file
0
addons/acpid/src/4.4.180/modules.order
Normal file
Reference in New Issue
Block a user