Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ linux_platform_headers = \
linux/ProcessField.h \
linux/SELinuxMeter.h \
linux/SystemdMeter.h \
linux/ThinkpadFan.h \
linux/ZramMeter.h \
linux/ZramStats.h \
linux/ZswapStats.h \
Expand All @@ -230,6 +231,7 @@ linux_platform_sources = \
linux/PressureStallMeter.c \
linux/SELinuxMeter.c \
linux/SystemdMeter.c \
linux/ThinkpadFan.c \
linux/ZramMeter.c \
zfs/ZfsArcMeter.c \
zfs/ZfsCompressedArcMeter.c
Expand Down
20 changes: 20 additions & 0 deletions linux/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ in the source distribution for its full text.
#include "linux/OpenRCMeter.h"
#include "linux/SELinuxMeter.h"
#include "linux/SystemdMeter.h"
#include "linux/ThinkpadFan.h"
#include "linux/ZramMeter.h"
#include "linux/ZramStats.h"
#include "linux/ZswapStats.h"
Expand Down Expand Up @@ -277,6 +278,7 @@ const MeterClass* const Platform_meterTypes[] = {
&OpenRCUserMeter_class,
&FileDescriptorMeter_class,
&GPUMeter_class,
&ThinkpadFanMeter_class,
NULL
};

Expand Down Expand Up @@ -991,6 +993,24 @@ void Platform_getBattery(double* percent, ACPresence* isOnAC) {
Platform_Battery_cacheTime = now;
}

int Platform_getThinkpadFan(void) {
char fandata[256];
ssize_t fanread = Compat_readfile(PROCDIR "/acpi/ibm/fan", fandata, sizeof(fandata));
if (fanread < 1)
return -1;

const char* speed = strstr(fandata, "speed:");
if (!speed)
return -1;

int rpm;
int n = sscanf(speed, "speed: %d", &rpm);
if (n != 1)
return -1;
Comment thread
BenBE marked this conversation as resolved.

return rpm;
}

void Platform_longOptionsUsage(const char* name)
{
#ifdef HAVE_LIBCAP
Expand Down
2 changes: 2 additions & 0 deletions linux/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ bool Platform_getNetworkIO(NetworkIOData* data);

void Platform_getBattery(double* percent, ACPresence* isOnAC);

int Platform_getThinkpadFan(void);

static inline void Platform_getHostname(char* buffer, size_t size) {
Generic_hostname(buffer, size);
}
Expand Down
44 changes: 44 additions & 0 deletions linux/ThinkpadFan.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
htop - ThinkpadFan.c
(C) 2026 Murad Karammaev
Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/

#include "config.h" // IWYU pragma: keep

#include "linux/ThinkpadFan.h"

#include "CRT.h"
#include "Object.h"
#include "XUtils.h"
#include "linux/Platform.h"


Comment thread
BenBE marked this conversation as resolved.
static const int ThinkpadFanMeter_attributes[] = {
METER_VALUE
};

static void ThinkpadFanMeter_updateValues(Meter* this) {
int fanspeed = Platform_getThinkpadFan();
if (fanspeed < 0)
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "N/A");
else
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%d RPM", fanspeed);
}

const MeterClass ThinkpadFanMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete
},
.updateValues = ThinkpadFanMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.supportedModes = (1 << TEXT_METERMODE) | (1 << LED_METERMODE),
.maxItems = 0,
.total = 0.0,
.attributes = ThinkpadFanMeter_attributes,
.name = "ThinkpadFan",
.uiName = "Thinkpad fan speed",
.caption = "Thinkpad fan: ",
};
15 changes: 15 additions & 0 deletions linux/ThinkpadFan.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef HEADER_ThinkpadFan
#define HEADER_ThinkpadFan
/*
htop - ThinkpadFan.h
(C) 2026 Murad Karammaev
Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/

#include "Meter.h"


extern const MeterClass ThinkpadFanMeter_class;

#endif
Loading