BSDFan, a simple fan control utility for ThinkPads

If you've ever used FreeBSD (or any other BSD for that matter) on a ThinkPad you might have noticed the loud and erratic behavior of the fan. I've written a small utility as per title to manage the fan and improve silence, coolness and battery life. If anyone finds it useful I'll make a port for it.

Be careful when playing with fan levels and temperatures.

Have fun.

https://github.com/darklightclod/bsdfan
 
I'm test this for my Lenovo X220, unfortunately it does not work (set 0 speed).
Code:
# sysctl -a | grep thermal
hw.acpi.thermal.min_runtime: 0
hw.acpi.thermal.polling_rate: 10
hw.acpi.thermal.user_override: 0
hw.acpi.thermal.tz0.temperature: 62.0C
hw.acpi.thermal.tz0.active: -1
hw.acpi.thermal.tz0.passive_cooling: 0
hw.acpi.thermal.tz0.thermal_flags: 0
hw.acpi.thermal.tz0._PSV: -1
hw.acpi.thermal.tz0._HOT: -1
hw.acpi.thermal.tz0._CRT: 99.0C
hw.acpi.thermal.tz0._ACx: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
hw.acpi.thermal.tz0._TC1: -1
hw.acpi.thermal.tz0._TC2: -1
hw.acpi.thermal.tz0._TSP: -1
# sysctl -a | grep fan
dev.acpi_ibm.0.fan_speed: 4481
dev.acpi_ibm.0.fan_level: 7
dev.acpi_ibm.0.fan: 0
Code:
# bsdfan -d -c /usr/local/etc/bsdfan.conf
# sysctl -a | grep fan
dev.acpi_ibm.0.fan_speed: 3931
dev.acpi_ibm.0.fan_level: 0
dev.acpi_ibm.0.fan: 0
# sysctl -a | grep thermal
hw.acpi.thermal.min_runtime: 0
hw.acpi.thermal.polling_rate: 10
hw.acpi.thermal.user_override: 0
hw.acpi.thermal.tz0.temperature: 62.0C
hw.acpi.thermal.tz0.active: -1
hw.acpi.thermal.tz0.passive_cooling: 0
hw.acpi.thermal.tz0.thermal_flags: 0
hw.acpi.thermal.tz0._PSV: -1
hw.acpi.thermal.tz0._HOT: -1
hw.acpi.thermal.tz0._CRT: 99.0C
hw.acpi.thermal.tz0._ACx: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
hw.acpi.thermal.tz0._TC1: -1
hw.acpi.thermal.tz0._TC2: -1
hw.acpi.thermal.tz0._TSP: -1
 
I'm test this for my Lenovo X220, unfortunately does not work (set 0 speed)
Sorry for the late reply, could you try and start it not in daemon mode and see if there are any errors? Also post your configuration and sysctl dev.acpi_ibm before and while it's running. I can't seem to reproduce it here.
 
Sorry for the late reply, could you try and start it not in daemon mode and see if there are any errors? also post your config and sysct dev.acpi_ibm before and while it's running. I can't seem to reproduce it here.
Code:
codedev.acpi_ibm.%parent:
dev.acpi_ibm.0.%desc: IBM ThinkPad ACPI Extras
dev.acpi_ibm.0.%driver: acpi_ibm
dev.acpi_ibm.0.%location: handle=\_SB_.PCI0.LPC_.EC__.HKEY
dev.acpi_ibm.0.%pnpinfo: _HID=LEN0068 _UID=0
dev.acpi_ibm.0.%parent: acpi0
dev.acpi_ibm.0.initialmask: 2060
dev.acpi_ibm.0.availmask: 134217727
dev.acpi_ibm.0.events: 0
dev.acpi_ibm.0.eventmask: 2060
dev.acpi_ibm.0.hotkey: 3353
dev.acpi_ibm.0.lcd_brightness: 0
dev.acpi_ibm.0.volume: 10
dev.acpi_ibm.0.mute: 0
dev.acpi_ibm.0.thinklight: 0
dev.acpi_ibm.0.bluetooth: 0
dev.acpi_ibm.0.wlan: 1
dev.acpi_ibm.0.fan_speed: 4464
dev.acpi_ibm.0.fan_level: 7
dev.acpi_ibm.0.fan: 0
dev.acpi_ibm.0.handlerevents: NONE
If I start bsdfan -c /usr/local/etc/bsdfan.conf it does not produce any error messages as the fan speed becomes set to zero, after start.
Code:
# sysctl dev.acpi_ibm
...
dev.acpi_ibm.0.fan_speed: 3424 <-- slowly decreases to 0
dev.acpi_ibm.0.fan_level: 0  <--- set 0 after start bsdfan
...
 
