mirror of
https://github.com/anotherhadi/settuings.git
synced 2026-10-05 08:18:23 +02:00
84 lines
2.6 KiB
Go
84 lines
2.6 KiB
Go
package bluetooth
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/godbus/dbus/v5"
|
|
)
|
|
|
|
const (
|
|
agentPath = dbus.ObjectPath("/org/anotherhadi/settuings/agent")
|
|
agentCapability = "DisplayYesNo"
|
|
)
|
|
|
|
// agent implements the BlueZ org.bluez.Agent1 interface, auto-accepting
|
|
// every pairing prompt. `bluetoothctl pair` run non-interactively never
|
|
// registers an agent, so BlueZ has nobody to ask for PIN/passkey
|
|
// confirmation and any device that isn't "Just Works" fails with
|
|
// AuthenticationFailed. Registering this agent as the system default
|
|
// fixes that even though pairing itself still happens in a separate
|
|
// bluetoothctl process: BlueZ routes auth requests to whichever agent is
|
|
// registered as default, not to whoever initiated the pairing.
|
|
type agent struct{}
|
|
|
|
func (agent) Release() *dbus.Error { return nil }
|
|
|
|
func (agent) RequestPinCode(_ dbus.ObjectPath) (string, *dbus.Error) {
|
|
return "", dbus.NewError("org.bluez.Error.Rejected", nil)
|
|
}
|
|
|
|
func (agent) DisplayPinCode(_ dbus.ObjectPath, _ string) *dbus.Error { return nil }
|
|
|
|
func (agent) RequestPasskey(_ dbus.ObjectPath) (uint32, *dbus.Error) {
|
|
return 0, dbus.NewError("org.bluez.Error.Rejected", nil)
|
|
}
|
|
|
|
func (agent) DisplayPasskey(_ dbus.ObjectPath, _ uint32, _ uint16) *dbus.Error { return nil }
|
|
|
|
func (agent) RequestConfirmation(_ dbus.ObjectPath, _ uint32) *dbus.Error { return nil }
|
|
|
|
func (agent) RequestAuthorization(_ dbus.ObjectPath) *dbus.Error { return nil }
|
|
|
|
func (agent) AuthorizeService(_ dbus.ObjectPath, _ string) *dbus.Error { return nil }
|
|
|
|
func (agent) Cancel() *dbus.Error { return nil }
|
|
|
|
var (
|
|
agentOnce sync.Once
|
|
agentErr error
|
|
// agentConn is kept alive for the process lifetime: BlueZ calls back
|
|
// into our agent over this connection while pairing is in progress.
|
|
agentConn *dbus.Conn
|
|
)
|
|
|
|
// ensureAgent registers this process as BlueZ's default pairing agent, once
|
|
// per run. Call before any Pair.
|
|
func ensureAgent() error {
|
|
agentOnce.Do(func() {
|
|
conn, err := dbus.ConnectSystemBus()
|
|
if err != nil {
|
|
agentErr = fmt.Errorf("connect to system bus: %w", err)
|
|
return
|
|
}
|
|
|
|
if err := conn.Export(agent{}, agentPath, "org.bluez.Agent1"); err != nil {
|
|
agentErr = fmt.Errorf("export agent: %w", err)
|
|
return
|
|
}
|
|
|
|
manager := conn.Object("org.bluez", dbus.ObjectPath("/org/bluez"))
|
|
if call := manager.Call("org.bluez.AgentManager1.RegisterAgent", 0, agentPath, agentCapability); call.Err != nil {
|
|
agentErr = fmt.Errorf("register agent: %w", call.Err)
|
|
return
|
|
}
|
|
if call := manager.Call("org.bluez.AgentManager1.RequestDefaultAgent", 0, agentPath); call.Err != nil {
|
|
agentErr = fmt.Errorf("request default agent: %w", call.Err)
|
|
return
|
|
}
|
|
|
|
agentConn = conn
|
|
})
|
|
return agentErr
|
|
}
|