📄 asus-laptop.c
字号:
printk(ASUS_WARNING "Error changing brightness\n"); ret = -EIO; } return ret;}static int update_bl_status(struct backlight_device *bd){ int rv; int value = bd->props.brightness; rv = set_brightness(bd, value); if (rv) return rv; value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0; return set_lcd_state(value);}/* * Platform device handlers *//* * We write our info in page, we begin at offset off and cannot write more * than count bytes. We set eof to 1 if we handle those 2 values. We return the * number of bytes written in page */static ssize_t show_infos(struct device *dev, struct device_attribute *attr, char *page){ int len = 0; ulong temp; char buf[16]; //enough for all info acpi_status rv = AE_OK; /* * We use the easy way, we don't care of off and count, so we don't set eof * to 1 */ len += sprintf(page, ASUS_HOTK_NAME " " ASUS_LAPTOP_VERSION "\n"); len += sprintf(page + len, "Model reference : %s\n", hotk->name); /* * The SFUN method probably allows the original driver to get the list * of features supported by a given model. For now, 0x0100 or 0x0800 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card. * The significance of others is yet to be found. */ rv = acpi_evaluate_integer(hotk->handle, "SFUN", NULL, &temp); if (!ACPI_FAILURE(rv)) len += sprintf(page + len, "SFUN value : 0x%04x\n", (uint) temp); /* * Another value for userspace: the ASYM method returns 0x02 for * battery low and 0x04 for battery critical, its readings tend to be * more accurate than those provided by _BST. * Note: since not all the laptops provide this method, errors are * silently ignored. */ rv = acpi_evaluate_integer(hotk->handle, "ASYM", NULL, &temp); if (!ACPI_FAILURE(rv)) len += sprintf(page + len, "ASYM value : 0x%04x\n", (uint) temp); if (asus_info) { snprintf(buf, 16, "%d", asus_info->length); len += sprintf(page + len, "DSDT length : %s\n", buf); snprintf(buf, 16, "%d", asus_info->checksum); len += sprintf(page + len, "DSDT checksum : %s\n", buf); snprintf(buf, 16, "%d", asus_info->revision); len += sprintf(page + len, "DSDT revision : %s\n", buf); snprintf(buf, 7, "%s", asus_info->oem_id); len += sprintf(page + len, "OEM id : %s\n", buf); snprintf(buf, 9, "%s", asus_info->oem_table_id); len += sprintf(page + len, "OEM table id : %s\n", buf); snprintf(buf, 16, "%x", asus_info->oem_revision); len += sprintf(page + len, "OEM revision : 0x%s\n", buf); snprintf(buf, 5, "%s", asus_info->asl_compiler_id); len += sprintf(page + len, "ASL comp vendor id : %s\n", buf); snprintf(buf, 16, "%x", asus_info->asl_compiler_revision); len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf); } return len;}static int parse_arg(const char *buf, unsigned long count, int *val){ if (!count) return 0; if (count > 31) return -EINVAL; if (sscanf(buf, "%i", val) != 1) return -EINVAL; return count;}static ssize_t store_status(const char *buf, size_t count, acpi_handle handle, int mask){ int rv, value; int out = 0; rv = parse_arg(buf, count, &value); if (rv > 0) out = value ? 1 : 0; write_status(handle, out, mask); return rv;}/* * LEDD display */static ssize_t show_ledd(struct device *dev, struct device_attribute *attr, char *buf){ return sprintf(buf, "0x%08x\n", hotk->ledd_status);}static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ int rv, value; rv = parse_arg(buf, count, &value); if (rv > 0) { if (!write_acpi_int(ledd_set_handle, NULL, value, NULL)) printk(ASUS_WARNING "LED display write failed\n"); else hotk->ledd_status = (u32) value; } return rv;}/* * WLAN */static ssize_t show_wlan(struct device *dev, struct device_attribute *attr, char *buf){ return sprintf(buf, "%d\n", read_status(WL_ON));}static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ return store_status(buf, count, wl_switch_handle, WL_ON);}/* * Bluetooth */static ssize_t show_bluetooth(struct device *dev, struct device_attribute *attr, char *buf){ return sprintf(buf, "%d\n", read_status(BT_ON));}static ssize_t store_bluetooth(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ return store_status(buf, count, bt_switch_handle, BT_ON);}/* * Display */static void set_display(int value){ /* no sanity check needed for now */ if (!write_acpi_int(display_set_handle, NULL, value, NULL)) printk(ASUS_WARNING "Error setting display\n"); return;}static int read_display(void){ ulong value = 0; acpi_status rv = AE_OK; /* In most of the case, we know how to set the display, but sometime we can't read it */ if (display_get_handle) { rv = acpi_evaluate_integer(display_get_handle, NULL, NULL, &value); if (ACPI_FAILURE(rv)) printk(ASUS_WARNING "Error reading display status\n"); } value &= 0x0F; /* needed for some models, shouldn't hurt others */ return value;}/* * Now, *this* one could be more user-friendly, but so far, no-one has * complained. The significance of bits is the same as in store_disp() */static ssize_t show_disp(struct device *dev, struct device_attribute *attr, char *buf){ return sprintf(buf, "%d\n", read_display());}/* * Experimental support for display switching. As of now: 1 should activate * the LCD output, 2 should do for CRT, 4 for TV-Out and 8 for DVI. * Any combination (bitwise) of these will suffice. I never actually tested 4 * displays hooked up simultaneously, so be warned. See the acpi4asus README * for more info. */static ssize_t store_disp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ int rv, value; rv = parse_arg(buf, count, &value); if (rv > 0) set_display(value); return rv;}/* * Light Sens */static void set_light_sens_switch(int value){ if (!write_acpi_int(ls_switch_handle, NULL, value, NULL)) printk(ASUS_WARNING "Error setting light sensor switch\n"); hotk->light_switch = value;}static ssize_t show_lssw(struct device *dev, struct device_attribute *attr, char *buf){ return sprintf(buf, "%d\n", hotk->light_switch);}static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ int rv, value; rv = parse_arg(buf, count, &value); if (rv > 0) set_light_sens_switch(value ? 1 : 0); return rv;}static void set_light_sens_level(int value){ if (!write_acpi_int(ls_level_handle, NULL, value, NULL)) printk(ASUS_WARNING "Error setting light sensor level\n"); hotk->light_level = value;}static ssize_t show_lslvl(struct device *dev, struct device_attribute *attr, char *buf){ return sprintf(buf, "%d\n", hotk->light_level);}static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ int rv, value; rv = parse_arg(buf, count, &value); if (rv > 0) { value = (0 < value) ? ((15 < value) ? 15 : value) : 0; /* 0 <= value <= 15 */ set_light_sens_level(value); } return rv;}/* * GPS */static ssize_t show_gps(struct device *dev, struct device_attribute *attr, char *buf){ return sprintf(buf, "%d\n", read_status(GPS_ON));}static ssize_t store_gps(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ return store_status(buf, count, NULL, GPS_ON);}static void asus_hotk_notify(acpi_handle handle, u32 event, void *data){ /* TODO Find a better way to handle events count. */ if (!hotk) return; /* * We need to tell the backlight device when the backlight power is * switched */ if (event == ATKD_LCD_ON) { write_status(NULL, 1, LCD_ON); lcd_blank(FB_BLANK_UNBLANK); } else if (event == ATKD_LCD_OFF) { write_status(NULL, 0, LCD_ON); lcd_blank(FB_BLANK_POWERDOWN); } acpi_bus_generate_proc_event(hotk->device, event, hotk->event_count[event % 128]++); return;}#define ASUS_CREATE_DEVICE_ATTR(_name) \ struct device_attribute dev_attr_##_name = { \ .attr = { \ .name = __stringify(_name), \ .mode = 0 }, \ .show = NULL, \ .store = NULL, \ }#define ASUS_SET_DEVICE_ATTR(_name, _mode, _show, _store) \ do { \ dev_attr_##_name.attr.mode = _mode; \ dev_attr_##_name.show = _show; \ dev_attr_##_name.store = _store; \ } while(0)static ASUS_CREATE_DEVICE_ATTR(infos);static ASUS_CREATE_DEVICE_ATTR(wlan);static ASUS_CREATE_DEVICE_ATTR(bluetooth);static ASUS_CREATE_DEVICE_ATTR(display);static ASUS_CREATE_DEVICE_ATTR(ledd);static ASUS_CREATE_DEVICE_ATTR(ls_switch);static ASUS_CREATE_DEVICE_ATTR(ls_level);static ASUS_CREATE_DEVICE_ATTR(gps);static struct attribute *asuspf_attributes[] = { &dev_attr_infos.attr, &dev_attr_wlan.attr, &dev_attr_bluetooth.attr, &dev_attr_display.attr, &dev_attr_ledd.attr, &dev_attr_ls_switch.attr, &dev_attr_ls_level.attr, &dev_attr_gps.attr, NULL};static struct attribute_group asuspf_attribute_group = { .attrs = asuspf_attributes};static struct platform_driver asuspf_driver = { .driver = { .name = ASUS_HOTK_FILE, .owner = THIS_MODULE, }};static struct platform_device *asuspf_device;static void asus_hotk_add_fs(void){ ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL); if (wl_switch_handle) ASUS_SET_DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan); if (bt_switch_handle) ASUS_SET_DEVICE_ATTR(bluetooth, 0644, show_bluetooth, store_bluetooth); if (display_set_handle && display_get_handle) ASUS_SET_DEVICE_ATTR(display, 0644, show_disp, store_disp); else if (display_set_handle) ASUS_SET_DEVICE_ATTR(display, 0200, NULL, store_disp); if (ledd_set_handle) ASUS_SET_DEVICE_ATTR(ledd, 0644, show_ledd, store_ledd); if (ls_switch_handle && ls_level_handle) { ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl); ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw); } if (gps_status_handle && gps_on_handle && gps_off_handle) ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps);}static int asus_handle_init(char *name, acpi_handle * handle, char **paths, int num_paths){ int i; acpi_status status; for (i = 0; i < num_paths; i++) { status = acpi_get_handle(NULL, paths[i], handle); if (ACPI_SUCCESS(status)) return 0; } *handle = NULL; return -ENODEV;}#define ASUS_HANDLE_INIT(object) \ asus_handle_init(#object, &object##_handle, object##_paths, \ ARRAY_SIZE(object##_paths))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -