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, &params, 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 + -
显示快捷键?