mirror of
https://github.com/mainnika/acpi-wakeup-fixxer.git
synced 2026-05-22 15:53:40 +00:00
initial setup of an app to toggle acpi wakeup devices
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
package wakeup
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"code.tokarch.uk/mainnika/acpi-wakeup-fixxer/pkg/procfs"
|
||||
)
|
||||
|
||||
const (
|
||||
deviceHeader = "Device"
|
||||
columnDeviceIndex = 0
|
||||
columnStatusIndex = 2
|
||||
columnIndexMax = 3
|
||||
)
|
||||
|
||||
type Status string
|
||||
|
||||
const StatusAll Status = ""
|
||||
const StatusEnabled Status = "*enabled"
|
||||
const StatusDisabled Status = "*disabled"
|
||||
|
||||
type WakeupController struct {
|
||||
ProcfsProvider procfs.Procfs
|
||||
}
|
||||
|
||||
func NewWakeupController() *WakeupController {
|
||||
return &WakeupController{ProcfsProvider: &procfs.ProcfsDefaultPath{}}
|
||||
}
|
||||
|
||||
func (w *WakeupController) GetWakeupDevices(withStatus Status) ([]string, error) {
|
||||
wakeupFile, err := w.ProcfsProvider.ACPIWakeup()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get wakeup file: %w", err)
|
||||
}
|
||||
defer func() { _ = wakeupFile.Close() }()
|
||||
|
||||
scanner := bufio.NewScanner(wakeupFile)
|
||||
var devices []string
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < columnIndexMax {
|
||||
slog.Warn("unexpected number of columns", "line", line)
|
||||
continue
|
||||
}
|
||||
|
||||
device := fields[columnDeviceIndex]
|
||||
if device == deviceHeader {
|
||||
continue
|
||||
}
|
||||
|
||||
status := Status(fields[columnStatusIndex])
|
||||
if withStatus != StatusAll && status != withStatus {
|
||||
continue
|
||||
}
|
||||
|
||||
devices = append(devices, device)
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("failed to scan wakeup file: %w", err)
|
||||
}
|
||||
|
||||
return devices, nil
|
||||
}
|
||||
|
||||
func (w *WakeupController) ToggleWakeupDevice(device string) error {
|
||||
wakeupFile, err := w.ProcfsProvider.ACPIWakeupWrite()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open wakeup file for writing: %w", err)
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(wakeupFile, "%s\n", device)
|
||||
if err != nil {
|
||||
_ = wakeupFile.Close()
|
||||
return fmt.Errorf("failed to write to wakeup file: %w", err)
|
||||
}
|
||||
|
||||
err = wakeupFile.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to close wakeup file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package wakeup
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type procfsMock struct{}
|
||||
|
||||
func (p *procfsMock) ACPIWakeup() (io.ReadCloser, error) {
|
||||
const testFileRaw = `Device S-state Status Sysfs node
|
||||
PEG0 S3 *disabled
|
||||
EC S4 *disabled platform:PNP0C09:00
|
||||
HDEF S3 *disabled pci:0000:00:1b.0
|
||||
RP01 S3 *enabled pci:0000:00:1c.0
|
||||
RP02 S3 *enabled pci:0000:00:1c.1
|
||||
RP03 S3 *enabled pci:0000:00:1c.2
|
||||
ARPT S4 *enabled pci:0000:03:00.0
|
||||
RP05 S3 *enabled pci:0000:00:1c.4
|
||||
RP06 S3 *enabled pci:0000:00:1c.5
|
||||
SPIT S3 *disabled spi:spi-APP000D:00
|
||||
XHC1 S3 *disabled pci:0000:00:14.0
|
||||
ADP1 S4 *disabled platform:ACPI0003:00
|
||||
LID0 S4 *disabled platform:PNP0C0D:00
|
||||
`
|
||||
|
||||
return io.NopCloser(strings.NewReader(testFileRaw)), nil
|
||||
}
|
||||
|
||||
func (p *procfsMock) ACPIWakeupWrite() (io.WriteCloser, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func TestSomething(t *testing.T) {
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
wantStatus Status
|
||||
wantDevices []string
|
||||
}{
|
||||
{
|
||||
name: "Read and parse successfully",
|
||||
wantStatus: StatusEnabled,
|
||||
wantDevices: []string{
|
||||
"RP01",
|
||||
"RP02",
|
||||
"RP03",
|
||||
"RP05",
|
||||
"RP06",
|
||||
"ARPT",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Read and parse disabled successfully",
|
||||
wantStatus: StatusDisabled,
|
||||
wantDevices: []string{
|
||||
"PEG0",
|
||||
"EC",
|
||||
"HDEF",
|
||||
"SPIT",
|
||||
"XHC1",
|
||||
"ADP1",
|
||||
"LID0",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Read and parse all successfully",
|
||||
wantStatus: StatusAll,
|
||||
wantDevices: []string{
|
||||
"RP01",
|
||||
"RP02",
|
||||
"RP03",
|
||||
"RP05",
|
||||
"RP06",
|
||||
"ARPT",
|
||||
"PEG0",
|
||||
"EC",
|
||||
"HDEF",
|
||||
"SPIT",
|
||||
"XHC1",
|
||||
"ADP1",
|
||||
"LID0",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
c := NewWakeupController()
|
||||
c.ProcfsProvider = &procfsMock{}
|
||||
|
||||
devices, err := c.GetWakeupDevices(tc.wantStatus)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Len(t, devices, len(tc.wantDevices))
|
||||
for i, wantDevice := range tc.wantDevices {
|
||||
assert.Contains(t, devices, wantDevice, "device %d not found", i)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user