Could you show me your bsdfan.conf ?
I haven't changed this.
Code:
# diff --report-identical-files /usr/local/etc/bsdfan.conf /home/andrey/bsdfan/bsdfan.conf 
Files /usr/local/etc/bsdfan.conf and /home/andrey/bsdfan/bsdfan.conf are identical
 
Ah! I don't know how I missed it in the other post, it seems like you lack dev.acpi_ibm.0.thermal, which is where it gets the temperatures from, I'm not sure why (hardware not fully supported by the driver perhaps?), I could look at hw.acpi.thermal.tz0.temperature instead but I suggest you first try to find out why the driver does not have the sysctl. What version of FreeBSD are you using?
 
Code:
FreeBSD 11.0-CURRENT #0 r273477: Tue Oct 28
It looks like it is a feature of new models of Lenovo, they do not fully realize the old acpi_ibm.
 
The new code does not compile, the first error I fixed:
Code:
% git diff
diff --git a/system.c b/system.c
index 310539d..27e6cf0 100644
--- a/system.c
+++ b/system.c
@@ -31,7 +31,7 @@ void setFan(int mode,struct Level *levels)
 
  /*get mib for dev.acpi_ibm.0.thermal*/
  len = 4;
-  if (sysctlnametomib("dev.acpi_ibm.0.thermal",mib_get_temp_level,&len) == -1);
+  if (sysctlnametomib("dev.acpi_ibm.0.thermal",mib_get_temp_level,&len) == -1)
  {
  len = 5;
  /*get mib for hw.acpi.thermal.tz0.temperature*/
How to correct the mistake I do not know.
Code:
% make
clang -c -Wall -O3 system.c -o system.o
system.c:92:9: error: use of undeclared identifier 'temp'
  return temp[0];
  ^
1 error generated.
*** Error code 1

Stop.
make: stopped in /usr/home/andrey/bsdfan
 
Okay, now it builds and runs correctly. But the speed increases only; immediately after the start it's small and growing about a minute to a
Code:
maximum dev.acpi_ibm.0.fan_level: 7
I made this configuration:
Code:
level (0,0,25)
level (1,23,35)
level (2,32,45)
level (3,42,55)
level (4,52,65)
level (5,62,75)
level (6,72,85)
level (7,82,32767)
Current temperature
Code:
hw.acpi.thermal.tz0.temperature: 63.0C
 
Ok, I can't even build it from here, you could try to get the latest version, add a
Code:
printf("Temp: %d",cur_temp);
at the end of bsdfan.c right before
Code:
oldtemp = cur_temp;
in the while loop. Build, launch without -d and let's see what's the output.
 
Sorry it took a while, life got in the way, apparently hw.acpi.thermal.tz0.temperature returns Celsius using /usr/sbin/sysctl but when doing a sysctl in C it returns Kelvin. I have no idea if it's intentional or wrong but anyways I made some changes and it should work now. I tested it here and it worked fine :)
 
Hi clod89, looking through your code, I feel compelled giving some unsolicited advice :D

Now that you have it working properly, you should take the time for some cleanup:
  • Eliminate typos in strings.
  • Format the code according to a single scheme you like.
It helps a lot when it grows (and projects tend to do so).

On a side node, the daemon(3) function looks like a nice time/SLOC-saver for code that doesn't need to be portable -- this one was new to me.
 
I'd just like to report that this works wonderfully on my T61. Great work.

If you were working on a second version, a RC script would be wonderful!
 
Back
Top