11package bluetooth
22
33import (
4+ "context"
5+ "errors"
46 "fmt"
57 "regexp"
68 "strings"
@@ -14,43 +16,37 @@ import (
1416
1517var macRegex = regexp .MustCompile (`^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$` )
1618
17- // callWithTimeout executes a D-Bus call with timeout
18- func callWithTimeout (call * dbus.Call , timeout time.Duration ) error {
19- done := make (chan error , 1 )
20-
21- go func () {
22- done <- call .Err
23- }()
24-
25- select {
26- case err := <- done :
27- return err
28- case <- time .After (timeout ):
29- return & dbusTimeoutError {}
19+ // call issues a method call bounded by timeout. The deadline has to be on the
20+ // call itself: obj.Call blocks until a reply, so wrapping it afterwards never
21+ // times out.
22+ func call (obj dbus.BusObject , timeout time.Duration , method string , args ... interface {}) * dbus.Call {
23+ ctx , cancel := context .WithTimeout (context .Background (), timeout )
24+ defer cancel ()
25+ c := obj .CallWithContext (ctx , method , 0 , args ... )
26+ if errors .Is (c .Err , context .DeadlineExceeded ) {
27+ c .Err = & dbusTimeoutError {}
3028 }
29+ return c
3130}
3231
33- // callWithTimeout receiver method for BluetoothBackend
34- func (b * BluetoothBackend ) callWithTimeout (call * dbus.Call ) error {
35- return callWithTimeout (call , b .timeout )
32+ func (b * BluetoothBackend ) call (obj dbus.BusObject , method string , args ... interface {}) * dbus.Call {
33+ return call (obj , b .timeout , method , args ... )
3634}
3735
38- // callMethod calls a method on an object with timeout
3936func (b * BluetoothBackend ) callMethod (obj dbus.BusObject , method string , args ... interface {}) error {
40- return b .callWithTimeout (obj . Call ( method , 0 , args ... ))
37+ return b .call (obj , method , args ... ). Err
4138}
4239
4340func (b * BluetoothBackend ) setProperty (obj dbus.BusObject , iface , prop string , value interface {}) error {
44- call := obj .Call (DBUS_PROP_SET , 0 , iface , prop , dbus .MakeVariant (value ))
45- return b .callWithTimeout (call )
41+ return b .call (obj , DBUS_PROP_SET , iface , prop , dbus .MakeVariant (value )).Err
4642}
4743
4844// getProperty retrieves a property from D-Bus for a given busName
4945func (b * BluetoothBackend ) getProperty (obj dbus.BusObject , iface , prop string ) (dbus.Variant , error ) {
5046 var v dbus.Variant
51- call := obj . Call ( DBUS_PROP_GET , 0 , iface , prop )
52- if err := b . callWithTimeout ( call ); err != nil {
53- return dbus.Variant {}, err
47+ call := b . call ( obj , DBUS_PROP_GET , iface , prop )
48+ if call . Err != nil {
49+ return dbus.Variant {}, call . Err
5450 }
5551 if err := call .Store (& v ); err != nil {
5652 return dbus.Variant {}, err
@@ -67,14 +63,7 @@ func (b *BluetoothBackend) adapter() dbus.BusObject {
6763}
6864
6965func (b * BluetoothBackend ) setAdapterProp (prop string , value interface {}) error {
70- call := b .adapter ().Call (
71- DBUS_PROP_SET ,
72- 0 ,
73- BLUETOOTH_ADAPTER ,
74- prop ,
75- dbus .MakeVariant (value ),
76- )
77- return b .callWithTimeout (call )
66+ return b .setProperty (b .adapter (), BLUETOOTH_ADAPTER , prop , value )
7867}
7968
8069func extractBool (v dbus.Variant ) (bool , bool ) {
@@ -255,8 +244,10 @@ func (b *BluetoothBackend) setDiscoveryFilter() error {
255244 return nil
256245}
257246
247+ // connectDevice gets the pairing deadline: a first connect bonds the device
248+ // and takes several seconds, well past the generic call timeout.
258249func (b * BluetoothBackend ) connectDevice (path dbus.ObjectPath ) error {
259- return b . callMethod (b .getObj (BLUETOOTH_PREFIX , string (path )), DEVICE_CONNECT )
250+ return call (b .getObj (BLUETOOTH_PREFIX , string (path )), b . pairingTimeout , DEVICE_CONNECT ). Err
260251}
261252
262253func (b * BluetoothBackend ) disconnectDevice (path dbus.ObjectPath ) error {
@@ -356,7 +347,7 @@ func (b *BluetoothBackend) SetTimeOut(prop string) error {
356347func (b * BluetoothBackend ) getManagedObjects () (map [dbus.ObjectPath ]map [string ]map [string ]dbus.Variant , error ) {
357348 objManager := b .getObj (BLUETOOTH_PREFIX , "/" )
358349 var managedObjects map [dbus.ObjectPath ]map [string ]map [string ]dbus.Variant
359- if err := objManager . Call ( MANAGED_OBJECTS , 0 ).Store (& managedObjects ); err != nil {
350+ if err := b . call ( objManager , MANAGED_OBJECTS ).Store (& managedObjects ); err != nil {
360351 logger .Warn ("[bluetooth] failed to query BlueZ managed objects: %v" , err )
361352 return nil , err
362353 }
0 commit comments