thinkpad_acpi.c
来自「linux 内核源代码」· C语言 代码 · 共 2,636 行 · 第 1/5 页
C
2,636 行
static struct platform_device *tpacpi_sensors_pdev;static struct device *tpacpi_hwmon;static struct input_dev *tpacpi_inputdev;static struct mutex tpacpi_inputdev_send_mutex;static int tpacpi_resume_handler(struct platform_device *pdev){ struct ibm_struct *ibm, *itmp; list_for_each_entry_safe(ibm, itmp, &tpacpi_all_drivers, all_drivers) { if (ibm->resume) (ibm->resume)(); } return 0;}static struct platform_driver tpacpi_pdriver = { .driver = { .name = IBM_DRVR_NAME, .owner = THIS_MODULE, }, .resume = tpacpi_resume_handler,};static struct platform_driver tpacpi_hwmon_pdriver = { .driver = { .name = IBM_HWMON_DRVR_NAME, .owner = THIS_MODULE, },};/************************************************************************* * thinkpad-acpi driver attributes *//* interface_version --------------------------------------------------- */static ssize_t tpacpi_driver_interface_version_show( struct device_driver *drv, char *buf){ return snprintf(buf, PAGE_SIZE, "0x%08x\n", TPACPI_SYSFS_VERSION);}static DRIVER_ATTR(interface_version, S_IRUGO, tpacpi_driver_interface_version_show, NULL);/* debug_level --------------------------------------------------------- */static ssize_t tpacpi_driver_debug_show(struct device_driver *drv, char *buf){ return snprintf(buf, PAGE_SIZE, "0x%04x\n", dbg_level);}static ssize_t tpacpi_driver_debug_store(struct device_driver *drv, const char *buf, size_t count){ unsigned long t; if (parse_strtoul(buf, 0xffff, &t)) return -EINVAL; dbg_level = t; return count;}static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, tpacpi_driver_debug_show, tpacpi_driver_debug_store);/* version ------------------------------------------------------------- */static ssize_t tpacpi_driver_version_show(struct device_driver *drv, char *buf){ return snprintf(buf, PAGE_SIZE, "%s v%s\n", IBM_DESC, IBM_VERSION);}static DRIVER_ATTR(version, S_IRUGO, tpacpi_driver_version_show, NULL);/* --------------------------------------------------------------------- */static struct driver_attribute* tpacpi_driver_attributes[] = { &driver_attr_debug_level, &driver_attr_version, &driver_attr_interface_version,};static int __init tpacpi_create_driver_attributes(struct device_driver *drv){ int i, res; i = 0; res = 0; while (!res && i < ARRAY_SIZE(tpacpi_driver_attributes)) { res = driver_create_file(drv, tpacpi_driver_attributes[i]); i++; } return res;}static void tpacpi_remove_driver_attributes(struct device_driver *drv){ int i; for(i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++) driver_remove_file(drv, tpacpi_driver_attributes[i]);}/************************************************************************* * sysfs support helpers */struct attribute_set_obj { struct attribute_set s; struct attribute *a;} __attribute__((packed));static struct attribute_set *create_attr_set(unsigned int max_members, const char* name){ struct attribute_set_obj *sobj; if (max_members == 0) return NULL; /* Allocates space for implicit NULL at the end too */ sobj = kzalloc(sizeof(struct attribute_set_obj) + max_members * sizeof(struct attribute *), GFP_KERNEL); if (!sobj) return NULL; sobj->s.max_members = max_members; sobj->s.group.attrs = &sobj->a; sobj->s.group.name = name; return &sobj->s;}/* not multi-threaded safe, use it in a single thread per set */static int add_to_attr_set(struct attribute_set* s, struct attribute *attr){ if (!s || !attr) return -EINVAL; if (s->members >= s->max_members) return -ENOMEM; s->group.attrs[s->members] = attr; s->members++; return 0;}static int add_many_to_attr_set(struct attribute_set* s, struct attribute **attr, unsigned int count){ int i, res; for (i = 0; i < count; i++) { res = add_to_attr_set(s, attr[i]); if (res) return res; } return 0;}static void delete_attr_set(struct attribute_set* s, struct kobject *kobj){ sysfs_remove_group(kobj, &s->group); destroy_attr_set(s);}static int parse_strtoul(const char *buf, unsigned long max, unsigned long *value){ char *endp; while (*buf && isspace(*buf)) buf++; *value = simple_strtoul(buf, &endp, 0); while (*endp && isspace(*endp)) endp++; if (*endp || *value > max) return -EINVAL; return 0;}/**************************************************************************** **************************************************************************** * * Subdrivers * **************************************************************************** ****************************************************************************//************************************************************************* * thinkpad-acpi init subdriver */static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm){ printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); printk(IBM_INFO "%s\n", IBM_URL); printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n", (thinkpad_id.bios_version_str) ? thinkpad_id.bios_version_str : "unknown", (thinkpad_id.ec_version_str) ? thinkpad_id.ec_version_str : "unknown"); if (thinkpad_id.vendor && thinkpad_id.model_str) printk(IBM_INFO "%s %s\n", (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? "IBM" : ((thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) ? "Lenovo" : "Unknown vendor"), thinkpad_id.model_str); return 0;}static int thinkpad_acpi_driver_read(char *p){ int len = 0; len += sprintf(p + len, "driver:\t\t%s\n", IBM_DESC); len += sprintf(p + len, "version:\t%s\n", IBM_VERSION); return len;}static struct ibm_struct thinkpad_acpi_driver_data = { .name = "driver", .read = thinkpad_acpi_driver_read,};/************************************************************************* * Hotkey subdriver */static int hotkey_orig_status;static u32 hotkey_orig_mask;static u32 hotkey_all_mask;static u32 hotkey_reserved_mask;static u16 *hotkey_keycode_map;static struct attribute_set *hotkey_dev_attributes;static int hotkey_get_wlsw(int *status){ if (!acpi_evalf(hkey_handle, status, "WLSW", "d")) return -EIO; return 0;}/* sysfs hotkey enable ------------------------------------------------- */static ssize_t hotkey_enable_show(struct device *dev, struct device_attribute *attr, char *buf){ int res, status; u32 mask; res = hotkey_get(&status, &mask); if (res) return res; return snprintf(buf, PAGE_SIZE, "%d\n", status);}static ssize_t hotkey_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ unsigned long t; int res, status; u32 mask; if (parse_strtoul(buf, 1, &t)) return -EINVAL; res = hotkey_get(&status, &mask); if (!res) res = hotkey_set(t, mask); return (res) ? res : count;}static struct device_attribute dev_attr_hotkey_enable = __ATTR(hotkey_enable, S_IWUSR | S_IRUGO, hotkey_enable_show, hotkey_enable_store);/* sysfs hotkey mask --------------------------------------------------- */static ssize_t hotkey_mask_show(struct device *dev, struct device_attribute *attr, char *buf){ int res, status; u32 mask; res = hotkey_get(&status, &mask); if (res) return res; return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask);}static ssize_t hotkey_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ unsigned long t; int res, status; u32 mask; if (parse_strtoul(buf, 0xffffffffUL, &t)) return -EINVAL; res = hotkey_get(&status, &mask); if (!res) hotkey_set(status, t); return (res) ? res : count;}static struct device_attribute dev_attr_hotkey_mask = __ATTR(hotkey_mask, S_IWUSR | S_IRUGO, hotkey_mask_show, hotkey_mask_store);/* sysfs hotkey bios_enabled ------------------------------------------- */static ssize_t hotkey_bios_enabled_show(struct device *dev, struct device_attribute *attr, char *buf){ return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_orig_status);}static struct device_attribute dev_attr_hotkey_bios_enabled = __ATTR(hotkey_bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL);/* sysfs hotkey bios_mask ---------------------------------------------- */static ssize_t hotkey_bios_mask_show(struct device *dev, struct device_attribute *attr, char *buf){ return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask);}static struct device_attribute dev_attr_hotkey_bios_mask = __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);/* sysfs hotkey all_mask ----------------------------------------------- */static ssize_t hotkey_all_mask_show(struct device *dev, struct device_attribute *attr, char *buf){ return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_all_mask);}static struct device_attribute dev_attr_hotkey_all_mask = __ATTR(hotkey_all_mask, S_IRUGO, hotkey_all_mask_show, NULL);/* sysfs hotkey recommended_mask --------------------------------------- */static ssize_t hotkey_recommended_mask_show(struct device *dev, struct device_attribute *attr, char *buf){ return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_all_mask & ~hotkey_reserved_mask);}static struct device_attribute dev_attr_hotkey_recommended_mask = __ATTR(hotkey_recommended_mask, S_IRUGO, hotkey_recommended_mask_show, NULL);/* sysfs hotkey radio_sw ----------------------------------------------- */static ssize_t hotkey_radio_sw_show(struct device *dev, struct device_attribute *attr, char *buf){ int res, s; res = hotkey_get_wlsw(&s); if (res < 0) return res; return snprintf(buf, PAGE_SIZE, "%d\n", !!s);}static struct device_attribute dev_attr_hotkey_radio_sw = __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL);/* sysfs hotkey report_mode -------------------------------------------- */static ssize_t hotkey_report_mode_show(struct device *dev, struct device_attribute *attr, char *buf){ return snprintf(buf, PAGE_SIZE, "%d\n", (hotkey_report_mode != 0) ? hotkey_report_mode : 1);}static struct device_attribute dev_attr_hotkey_report_mode = __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);/* --------------------------------------------------------------------- */static struct attribute *hotkey_attributes[] __initdata = { &dev_attr_hotkey_enable.attr, &dev_attr_hotkey_report_mode.attr,};static struct attribute *hotkey_mask_attributes[] __initdata = { &dev_attr_hotkey_mask.attr, &dev_attr_hotkey_bios_enabled.attr, &dev_attr_hotkey_bios_mask.attr, &dev_attr_hotkey_all_mask.attr, &dev_attr_hotkey_recommended_mask.attr,};static int __init hotkey_init(struct ibm_init_struct *iibm){ static u16 ibm_keycode_map[] __initdata = { /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP, KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */ KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ KEY_UNKNOWN, /* 0x0D: FN+INSERT */ KEY_UNKNOWN, /* 0x0E: FN+DELETE */ KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ KEY_RESERVED, /* 0x10: FN+END (brightness down) */ KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ KEY_RESERVED, /* 0x14: VOLUME UP */ KEY_RESERVED, /* 0x15: VOLUME DOWN */ KEY_RESERVED, /* 0x16: MUTE */ KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, }; static u16 lenovo_keycode_map[] __initdata = { /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP, KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */ KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ KEY_UNKNOWN, /* 0x0D: FN+INSERT */ KEY_UNKNOWN, /* 0x0E: FN+DELETE */ KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ KEY_RESERVED, /* 0x10: FN+END (brightness down) */ KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ KEY_RESERVED, /* 0x14: VOLUME UP */ KEY_RESERVED, /* 0x15: VOLUME DOWN */ KEY_RESERVED, /* 0x16: MUTE */ KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, };#define TPACPI_HOTKEY_MAP_LEN ARRAY_SIZE(ibm_keycode_map)#define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map)#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0]) int res, i; int status; int hkeyv; vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); BUG_ON(!tpacpi_inputdev); IBM_ACPIHANDLE_INIT(hkey); mutex_init(&hotkey_mutex); /* hotkey not supported on 570 */ tp_features.hotkey = hkey_handle != NULL; vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n", str_supported(tp_features.hotkey)); if (tp_features.hotkey) { hotkey_dev_attributes = create_attr_set(8, NULL); if (!hotkey_dev_attributes) return -ENOMEM; res = add_many_to_attr_set(hotkey_dev_attributes, hotkey_attributes, ARRAY_SIZE(hotkey_attributes)); if (res) return res; /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking for HKEY interface version 0x100 */ if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { if ((hkeyv >> 8) != 1) { printk(IBM_ERR "unknown version of the " "HKEY interface: 0x%x\n", hkeyv); printk(IBM_ERR "please report this to %s\n", IBM_MAIL); } else { /* * MHKV 0x100 in A31, R40, R40e, * T4x, X31, and later * */ tp_features.hotkey_mask = 1; } } vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", str_supported(tp_features.hotkey_mask));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?