-
-
Save felipec/6169047 to your computer and use it in GitHub Desktop.
/* | |
* | |
* obj-m := fan.o | |
* KDIR := /lib/modules/$(shell uname -r)/build | |
* PWD := $(shell pwd) | |
* | |
* all: | |
* $(MAKE) -C $(KDIR) M=$(PWD) modules | |
* | |
* clean: | |
* $(MAKE) -C $(KDIR) M=$(PWD) clean | |
*/ | |
#include <linux/module.h> | |
#include <linux/kernel.h> | |
#include <linux/init.h> | |
#include <linux/acpi.h> | |
#include <linux/thermal.h> | |
#include <linux/dmi.h> | |
MODULE_AUTHOR("Felipe Contreras <felipe.contreras@gmail.com>"); | |
MODULE_DESCRIPTION("ASUS fan driver"); | |
MODULE_LICENSE("GPL"); | |
static struct thermal_cooling_device *cdev; | |
static int fan_get_max_state(struct thermal_cooling_device *cdev, | |
unsigned long *state) | |
{ | |
*state = 0xff; | |
return 0; | |
} | |
static int fan_get_cur_state(struct thermal_cooling_device *cdev, | |
unsigned long *state) | |
{ | |
struct acpi_object_list params; | |
union acpi_object in_objs[1]; | |
unsigned long long value; | |
acpi_status r; | |
params.count = ARRAY_SIZE(in_objs); | |
params.pointer = in_objs; | |
in_objs[0].type = ACPI_TYPE_INTEGER; | |
in_objs[0].integer.value = 0; | |
r = acpi_evaluate_integer(NULL, "\\_TZ.RFAN", ¶ms, &value); | |
if (r != AE_OK) | |
return r; | |
*state = value; | |
return 0; | |
} | |
static int fan_set(struct thermal_cooling_device *cdev, int fan, int speed) | |
{ | |
struct acpi_object_list params; | |
union acpi_object in_objs[2]; | |
unsigned long long value; | |
params.count = ARRAY_SIZE(in_objs); | |
params.pointer = in_objs; | |
in_objs[0].type = ACPI_TYPE_INTEGER; | |
in_objs[0].integer.value = fan; | |
in_objs[1].type = ACPI_TYPE_INTEGER; | |
in_objs[1].integer.value = speed; | |
return acpi_evaluate_integer(NULL, "\\_SB.PCI0.LPCB.EC0.SFNV", ¶ms, &value); | |
} | |
static int fan_set_cur_state(struct thermal_cooling_device *cdev, | |
unsigned long state) | |
{ | |
return fan_set(cdev, 1, state); | |
} | |
static int fan_set_auto(struct thermal_cooling_device *cdev) | |
{ | |
return fan_set(cdev, 0, 0); | |
} | |
static const struct thermal_cooling_device_ops fan_cooling_ops = { | |
.get_max_state = fan_get_max_state, | |
.get_cur_state = fan_get_cur_state, | |
.set_cur_state = fan_set_cur_state, | |
}; | |
static int __init fan_init(void) | |
{ | |
if (strcmp(dmi_get_system_info(DMI_SYS_VENDOR), "ASUSTeK COMPUTER INC.")) | |
return -ENODEV; | |
cdev = thermal_cooling_device_register("Fan", NULL, &fan_cooling_ops); | |
if (IS_ERR(cdev)) | |
return PTR_ERR(cdev); | |
fan_set_auto(cdev); | |
return 0; | |
} | |
static void __exit fan_exit(void) | |
{ | |
fan_set_auto(cdev); | |
thermal_cooling_device_unregister(cdev); | |
} | |
module_init(fan_init); | |
module_exit(fan_exit); |
Hi there! Thank you very much for this!! This fan on-off-on-off is driving me crazy, it forces me sometimes to work with Windows, because there that NotebookFanControl program works perfectly and makes working almost fan/noise-less (CPU temp while working with Office / Browsing web is always around 45-55°C here and normaly the fan turn on at 50°C. NBFC forces the fan to start at 60°C).
Could you please provide some more info about compiling and using this peace of code?
I get the following error under Kubuntu x64 when trying to compile with gcc
asus_fan.c:14:26: fatal error: linux/module.h: No such file or directory
compilation terminated.
Kernels header should be installed here.
you have a makefile at the top of the file .... just create one with those few lines and run make all... you can then insmod the .ko produced... if you get an error like "file exists" you probably already have a module name "fan" running ... rmmod it and re-run insmod.
Hi, I compiled and inserted the module too, but I'm stuck there, as the fan isn't seen by 'sensors' program, and there seems to be no way to control it.
What I'm I missing? Do I need to recompile the kernel with the modified asus-laptop.c?
By the way, I'm running Arch Linux on 3.10.9-1 stock kernel.
Thank you.
I do have a "asus" part in sensors
when it is modprobed. However, cpu temperature is pretty much all I got. So I still don't have any fan informations...
If you don't have any informations, maybe you do not have acpi stuff installed...
@asuxer: thanks for the lkml link, I hope it will keep going on...
OK I give up...
I recompiled the original Ubuntu kernel, but patched it with the diff from here
https://lkml.org/lkml/2013/10/8/800
(http://www.gossamer-threads.com/lists/linux/kernel/1796054)
Reboot, then I re-run sensors-detect, then sudo pwmconfig (from package fancontrol) but still I get
/usr/sbin/pwmconfig: There are no fan-capable sensor modules installed
felipec, please tell us what you did. You say it works perfectly for you?
@asuxer this module don't create /sys/class/hwmon
devices. Control your fan with:
$ echo 200 | sudo tee /sys/class/thermal/cooling_deviceN/cur_state
- added full Makefile
- added "hack" to set fan back to automatic without unloading the module
-> forked here: https://gist.github.com/daringer/721e2cea17b570512097
Compilation and Modprobe worked for me on my arch, on a 3.9.9-1-ARCH x64. But how to use it ? Can't wait to get it working ! Thank you so much for this code !