⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asus-laptop.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * This function is used to initialize the hotk with right values. In this * method, we can make all the detection we want, and modify the hotk struct */static int asus_hotk_get_info(void){	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };	union acpi_object *model = NULL;	ulong bsts_result, hwrs_result;	char *string = NULL;	acpi_status status;	/*	 * Get DSDT headers early enough to allow for differentiating between	 * models, but late enough to allow acpi_bus_register_driver() to fail	 * before doing anything ACPI-specific. Should we encounter a machine,	 * which needs special handling (i.e. its hotkey device has a different	 * HID), this bit will be moved. A global variable asus_info contains	 * the DSDT header.	 */	status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info);	if (ACPI_FAILURE(status))		printk(ASUS_WARNING "Couldn't get the DSDT table header\n");	/* We have to write 0 on init this far for all ASUS models */	if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {		printk(ASUS_ERR "Hotkey initialization failed\n");		return -ENODEV;	}	/* This needs to be called for some laptops to init properly */	status =	    acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result);	if (ACPI_FAILURE(status))		printk(ASUS_WARNING "Error calling BSTS\n");	else if (bsts_result)		printk(ASUS_NOTICE "BSTS called, 0x%02x returned\n",		       (uint) bsts_result);	/* This too ... */	write_acpi_int(hotk->handle, "CWAP", wapf, NULL);	/*	 * Try to match the object returned by INIT to the specific model.	 * Handle every possible object (or the lack of thereof) the DSDT	 * writers might throw at us. When in trouble, we pass NULL to	 * asus_model_match() and try something completely different.	 */	if (buffer.pointer) {		model = buffer.pointer;		switch (model->type) {		case ACPI_TYPE_STRING:			string = model->string.pointer;			break;		case ACPI_TYPE_BUFFER:			string = model->buffer.pointer;			break;		default:			string = "";			break;		}	}	hotk->name = kstrdup(string, GFP_KERNEL);	if (!hotk->name)		return -ENOMEM;	if (*string)		printk(ASUS_NOTICE "  %s model detected\n", string);	ASUS_HANDLE_INIT(mled_set);	ASUS_HANDLE_INIT(tled_set);	ASUS_HANDLE_INIT(rled_set);	ASUS_HANDLE_INIT(pled_set);	ASUS_HANDLE_INIT(gled_set);	ASUS_HANDLE_INIT(ledd_set);	/*	 * The HWRS method return informations about the hardware.	 * 0x80 bit is for WLAN, 0x100 for Bluetooth.	 * The significance of others is yet to be found.	 * If we don't find the method, we assume the device are present.	 */	status =	    acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &hwrs_result);	if (ACPI_FAILURE(status))		hwrs_result = WL_HWRS | BT_HWRS;	if (hwrs_result & WL_HWRS)		ASUS_HANDLE_INIT(wl_switch);	if (hwrs_result & BT_HWRS)		ASUS_HANDLE_INIT(bt_switch);	ASUS_HANDLE_INIT(wireless_status);	ASUS_HANDLE_INIT(brightness_set);	ASUS_HANDLE_INIT(brightness_get);	ASUS_HANDLE_INIT(lcd_switch);	ASUS_HANDLE_INIT(display_set);	ASUS_HANDLE_INIT(display_get);	/* There is a lot of models with "ALSL", but a few get	   a real light sens, so we need to check it. */	if (!ASUS_HANDLE_INIT(ls_switch))		ASUS_HANDLE_INIT(ls_level);	ASUS_HANDLE_INIT(gps_on);	ASUS_HANDLE_INIT(gps_off);	ASUS_HANDLE_INIT(gps_status);	kfree(model);	return AE_OK;}static int asus_hotk_check(void){	int result = 0;	result = acpi_bus_get_status(hotk->device);	if (result)		return result;	if (hotk->device->status.present) {		result = asus_hotk_get_info();	} else {		printk(ASUS_ERR "Hotkey device not present, aborting\n");		return -EINVAL;	}	return result;}static int asus_hotk_found;static int asus_hotk_add(struct acpi_device *device){	acpi_status status = AE_OK;	int result;	if (!device)		return -EINVAL;	printk(ASUS_NOTICE "Asus Laptop Support version %s\n",	       ASUS_LAPTOP_VERSION);	hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);	if (!hotk)		return -ENOMEM;	hotk->handle = device->handle;	strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);	strcpy(acpi_device_class(device), ASUS_HOTK_CLASS);	acpi_driver_data(device) = hotk;	hotk->device = device;	result = asus_hotk_check();	if (result)		goto end;	asus_hotk_add_fs();	/*	 * We install the handler, it will receive the hotk in parameter, so, we	 * could add other data to the hotk struct	 */	status = acpi_install_notify_handler(hotk->handle, ACPI_ALL_NOTIFY,					     asus_hotk_notify, hotk);	if (ACPI_FAILURE(status))		printk(ASUS_ERR "Error installing notify handler\n");	asus_hotk_found = 1;	/* WLED and BLED are on by default */	write_status(bt_switch_handle, 1, BT_ON);	write_status(wl_switch_handle, 1, WL_ON);	/* If the h/w switch is off, we need to check the real status */	write_status(NULL, read_status(BT_ON), BT_ON);	write_status(NULL, read_status(WL_ON), WL_ON);	/* LCD Backlight is on by default */	write_status(NULL, 1, LCD_ON);	/* LED display is off by default */	hotk->ledd_status = 0xFFF;	/* Set initial values of light sensor and level */	hotk->light_switch = 1;	/* Default to light sensor disabled */	hotk->light_level = 0;	/* level 5 for sensor sensitivity */	if (ls_switch_handle)		set_light_sens_switch(hotk->light_switch);	if (ls_level_handle)		set_light_sens_level(hotk->light_level);	/* GPS is on by default */	write_status(NULL, 1, GPS_ON);      end:	if (result) {		kfree(hotk->name);		kfree(hotk);	}	return result;}static int asus_hotk_remove(struct acpi_device *device, int type){	acpi_status status = 0;	if (!device || !acpi_driver_data(device))		return -EINVAL;	status = acpi_remove_notify_handler(hotk->handle, ACPI_ALL_NOTIFY,					    asus_hotk_notify);	if (ACPI_FAILURE(status))		printk(ASUS_ERR "Error removing notify handler\n");	kfree(hotk->name);	kfree(hotk);	return 0;}static void asus_backlight_exit(void){	if (asus_backlight_device)		backlight_device_unregister(asus_backlight_device);}#define  ASUS_LED_UNREGISTER(object)				\	if (object##_led.dev)					\		led_classdev_unregister(&object##_led)static void asus_led_exit(void){	destroy_workqueue(led_workqueue);	ASUS_LED_UNREGISTER(mled);	ASUS_LED_UNREGISTER(tled);	ASUS_LED_UNREGISTER(pled);	ASUS_LED_UNREGISTER(rled);	ASUS_LED_UNREGISTER(gled);}static void __exit asus_laptop_exit(void){	asus_backlight_exit();	asus_led_exit();	acpi_bus_unregister_driver(&asus_hotk_driver);	sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);	platform_device_unregister(asuspf_device);	platform_driver_unregister(&asuspf_driver);}static int asus_backlight_init(struct device *dev){	struct backlight_device *bd;	if (brightness_set_handle && lcd_switch_handle) {		bd = backlight_device_register(ASUS_HOTK_FILE, dev,					       NULL, &asusbl_ops);		if (IS_ERR(bd)) {			printk(ASUS_ERR			       "Could not register asus backlight device\n");			asus_backlight_device = NULL;			return PTR_ERR(bd);		}		asus_backlight_device = bd;		bd->props.max_brightness = 15;		bd->props.brightness = read_brightness(NULL);		bd->props.power = FB_BLANK_UNBLANK;		backlight_update_status(bd);	}	return 0;}static int asus_led_register(acpi_handle handle,			     struct led_classdev *ldev, struct device *dev){	if (!handle)		return 0;	return led_classdev_register(dev, ldev);}#define ASUS_LED_REGISTER(object, device)				\	asus_led_register(object##_set_handle, &object##_led, device)static int asus_led_init(struct device *dev){	int rv;	rv = ASUS_LED_REGISTER(mled, dev);	if (rv)		goto out;	rv = ASUS_LED_REGISTER(tled, dev);	if (rv)		goto out1;	rv = ASUS_LED_REGISTER(rled, dev);	if (rv)		goto out2;	rv = ASUS_LED_REGISTER(pled, dev);	if (rv)		goto out3;	rv = ASUS_LED_REGISTER(gled, dev);	if (rv)		goto out4;	led_workqueue = create_singlethread_workqueue("led_workqueue");	if (!led_workqueue)		goto out5;	return 0;out5:	rv = -ENOMEM;	ASUS_LED_UNREGISTER(gled);out4:	ASUS_LED_UNREGISTER(pled);out3:	ASUS_LED_UNREGISTER(rled);out2:	ASUS_LED_UNREGISTER(tled);out1:	ASUS_LED_UNREGISTER(mled);out:	return rv;}static int __init asus_laptop_init(void){	struct device *dev;	int result;	if (acpi_disabled)		return -ENODEV;	result = acpi_bus_register_driver(&asus_hotk_driver);	if (result < 0)		return result;	/*	 * This is a bit of a kludge.  We only want this module loaded	 * for ASUS systems, but there's currently no way to probe the	 * ACPI namespace for ASUS HIDs.  So we just return failure if	 * we didn't find one, which will cause the module to be	 * unloaded.	 */	if (!asus_hotk_found) {		acpi_bus_unregister_driver(&asus_hotk_driver);		return -ENODEV;	}	dev = acpi_get_physical_device(hotk->device->handle);	result = asus_backlight_init(dev);	if (result)		goto fail_backlight;	result = asus_led_init(dev);	if (result)		goto fail_led;	/* Register platform stuff */	result = platform_driver_register(&asuspf_driver);	if (result)		goto fail_platform_driver;	asuspf_device = platform_device_alloc(ASUS_HOTK_FILE, -1);	if (!asuspf_device) {		result = -ENOMEM;		goto fail_platform_device1;	}	result = platform_device_add(asuspf_device);	if (result)		goto fail_platform_device2;	result = sysfs_create_group(&asuspf_device->dev.kobj,				    &asuspf_attribute_group);	if (result)		goto fail_sysfs;	return 0;      fail_sysfs:	platform_device_del(asuspf_device);      fail_platform_device2:	platform_device_put(asuspf_device);      fail_platform_device1:	platform_driver_unregister(&asuspf_driver);      fail_platform_driver:	asus_led_exit();      fail_led:	asus_backlight_exit();      fail_backlight:	return result;}module_init(asus_laptop_init);module_exit(asus_laptop_exit);

⌨️ 快捷键说明

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