Skip to content
This repository has been archived by the owner on Sep 20, 2023. It is now read-only.

Commit

Permalink
sysfs: include thermal sensors from hwmon (#352)
Browse files Browse the repository at this point in the history
* sysfs: include thermal sensors from hwmon, like those added by the w1_therm kernel model

* Update the ThermalSensors comment
  • Loading branch information
davidsansome authored and maruel committed Dec 20, 2018
1 parent 17c9e16 commit 1bed8c9
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 32 deletions.
75 changes: 52 additions & 23 deletions host/sysfs/thermal_sensor.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import (
"periph.io/x/periph/conn/physic"
)

// ThermalSensors is all the sensors discovered on this host via sysfs.
// ThermalSensors is all the sensors discovered on this host via sysfs. It
// includes 'thermal' devices as well as temperature 'hwmon' devices, so
// pre-configured onewire temperature sensors will be discovered automatically.
var ThermalSensors []*ThermalSensor

// ThermalSensorByName returns a *ThermalSensor for the sensor name, if any.
Expand All @@ -39,8 +41,10 @@ func ThermalSensorByName(name string) (*ThermalSensor, error) {

// ThermalSensor represents one thermal sensor on the system.
type ThermalSensor struct {
name string
root string
name string
root string
sensorFilename string
typeFilename string

mu sync.Mutex
nameType string
Expand All @@ -62,25 +66,35 @@ func (t *ThermalSensor) Type() string {
t.mu.Lock()
defer t.mu.Unlock()
if t.nameType == "" {
f, err := fileIOOpen(t.root+"type", os.O_RDONLY)
nameType, err := t.readType()
if err != nil {
return fmt.Sprintf("sysfs-thermal: %v", err)
}
defer f.Close()
var buf [256]byte
n, err := f.Read(buf[:])
if err != nil {
return fmt.Sprintf("sysfs-thermal: %v", err)
}
if n < 2 {
t.nameType = "<unknown>"
} else {
t.nameType = string(buf[:n-1])
return err.Error()
}
t.nameType = nameType
}
return t.nameType
}

func (t *ThermalSensor) readType() (string, error) {
f, err := fileIOOpen(t.root+t.typeFilename, os.O_RDONLY)
if os.IsNotExist(err) {
return "<unknown>", nil
}
if err != nil {
return "", fmt.Errorf("sysfs-thermal: %v", err)
}
defer f.Close()
var buf [256]byte
n, err := f.Read(buf[:])
if err != nil {
return "", fmt.Errorf("sysfs-thermal: %v", err)
}
if n < 2 {
return "<unknown>", nil
}
return string(buf[:n-1]), nil
}

// Sense implements physic.SenseEnv.
func (t *ThermalSensor) Sense(e *physic.Env) error {
if err := t.open(); err != nil {
Expand Down Expand Up @@ -136,7 +150,7 @@ func (t *ThermalSensor) open() error {
if t.f != nil {
return nil
}
f, err := fileIOOpen(t.root+"temp", os.O_RDONLY)
f, err := fileIOOpen(t.root+t.sensorFilename, os.O_RDONLY)
if err != nil {
return fmt.Errorf("sysfs-thermal: %v", err)
}
Expand Down Expand Up @@ -167,24 +181,39 @@ func (d *driverThermalSensor) After() []string {
//
// * for the most minimalistic meaning of 'described'.
func (d *driverThermalSensor) Init() (bool, error) {
if err := d.discoverDevices("/sys/class/thermal/*/temp", "type"); err != nil {
return true, err
}
if err := d.discoverDevices("/sys/class/hwmon/*/temp*_input", "device/name"); err != nil {
return true, err
}
if len(ThermalSensors) == 0 {
return false, errors.New("sysfs-thermal: no sensor found")
}
return true, nil
}

func (d *driverThermalSensor) discoverDevices(glob, typeFilename string) error {
// This driver is only registered on linux, so there is no legitimate time to
// skip it.
items, err := filepath.Glob("/sys/class/thermal/*/temp")
items, err := filepath.Glob(glob)
if err != nil {
return true, err
return err
}
if len(items) == 0 {
return false, errors.New("sysfs-thermal: no sensor found")
return nil
}
sort.Strings(items)
for _, item := range items {
base := filepath.Dir(item)
ThermalSensors = append(ThermalSensors, &ThermalSensor{
name: filepath.Base(base),
root: base + "/",
name: filepath.Base(base),
root: base + "/",
sensorFilename: filepath.Base(item),
typeFilename: typeFilename,
})
}
return true, nil
return nil
}

func init() {
Expand Down
38 changes: 29 additions & 9 deletions host/sysfs/thermal_sensor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,32 @@ func TestThermalSensor_Type_success(t *testing.T) {
return nil, errors.New("unknown file")
}
}
d := ThermalSensor{name: "cpu", root: "//\000/"}
d := ThermalSensor{name: "cpu", root: "//\000/", typeFilename: "type"}
if s := d.Type(); s != "dummy" {
t.Fatal(s)
}
}

func TestThermalSensor_Type_NotFoundIsUnknown(t *testing.T) {
defer resetThermal()
fileIOOpen = func(path string, flag int) (fileIO, error) {
if flag != os.O_RDONLY {
t.Fatal(flag)
}
switch path {
case "//\x00/type":
return nil, os.ErrNotExist
default:
t.Fatalf("unknown %q", path)
return nil, errors.New("unknown file")
}
}
d := ThermalSensor{name: "cpu", root: "//\000/", typeFilename: "type"}
if s := d.Type(); s != "<unknown>" {
t.Fatal(s)
}
}

func TestThermalSensor_Type_fail_1(t *testing.T) {
defer resetThermal()
fileIOOpen = func(path string, flag int) (fileIO, error) {
Expand All @@ -95,7 +115,7 @@ func TestThermalSensor_Type_fail_1(t *testing.T) {
return nil, errors.New("unknown file")
}
}
d := ThermalSensor{name: "cpu", root: "//\000/"}
d := ThermalSensor{name: "cpu", root: "//\000/", typeFilename: "type"}
if s := d.Type(); s != "sysfs-thermal: not implemented" {
t.Fatal(s)
}
Expand All @@ -115,7 +135,7 @@ func TestThermalSensor_Type_fail_2(t *testing.T) {
return nil, errors.New("unknown file")
}
}
d := ThermalSensor{name: "cpu", root: "//\000/"}
d := ThermalSensor{name: "cpu", root: "//\000/", typeFilename: "type"}
if s := d.Type(); s != "<unknown>" {
t.Fatal(s)
}
Expand All @@ -135,7 +155,7 @@ func TestThermalSensor_Sense_success(t *testing.T) {
return nil, errors.New("unknown file")
}
}
d := ThermalSensor{name: "cpu", root: "//\000/"}
d := ThermalSensor{name: "cpu", root: "//\000/", sensorFilename: "temp"}
e := physic.Env{}
if err := d.Sense(&e); err != nil {
t.Fatal(err)
Expand All @@ -159,7 +179,7 @@ func TestThermalSensor_Sense_fail_1(t *testing.T) {
return nil, errors.New("unknown file")
}
}
d := ThermalSensor{name: "cpu", root: "//\000/"}
d := ThermalSensor{name: "cpu", root: "//\000/", sensorFilename: "temp"}
e := physic.Env{}
if err := d.Sense(&e); err == nil || err.Error() != "sysfs-thermal: not implemented" {
t.Fatal(err)
Expand All @@ -180,7 +200,7 @@ func TestThermalSensor_Sense_fail_2(t *testing.T) {
return nil, errors.New("unknown file")
}
}
d := ThermalSensor{name: "cpu", root: "//\000/"}
d := ThermalSensor{name: "cpu", root: "//\000/", sensorFilename: "temp"}
e := physic.Env{}
if err := d.Sense(&e); err == nil || err.Error() != "sysfs-thermal: failed to read temperature" {
t.Fatal(err)
Expand All @@ -201,7 +221,7 @@ func TestThermalSensor_Sense_fail_3(t *testing.T) {
return nil, errors.New("unknown file")
}
}
d := ThermalSensor{name: "cpu", root: "//\000/"}
d := ThermalSensor{name: "cpu", root: "//\000/", sensorFilename: "temp"}
e := physic.Env{}
err := d.Sense(&e)
if err == nil {
Expand Down Expand Up @@ -231,7 +251,7 @@ func TestThermalSensor_Precision_Kelvin(t *testing.T) {
return nil, errors.New("unknown file")
}
}
d := ThermalSensor{name: "cpu", root: "//\000/"}
d := ThermalSensor{name: "cpu", root: "//\000/", sensorFilename: "temp"}
e := physic.Env{}
d.Precision(&e)
if e.Temperature != physic.Kelvin {
Expand All @@ -253,7 +273,7 @@ func TestThermalSensor_Precision_MilliKelvin(t *testing.T) {
return nil, errors.New("unknown file")
}
}
d := ThermalSensor{name: "cpu", root: "//\000/"}
d := ThermalSensor{name: "cpu", root: "//\000/", sensorFilename: "temp"}
e := physic.Env{}
d.Precision(&e)
if e.Temperature != physic.MilliKelvin {
Expand Down

0 comments on commit 1bed8c9

Please sign in to comment.