# BSDFan, a simple fan control utility for ThinkPads



## clod89 (Nov 5, 2014)

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


----------



## f-andrey (Nov 12, 2014)

I'm test this for my Lenovo X220, unfortunately it does not work (set 0 speed).

```
# 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
```


```
# 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
```


----------



## clod89 (Nov 14, 2014)

f-andrey said:


> 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.


----------



## f-andrey (Nov 14, 2014)

clod89 said:


> 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.




```
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.

```
# 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
...
```


----------



## clod89 (Nov 18, 2014)

Could you show me your bsdfan.conf?


----------



## f-andrey (Nov 18, 2014)

clod89 said:


> Could you show me your bsdfan.conf ?


I haven't changed this.

```
# 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
```


----------



## clod89 (Nov 18, 2014)

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?


----------



## f-andrey (Nov 18, 2014)

```
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.


----------



## clod89 (Nov 18, 2014)

I'm at work right now so I can't test it, could you try with the changes I just committed ?


----------



## f-andrey (Nov 18, 2014)

The new code does not compile, the first error I fixed:

```
% 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.

```
% 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
```


----------



## clod89 (Nov 18, 2014)

Whoops, try it now.


----------



## f-andrey (Nov 18, 2014)

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 
	
	



```
maximum dev.acpi_ibm.0.fan_level: 7
```
I made this configuration:

```
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 
	
	



```
hw.acpi.thermal.tz0.temperature: 63.0C
```


----------



## clod89 (Nov 18, 2014)

Ok, I can't even build it from here, you could try to get the latest version, add a 
	
	



```
printf("Temp: %d",cur_temp);
```
 at the end of bsdfan.c right before 
	
	



```
oldtemp = cur_temp;
```
 in the while loop. Build, launch without -d and let's see what's the output.


----------



## f-andrey (Nov 18, 2014)

Unfortunately, there is no output*.*


----------



## clod89 (Nov 26, 2014)

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


----------



## f-andrey (Nov 26, 2014)

Excellent, now it works correctly


----------



## zirias@ (Nov 26, 2014)

Hi clod89, looking through your code, I feel compelled giving some unsolicited advice 

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.


----------



## dscrdia (Jan 16, 2015)

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!


----------

