asus_acpi.c

来自「linux 内核源代码」· C语言 代码 · 共 1,425 行 · 第 1/3 页

C
1,425
字号
	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 int read_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 rv, value;	int led_out = 0;	rv = parse_arg(buffer, count, &value);	if (rv > 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 rv;}/* * 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 LED display */static intproc_read_ledd(char *page, char **start, off_t off, int count, int *eof,	       void *data){	return sprintf(page, "0x%08x\n", hotk->ledd_status);}static intproc_write_ledd(struct file *file, const char __user * buffer,		unsigned long count, void *data){	int rv, value;	rv = parse_arg(buffer, count, &value);	if (rv > 0) {		if (!write_acpi_int		    (hotk->handle, hotk->methods->mt_ledd, value, NULL))			printk(KERN_WARNING			       "Asus ACPI: LED display write failed\n");		else			hotk->ledd_status = (u32) value;	}	return rv;}/* * 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 Bluetooth */static intproc_read_bluetooth(char *page, char **start, off_t off, int count, int *eof,		    void *data){	return sprintf(page, "%d\n", read_led(hotk->methods->bt_status, BT_ON));}static intproc_write_bluetooth(struct file *file, const char __user * buffer,		     unsigned long count, void *data){	/* Note: mt_bt_switch controls both internal Bluetooth adapter's 	   presence and its LED */	return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_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 rv, value;	rv = parse_arg(buffer, count, &value);	if (rv > 0)		set_lcd_state(value);	return rv;}static int read_brightness(struct backlight_device *bd){	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 int set_brightness(int value){	acpi_status status = 0;	int ret = 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");			ret = -EIO;		goto out;	}	/* No SPLV method if we are here, act as appropriate */	value -= read_brightness(NULL);	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");			ret = -EIO;	}out:	return ret;}static int set_brightness_status(struct backlight_device *bd){	return set_brightness(bd->props.brightness);}static intproc_read_brn(char *page, char **start, off_t off, int count, int *eof,	      void *data){	return sprintf(page, "%d\n", read_brightness(NULL));}static intproc_write_brn(struct file *file, const char __user * buffer,	       unsigned long count, void *data){	int rv, value;	rv = parse_arg(buffer, count, &value);	if (rv > 0) {		value = (0 < value) ? ((15 < value) ? 15 : value) : 0;		/* 0 <= value <= 15 */		set_brightness(value);	}	return rv;}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 rv, value;	rv = parse_arg(buffer, count, &value);	if (rv > 0)		set_display(value);	return rv;}typedef int (proc_readfunc) (char *page, char **start, off_t off, int count,			     int *eof, void *data);typedef int (proc_writefunc) (struct file * file, const char __user * buffer,			      unsigned long count, void *data);static intasus_proc_add(char *name, proc_writefunc * writefunc,		     proc_readfunc * readfunc, mode_t mode,		     struct acpi_device *device){	struct proc_dir_entry *proc =	    create_proc_entry(name, mode, acpi_device_dir(device));	if (!proc) {		printk(KERN_WARNING "  Unable to create %s fs entry\n", name);		return -1;	}	proc->write_proc = writefunc;	proc->read_proc = readfunc;	proc->data = acpi_driver_data(device);	proc->owner = THIS_MODULE;	proc->uid = asus_uid;	proc->gid = asus_gid;	return 0;}static int asus_hotk_add_fs(struct acpi_device *device)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?