Files
Zer0TraceXandclaude[bot] 87a4da9e13 feat(freebsd): Add initial native FreeBSD support (#3559)
* feat(freebsd): add comprehensive native FreeBSD support

* Update BatteryService.qml

* Add battery probe completion and fallback updates

* Add isVideoSource function and update PwObjectTracker filter

* Add isPipewireVideoSource function to AudioService

Added a function to check if a Pipewire node is a video source.

* Refactor video source check to use AudioService

* Remove unnecessary call in BatteryService.qml

* Add call to updateFreeBsdBatteryFallback on completion

* Simplify AudioService by eliminating redundant bindings

Removed unnecessary bindings in the AudioService loader to streamline the loading process.

* Improve error handling in CheckUpdates function

Handle specific exit error for package upgrade check.

* Enhance FreeBSD network detection logic

* Implement FreeBSD Wi-Fi hardware discovery in Initialize

Added FreeBSD Wi-Fi hardware discovery and updated initialization logic to handle cases where no wpa_supplicant control socket is found.

* Implement Ethernet state monitoring in StartMonitoring

Added monitoring for Ethernet state updates in StartMonitoring function.

* Add Ethernet management functions to backend

* Remove unimplemented Ethernet control methods

Removed unimplemented Ethernet control methods from WpaSupplicantBackend.

* Implement SetWiFiEnabled method for WiFi control

Add error handling and state management for WiFi control

* Update core/internal/server/network/backend_wpa_ethernet.go

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* Implement Ethernet monitoring in WpaSupplicantBackend

* Refactor startEthernetMonitor and add debounce logic

Refactor the startEthernetMonitor function to improve readability and maintainability. Introduce a debounce mechanism for processing relevant FreeBSD route events.

* Reorder import statements in backend_pkg.go

* Remove unnecessary blank line in backend_wpa_ethernet.go

* Implement FreeBSD audio polling based on UI visibility

Introduce a polling mechanism for FreeBSD audio device updates based on visibility of UI elements.

* Add readonly freeBsdPollingRequested property and optimize polling

Introduce a readonly property to determine if FreeBSD polling is requested based on various UI conditions. Update command execution to prioritize polling efficiency.

* Simplify freeBsdPollingRequested logic

Removed unnecessary conditions from freeBsdPollingRequested property.

* Implement reference counting for battery consumers

Added reference counting to manage battery information consumers and updated related functions for better battery state handling.

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-10-05 22:03:32 -04:00

142 lines
4.0 KiB
Go

package network
import (
"fmt"
"os"
"runtime"
"github.com/godbus/dbus/v5"
)
type BackendType int
const (
BackendNone BackendType = iota
BackendNetworkManager
BackendIwd
BackendConnMan
BackendNetworkd
BackendWpaSupplicant
)
func nameHasOwner(bus *dbus.Conn, name string) (bool, error) {
obj := bus.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
var owned bool
if err := obj.Call("org.freedesktop.DBus.NameHasOwner", 0, name).Store(&owned); err != nil {
return false, err
}
return owned, nil
}
type DetectResult struct {
Backend BackendType
HasNM bool
HasIwd bool
HasConnMan bool
HasWpaSupp bool
HasNetworkd bool
ChosenReason string
}
func wpaSupplicantCtrlDirPresent() bool {
info, err := os.Stat(wpaSupplicantCtrlDir)
return err == nil && info.IsDir()
}
func DetectNetworkStack() (*DetectResult, error) {
// FreeBSD uses the native ifconfig/wpa_supplicant backend regardless of
// whether unrelated Linux-oriented D-Bus services happen to be present.
if runtime.GOOS == "freebsd" {
hasWpa := wpaSupplicantCtrlDirPresent()
reason := "FreeBSD detected. Using native Ethernet interfaces."
if hasWpa {
reason = "FreeBSD detected with wpa_supplicant control directory. Using native Ethernet and wpa_ctrl Wi-Fi."
}
return &DetectResult{
Backend: BackendWpaSupplicant,
HasWpaSupp: hasWpa,
ChosenReason: reason,
}, nil
}
bus, err := dbus.ConnectSystemBus()
if err != nil {
if runtime.GOOS == "freebsd" {
hasWpa := wpaSupplicantCtrlDirPresent()
reason := "FreeBSD detected. Using native Ethernet interfaces."
if hasWpa {
reason = "FreeBSD detected with wpa_supplicant control directory. Using native Ethernet and wpa_ctrl Wi-Fi."
}
return &DetectResult{
Backend: BackendWpaSupplicant,
HasWpaSupp: hasWpa,
ChosenReason: reason,
}, nil
}
if !wpaSupplicantCtrlDirPresent() {
return nil, fmt.Errorf("connect system bus: %w", err)
}
return &DetectResult{
Backend: BackendWpaSupplicant,
HasWpaSupp: true,
ChosenReason: "System bus unreachable; wpa_supplicant control directory present. Using wpa_ctrl interface.",
}, nil
}
defer bus.Close()
hasNM, _ := nameHasOwner(bus, "org.freedesktop.NetworkManager")
hasIwd, _ := nameHasOwner(bus, "net.connman.iwd")
hasConn, _ := nameHasOwner(bus, "net.connman")
hasWpa, _ := nameHasOwner(bus, "fi.w1.wpa_supplicant1")
hasNetworkd, _ := nameHasOwner(bus, "org.freedesktop.network1")
res := &DetectResult{
HasNM: hasNM,
HasIwd: hasIwd,
HasConnMan: hasConn,
HasWpaSupp: hasWpa,
HasNetworkd: hasNetworkd,
}
switch {
case hasNM:
res.Backend = BackendNetworkManager
if hasIwd {
res.ChosenReason = "NetworkManager present; iwd also running (likely NM's Wi-Fi backend). Using NM API."
} else {
res.ChosenReason = "NetworkManager present. Using NM API."
}
case hasConn && hasIwd:
res.Backend = BackendConnMan
res.ChosenReason = "ConnMan + iwd detected. Use ConnMan API (iwd is its Wi-Fi daemon)."
case hasIwd && hasNetworkd:
res.Backend = BackendNetworkd
res.ChosenReason = "iwd + systemd-networkd detected. Using iwd for Wi-Fi association and networkd for IP/DHCP."
case hasIwd:
res.Backend = BackendIwd
res.ChosenReason = "iwd detected without NM/ConnMan. Using iwd API."
case hasNetworkd:
res.Backend = BackendNetworkd
res.ChosenReason = "systemd-networkd detected (no NM/ConnMan). Using networkd for L3 and wired."
case wpaSupplicantCtrlDirPresent():
res.Backend = BackendWpaSupplicant
res.HasWpaSupp = true
res.ChosenReason = "No NM/ConnMan/iwd/networkd; wpa_supplicant control directory present. Using wpa_ctrl interface."
case runtime.GOOS == "freebsd":
res.Backend = BackendWpaSupplicant
res.ChosenReason = "FreeBSD detected without wpa_supplicant. Using native Ethernet support."
default:
res.Backend = BackendNone
if hasWpa {
res.ChosenReason = "No NM/ConnMan/iwd; wpa_supplicant D-Bus name present but control directory missing."
} else {
res.ChosenReason = "No known network manager bus names found."
}
}
return res, nil
}