asus_acpi.c
来自「linux 内核源代码」· C语言 代码 · 共 1,425 行 · 第 1/3 页
C
1,425 行
/* * asus_acpi.c - Asus Laptop ACPI Extras * * * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor * * 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 * * * The development page for this driver is located at * http://sourceforge.net/projects/acpi4asus/ * * Credits: * Pontus Fuchs - Helper functions, cleanup * Johann Wiesner - Small compile fixes * John Belmonte - ACPI code for Toshiba laptop was a good starting point. * �ic Burghard - LED display support for W1N * */#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/proc_fs.h>#include <linux/backlight.h>#include <acpi/acpi_drivers.h>#include <acpi/acpi_bus.h>#include <asm/uaccess.h>#define ASUS_ACPI_VERSION "0.30"#define PROC_ASUS "asus" //the directory#define PROC_MLED "mled"#define PROC_WLED "wled"#define PROC_TLED "tled"#define PROC_BT "bluetooth"#define PROC_LEDD "ledd"#define PROC_INFO "info"#define PROC_LCD "lcd"#define PROC_BRN "brn"#define PROC_DISP "disp"#define ACPI_HOTK_NAME "Asus Laptop ACPI Extras Driver"#define ACPI_HOTK_CLASS "hotkey"#define ACPI_HOTK_DEVICE_NAME "Hotkey"/* * Some events we use, same for all Asus */#define BR_UP 0x10#define BR_DOWN 0x20/* * Flags for hotk status */#define MLED_ON 0x01 //mail LED#define WLED_ON 0x02 //wireless LED#define TLED_ON 0x04 //touchpad LED#define BT_ON 0x08 //internal BluetoothMODULE_AUTHOR("Julien Lerouge, Karol Kozimor");MODULE_DESCRIPTION(ACPI_HOTK_NAME);MODULE_LICENSE("GPL");static uid_t asus_uid;static gid_t asus_gid;module_param(asus_uid, uint, 0);MODULE_PARM_DESC(asus_uid, "UID for entries in /proc/acpi/asus.\n");module_param(asus_gid, uint, 0);MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus.\n");/* For each model, all features implemented, * those marked with R are relative to HOTK, A for absolute */struct model_data { char *name; //name of the laptop________________A char *mt_mled; //method to handle mled_____________R char *mled_status; //node to handle mled reading_______A char *mt_wled; //method to handle wled_____________R char *wled_status; //node to handle wled reading_______A char *mt_tled; //method to handle tled_____________R char *tled_status; //node to handle tled reading_______A char *mt_ledd; //method to handle LED display______R char *mt_bt_switch; //method to switch Bluetooth on/off_R char *bt_status; //no model currently supports this__? char *mt_lcd_switch; //method to turn LCD on/off_________A char *lcd_status; //node to read LCD panel state______A char *brightness_up; //method to set brightness up_______A char *brightness_down; //guess what ?______________________A char *brightness_set; //method to set absolute brightness_R char *brightness_get; //method to get absolute brightness_R char *brightness_status; //node to get brightness____________A char *display_set; //method to set video output________R char *display_get; //method to get video output________R};/* * This is the main structure, we can use it to store anything interesting * about the hotk device */struct asus_hotk { struct acpi_device *device; //the device we are in acpi_handle handle; //the handle of the hotk device char status; //status of the hotk, for LEDs, ... u32 ledd_status; //status of the LED display struct model_data *methods; //methods available on the laptop u8 brightness; //brightness level enum { A1x = 0, //A1340D, A1300F A2x, //A2500H A4G, //A4700G D1x, //D1 L2D, //L2000D L3C, //L3800C L3D, //L3400D L3H, //L3H, L2000E, L5D L4R, //L4500R L5x, //L5800C L8L, //L8400L M1A, //M1300A M2E, //M2400E, L4400L M6N, //M6800N, W3400N M6R, //M6700R, A3000G P30, //Samsung P30 S1x, //S1300A, but also L1400B and M2400A (L84F) S2x, //S200 (J1 reported), Victor MP-XP7210 W1N, //W1000N W5A, //W5A W3V, //W3030V xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N A4S, //Z81sp //(Centrino) END_MODEL } model; //Models currently supported u16 event_count[128]; //count for each event TODO make this better};/* Here we go */#define A1x_PREFIX "\\_SB.PCI0.ISA.EC0."#define L3C_PREFIX "\\_SB.PCI0.PX40.ECD0."#define M1A_PREFIX "\\_SB.PCI0.PX40.EC0."#define P30_PREFIX "\\_SB.PCI0.LPCB.EC0."#define S1x_PREFIX "\\_SB.PCI0.PX40."#define S2x_PREFIX A1x_PREFIX#define xxN_PREFIX "\\_SB.PCI0.SBRG.EC0."static struct model_data model_conf[END_MODEL] = { /* * TODO I have seen a SWBX and AIBX method on some models, like L1400B, * it seems to be a kind of switch, but what for ? */ { .name = "A1x", .mt_mled = "MLED", .mled_status = "\\MAIL", .mt_lcd_switch = A1x_PREFIX "_Q10", .lcd_status = "\\BKLI", .brightness_up = A1x_PREFIX "_Q0E", .brightness_down = A1x_PREFIX "_Q0F"}, { .name = "A2x", .mt_mled = "MLED", .mt_wled = "WLED", .wled_status = "\\SG66", .mt_lcd_switch = "\\Q10", .lcd_status = "\\BAOF", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\INFB"}, { .name = "A4G", .mt_mled = "MLED",/* WLED present, but not controlled by ACPI */ .mt_lcd_switch = xxN_PREFIX "_Q10", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\ADVG"}, { .name = "D1x", .mt_mled = "MLED", .mt_lcd_switch = "\\Q0D", .lcd_status = "\\GP11", .brightness_up = "\\Q0C", .brightness_down = "\\Q0B", .brightness_status = "\\BLVL", .display_set = "SDSP", .display_get = "\\INFB"}, { .name = "L2D", .mt_mled = "MLED", .mled_status = "\\SGP6", .mt_wled = "WLED", .wled_status = "\\RCP3", .mt_lcd_switch = "\\Q10", .lcd_status = "\\SGP0", .brightness_up = "\\Q0E", .brightness_down = "\\Q0F", .display_set = "SDSP", .display_get = "\\INFB"}, { .name = "L3C", .mt_mled = "MLED", .mt_wled = "WLED", .mt_lcd_switch = L3C_PREFIX "_Q10", .lcd_status = "\\GL32", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\_SB.PCI0.PCI1.VGAC.NMAP"}, { .name = "L3D", .mt_mled = "MLED", .mled_status = "\\MALD", .mt_wled = "WLED", .mt_lcd_switch = "\\Q10", .lcd_status = "\\BKLG", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\INFB"}, { .name = "L3H", .mt_mled = "MLED", .mt_wled = "WLED", .mt_lcd_switch = "EHK", .lcd_status = "\\_SB.PCI0.PM.PBC", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\INFB"}, { .name = "L4R", .mt_mled = "MLED", .mt_wled = "WLED", .wled_status = "\\_SB.PCI0.SBRG.SG13", .mt_lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\_SB.PCI0.SBSM.SEO4", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"}, { .name = "L5x", .mt_mled = "MLED",/* WLED present, but not controlled by ACPI */ .mt_tled = "TLED", .mt_lcd_switch = "\\Q0D", .lcd_status = "\\BAOF", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\INFB"}, { .name = "L8L"/* No features, but at least support the hotkeys */ }, { .name = "M1A", .mt_mled = "MLED", .mt_lcd_switch = M1A_PREFIX "Q10", .lcd_status = "\\PNOF", .brightness_up = M1A_PREFIX "Q0E", .brightness_down = M1A_PREFIX "Q0F", .brightness_status = "\\BRIT", .display_set = "SDSP", .display_get = "\\INFB"}, { .name = "M2E", .mt_mled = "MLED", .mt_wled = "WLED", .mt_lcd_switch = "\\Q10", .lcd_status = "\\GP06", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\INFB"}, { .name = "M6N", .mt_mled = "MLED", .mt_wled = "WLED", .wled_status = "\\_SB.PCI0.SBRG.SG13", .mt_lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\_SB.BKLT", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\SSTE"}, { .name = "M6R", .mt_mled = "MLED", .mt_wled = "WLED", .mt_lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\_SB.PCI0.SBSM.SEO4", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"}, { .name = "P30", .mt_wled = "WLED", .mt_lcd_switch = P30_PREFIX "_Q0E", .lcd_status = "\\BKLT", .brightness_up = P30_PREFIX "_Q68", .brightness_down = P30_PREFIX "_Q69", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\DNXT"}, { .name = "S1x", .mt_mled = "MLED", .mled_status = "\\EMLE", .mt_wled = "WLED", .mt_lcd_switch = S1x_PREFIX "Q10", .lcd_status = "\\PNOF", .brightness_set = "SPLV", .brightness_get = "GPLV"}, { .name = "S2x", .mt_mled = "MLED", .mled_status = "\\MAIL", .mt_lcd_switch = S2x_PREFIX "_Q10", .lcd_status = "\\BKLI", .brightness_up = S2x_PREFIX "_Q0B", .brightness_down = S2x_PREFIX "_Q0A"}, { .name = "W1N", .mt_mled = "MLED", .mt_wled = "WLED", .mt_ledd = "SLCM", .mt_lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\BKLT", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\ADVG"}, { .name = "W5A", .mt_bt_switch = "BLED", .mt_wled = "WLED", .mt_lcd_switch = xxN_PREFIX "_Q10", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\ADVG"}, { .name = "W3V", .mt_mled = "MLED", .mt_wled = "WLED", .mt_lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\BKLT", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\INFB"}, { .name = "xxN", .mt_mled = "MLED",/* WLED present, but not controlled by ACPI */ .mt_lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\BKLT", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\ADVG"}, { .name = "A4S", .brightness_set = "SPLV", .brightness_get = "GPLV", .mt_bt_switch = "BLED", .mt_wled = "WLED" }};/* procdir we use */static struct proc_dir_entry *asus_proc_dir;static struct backlight_device *asus_backlight_device;/* * This header is made available to allow proper configuration given model, * revision number , ... this info cannot go in struct asus_hotk because it is * available before the hotk */static struct acpi_table_header *asus_info;/* The actual device the driver binds to */static struct asus_hotk *hotk;/* * The hotkey driver and autoloading declaration */static int asus_hotk_add(struct acpi_device *device);static int asus_hotk_remove(struct acpi_device *device, int type);static const struct acpi_device_id asus_device_ids[] = { {"ATK0100", 0}, {"", 0},};MODULE_DEVICE_TABLE(acpi, asus_device_ids);static struct acpi_driver asus_hotk_driver = { .name = "asus_acpi", .class = ACPI_HOTK_CLASS, .ids = asus_device_ids, .ops = { .add = asus_hotk_add, .remove = asus_hotk_remove, },};/* * This function evaluates an ACPI method, given an int as parameter, the * method is searched within the scope of the handle, can be NULL. The output * of the method is written is output, which can also be NULL * * returns 1 if write is successful, 0 else. */static int write_acpi_int(acpi_handle handle, const char *method, int val, struct acpi_buffer *output){ struct acpi_object_list params; //list of input parameters (an int here) union acpi_object in_obj; //the only param we use acpi_status status; params.count = 1; params.pointer = &in_obj; in_obj.type = ACPI_TYPE_INTEGER; in_obj.integer.value = val; status = acpi_evaluate_object(handle, (char *)method, ¶ms, output); return (status == AE_OK);}static int read_acpi_int(acpi_handle handle, const char *method, int *val){ struct acpi_buffer output; union acpi_object out_obj; acpi_status status;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?