mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-02 03:28:28 -04:00
90291bd627
ppd, and some things. Add a simple wpa_supplicant backend
163 lines
2.9 KiB
Go
163 lines
2.9 KiB
Go
package brightness
|
|
|
|
import (
|
|
"net"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
|
)
|
|
|
|
// devd(8) publishes device events on this SOCK_SEQPACKET socket, one
|
|
// "!system=... subsystem=... type=..." record per packet.
|
|
const devdSocketPath = "/var/run/devd.seqpacket.pipe"
|
|
|
|
const (
|
|
devdMaxRetries = 5
|
|
devdBaseDelay = 2 * time.Second
|
|
devdMaxDelay = 60 * time.Second
|
|
)
|
|
|
|
type DevdMonitor struct {
|
|
stop chan struct{}
|
|
rescanMutex sync.Mutex
|
|
rescanTimer *time.Timer
|
|
rescanPending bool
|
|
}
|
|
|
|
func newDevdMonitor(manager *Manager) *DevdMonitor {
|
|
m := &DevdMonitor{
|
|
stop: make(chan struct{}),
|
|
}
|
|
|
|
go m.run(manager)
|
|
return m
|
|
}
|
|
|
|
func (m *DevdMonitor) run(manager *Manager) {
|
|
failures := 0
|
|
for {
|
|
if err := m.monitorLoop(manager); err != nil {
|
|
log.Errorf("Devd monitor error: %v", err)
|
|
}
|
|
|
|
select {
|
|
case <-m.stop:
|
|
return
|
|
default:
|
|
}
|
|
|
|
failures++
|
|
if failures > devdMaxRetries {
|
|
log.Errorf("Devd monitor exceeded %d retries, giving up", devdMaxRetries)
|
|
return
|
|
}
|
|
|
|
delay := min(devdBaseDelay*time.Duration(1<<(failures-1)), devdMaxDelay)
|
|
log.Infof("Devd monitor reconnecting in %v (attempt %d/%d)", delay, failures, devdMaxRetries)
|
|
|
|
select {
|
|
case <-m.stop:
|
|
return
|
|
case <-time.After(delay):
|
|
}
|
|
}
|
|
}
|
|
|
|
func (m *DevdMonitor) monitorLoop(manager *Manager) error {
|
|
conn, err := net.Dial("unixpacket", devdSocketPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
done := make(chan struct{})
|
|
defer close(done)
|
|
go func() {
|
|
select {
|
|
case <-m.stop:
|
|
conn.Close()
|
|
case <-done:
|
|
}
|
|
}()
|
|
|
|
log.Info("Devd monitor started for backlight/drm events")
|
|
|
|
buf := make([]byte, 8192)
|
|
for {
|
|
n, err := conn.Read(buf)
|
|
if err != nil {
|
|
select {
|
|
case <-m.stop:
|
|
return nil
|
|
default:
|
|
return err
|
|
}
|
|
}
|
|
m.handleEvent(manager, string(buf[:n]))
|
|
}
|
|
}
|
|
|
|
func (m *DevdMonitor) handleEvent(manager *Manager, event string) {
|
|
notification, ok := strings.CutPrefix(event, "!")
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
fields := parseDevdEvent(notification)
|
|
switch fields["system"] {
|
|
case "DRM":
|
|
m.debouncedRescan(manager)
|
|
case "DEVFS":
|
|
if fields["subsystem"] != "CDEV" {
|
|
return
|
|
}
|
|
if !strings.HasPrefix(fields["cdev"], "backlight/") {
|
|
return
|
|
}
|
|
m.debouncedRescan(manager)
|
|
}
|
|
}
|
|
|
|
func parseDevdEvent(s string) map[string]string {
|
|
fields := make(map[string]string)
|
|
for _, part := range strings.Fields(s) {
|
|
k, v, ok := strings.Cut(part, "=")
|
|
if !ok {
|
|
continue
|
|
}
|
|
fields[k] = v
|
|
}
|
|
return fields
|
|
}
|
|
|
|
func (m *DevdMonitor) debouncedRescan(manager *Manager) {
|
|
m.rescanMutex.Lock()
|
|
defer m.rescanMutex.Unlock()
|
|
|
|
m.rescanPending = true
|
|
|
|
if m.rescanTimer != nil {
|
|
m.rescanTimer.Reset(2 * time.Second)
|
|
return
|
|
}
|
|
|
|
m.rescanTimer = time.AfterFunc(2*time.Second, func() {
|
|
m.rescanMutex.Lock()
|
|
pending := m.rescanPending
|
|
m.rescanPending = false
|
|
m.rescanMutex.Unlock()
|
|
|
|
if !pending {
|
|
return
|
|
}
|
|
|
|
manager.Rescan()
|
|
})
|
|
}
|
|
|
|
func (m *DevdMonitor) Close() {
|
|
close(m.stop)
|
|
}
|