asus_acpi.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,237 行 · 第 1/3 页
C
1,237 行
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; output.length = sizeof(out_obj); output.pointer = &out_obj; status = acpi_evaluate_object(handle, (char *) method, NULL, &output); *val = out_obj.integer.value; return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER);}/* * 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 intproc_read_info(char *page, char **start, off_t off, int count, int *eof, void *data){ int len = 0; int temp; char buf[16]; //enough for all info /* * We use the easy way, we don't care of off and count, so we don't set eof * to 1 */ len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n"); len += sprintf(page + len, "Model reference : %s\n", hotk->methods->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. */ if (read_acpi_int(hotk->handle, "SFUN", &temp)) len += sprintf(page + len, "SFUN value : 0x%04x\n", 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. */ if (read_acpi_int(hotk->handle, "ASYM", &temp)) len += sprintf(page + len, "ASYM value : 0x%04x\n", 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;}/* * /proc 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 *//* Generic LED functions */static intread_led(const char *ledname, int ledmask){ if (ledname) { int led_status; if (read_acpi_int(NULL, ledname, &led_status)) return led_status; else printk(KERN_WARNING "Asus ACPI: Error reading LED " "status\n"); } return (hotk->status & ledmask) ? 1 : 0;}static int parse_arg(const char __user *buf, unsigned long count, int *val){ char s[32]; if (!count) return 0; if (count > 31) return -EINVAL; if (copy_from_user(s, buf, count)) return -EFAULT; s[count] = 0; if (sscanf(s, "%i", val) != 1) return -EINVAL; return count;}/* FIXME: kill extraneous args so it can be called independently */static intwrite_led(const char __user *buffer, unsigned long count, char *ledname, int ledmask, int invert){ int value; int led_out = 0; count = parse_arg(buffer, count, &value); if (count > 0) led_out = value ? 1 : 0; hotk->status = (led_out) ? (hotk->status | ledmask) : (hotk->status & ~ledmask); if (invert) /* invert target value */ led_out = !led_out & 0x1; if (!write_acpi_int(hotk->handle, ledname, led_out, NULL)) printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n", ledname); return count;}/* * Proc handlers for MLED */static intproc_read_mled(char *page, char **start, off_t off, int count, int *eof, void *data){ return sprintf(page, "%d\n", read_led(hotk->methods->mled_status, MLED_ON));}static intproc_write_mled(struct file *file, const char __user *buffer, unsigned long count, void *data){ return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);}/* * Proc handlers for WLED */static intproc_read_wled(char *page, char **start, off_t off, int count, int *eof, void *data){ return sprintf(page, "%d\n", read_led(hotk->methods->wled_status, WLED_ON));}static intproc_write_wled(struct file *file, const char __user *buffer, unsigned long count, void *data){ return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);}/* * Proc handlers for TLED */static intproc_read_tled(char *page, char **start, off_t off, int count, int *eof, void *data){ return sprintf(page, "%d\n", read_led(hotk->methods->tled_status, TLED_ON));}static intproc_write_tled(struct file *file, const char __user *buffer, unsigned long count, void *data){ return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0);}static int get_lcd_state(void){ int lcd = 0; if (hotk->model != L3H) { /* We don't have to check anything if we are here */ if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd)) printk(KERN_WARNING "Asus ACPI: Error reading LCD status\n"); if (hotk->model == L2D) lcd = ~lcd; } else { /* L3H and the like have to be handled differently */ acpi_status status = 0; struct acpi_object_list input; union acpi_object mt_params[2]; struct acpi_buffer output; union acpi_object out_obj; input.count = 2; input.pointer = mt_params; /* Note: the following values are partly guessed up, but otherwise they seem to work */ mt_params[0].type = ACPI_TYPE_INTEGER; mt_params[0].integer.value = 0x02; mt_params[1].type = ACPI_TYPE_INTEGER; mt_params[1].integer.value = 0x02; output.length = sizeof(out_obj); output.pointer = &out_obj; status = acpi_evaluate_object(NULL, hotk->methods->lcd_status, &input, &output); if (status != AE_OK) return -1; if (out_obj.type == ACPI_TYPE_INTEGER) /* That's what the AML code does */ lcd = out_obj.integer.value >> 8; } return (lcd & 1);}static int set_lcd_state(int value){ int lcd = 0; acpi_status status = 0; lcd = value ? 1 : 0; if (lcd != get_lcd_state()) { /* switch */ if (hotk->model != L3H) { status = acpi_evaluate_object(NULL, hotk->methods->mt_lcd_switch, NULL, NULL); } else { /* L3H and the like have to be handled differently */ if (!write_acpi_int(hotk->handle, hotk->methods->mt_lcd_switch, 0x07, NULL)) status = AE_ERROR; /* L3H's AML executes EHK (0x07) upon Fn+F7 keypress, the exact behaviour is simulated here */ } if (ACPI_FAILURE(status)) printk(KERN_WARNING "Asus ACPI: Error switching LCD\n"); } return 0;}static intproc_read_lcd(char *page, char **start, off_t off, int count, int *eof, void *data){ return sprintf(page, "%d\n", get_lcd_state());}static intproc_write_lcd(struct file *file, const char __user *buffer, unsigned long count, void *data){ int value; count = parse_arg(buffer, count, &value); if (count > 0) set_lcd_state(value); return count;}static int read_brightness(void){ int value; if(hotk->methods->brightness_get) { /* SPLV/GPLV laptop */ if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get, &value)) printk(KERN_WARNING "Asus ACPI: Error reading brightness\n"); } else if (hotk->methods->brightness_status) { /* For D1 for example */ if (!read_acpi_int(NULL, hotk->methods->brightness_status, &value)) printk(KERN_WARNING "Asus ACPI: Error reading brightness\n"); } else /* No GPLV method */ value = hotk->brightness; return value;}/* * Change the brightness level */static void set_brightness(int value){ acpi_status status = 0; /* SPLV laptop */ if(hotk->methods->brightness_set) { if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set, value, NULL)) printk(KERN_WARNING "Asus ACPI: Error changing brightness\n"); return; } /* No SPLV method if we are here, act as appropriate */ value -= read_brightness(); while (value != 0) { status = acpi_evaluate_object(NULL, (value > 0) ? hotk->methods->brightness_up : hotk->methods->brightness_down, NULL, NULL); (value > 0) ? value-- : value++; if (ACPI_FAILURE(status)) printk(KERN_WARNING "Asus ACPI: Error changing brightness\n"); } return;}static intproc_read_brn(char *page, char **start, off_t off, int count, int *eof, void *data){ return sprintf(page, "%d\n", read_brightness());}static intproc_write_brn(struct file *file, const char __user *buffer, unsigned long count, void *data){ int value; count = parse_arg(buffer, count, &value); if (count > 0) { value = (0 < value) ? ((15 < value) ? 15 : value) : 0; /* 0 <= value <= 15 */ set_brightness(value); } else if (count < 0) { printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); } return count;}static void set_display(int value){ /* no sanity check needed for now */ if (!write_acpi_int(hotk->handle, hotk->methods->display_set, value, NULL)) printk(KERN_WARNING "Asus ACPI: Error setting display\n"); return;}/* * Now, *this* one could be more user-friendly, but so far, no-one has * complained. The significance of bits is the same as in proc_write_disp() */static intproc_read_disp(char *page, char **start, off_t off, int count, int *eof, void *data){ int value = 0; if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value)) printk(KERN_WARNING "Asus ACPI: Error reading display status\n"); value &= 0x07; /* needed for some models, shouldn't hurt others */ return sprintf(page, "%d\n", value);}/* * Experimental support for display switching. As of now: 1 should activate * the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination * (bitwise) of these will suffice. I never actually tested 3 displays hooked up * simultaneously, so be warned. See the acpi4asus README for more info. */static intproc_write_disp(struct file *file, const char __user *buffer, unsigned long count, void *data){ int value; count = parse_arg(buffer, count, &value); if (count > 0) set_display(value); else if (count < 0) printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); return count;}typedef int (proc_readfunc)(char *page, char **start, off_t off, int count,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?