Skip to content

Commit d8474a7

Browse files
authored
Merge pull request #34 from arduino/fix_unix_sync
Fixed LIBUSB_ERROR_ACCESS on Linux
2 parents 824e16d + 510ed92 commit d8474a7

File tree

2 files changed

+46
-36
lines changed

2 files changed

+46
-36
lines changed

main.go

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ int libusbHandleEvents();
3939
import "C"
4040

4141
import (
42+
"context"
4243
"errors"
4344
"fmt"
4445
"os"
46+
"time"
4547

4648
"github.com/arduino/go-properties-orderedmap"
4749
discovery "github.com/arduino/pluggable-discovery-protocol-handler/v2"
@@ -96,27 +98,62 @@ func (d *DFUDiscovery) libusbSync(eventCB discovery.EventCallback, errorCB disco
9698
return errors.New(C.GoString(err))
9799
}
98100

99-
closeChan := make(chan struct{})
101+
ctx, cancel := context.WithCancel(context.Background())
102+
eventChan := d.runUpdateSender(ctx, eventCB, errorCB)
103+
100104
go func() {
101-
d.sendUpdates(eventCB, errorCB)
102105
for {
103106
if C.libusbHandleEvents() != 0 {
104-
d.sendUpdates(eventCB, errorCB)
107+
select {
108+
case eventChan <- true:
109+
default:
110+
}
105111
}
106112
select {
107-
case <-closeChan:
113+
case <-ctx.Done():
108114
C.libusbHotplugDeregisterCallback()
109115
return
110116
default:
111117
}
112118
}
113119
}()
114-
d.close = func() {
115-
close(closeChan)
116-
}
120+
d.close = cancel
117121
return nil
118122
}
119123

124+
func (d *DFUDiscovery) runUpdateSender(ctx context.Context, eventCB discovery.EventCallback, errorCB discovery.ErrorCallback) chan<- bool {
125+
deviceEventChan := make(chan bool)
126+
go func() {
127+
d.sendUpdates(eventCB, errorCB)
128+
129+
for {
130+
select {
131+
case <-ctx.Done():
132+
return
133+
case <-deviceEventChan:
134+
}
135+
136+
again:
137+
d.sendUpdates(eventCB, errorCB)
138+
139+
// Trigger another update after 500ms because the PLUG-IN signal may come
140+
// way earlier before the port becomes actually READY.
141+
// We experienced problems like:
142+
// - the port not yet visibile
143+
// - the port not accessible (because permissions haven't been set yet)
144+
select {
145+
case <-ctx.Done():
146+
return
147+
case <-deviceEventChan:
148+
goto again
149+
case <-time.After(time.Millisecond * 500):
150+
}
151+
d.sendUpdates(eventCB, errorCB)
152+
}
153+
}()
154+
return deviceEventChan
155+
}
156+
120157
func (d *DFUDiscovery) sendUpdates(eventCB discovery.EventCallback, errorCB discovery.ErrorCallback) {
121158
C.dfuProbeDevices()
122159

sync_windows.go

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,14 @@ package main
1919

2020
import (
2121
"context"
22-
"time"
2322

2423
"github.com/arduino/go-win32-utils/devicenotification"
2524
discovery "github.com/arduino/pluggable-discovery-protocol-handler/v2"
2625
)
2726

2827
func (d *DFUDiscovery) sync(eventCB discovery.EventCallback, errorCB discovery.ErrorCallback) error {
2928
ctx, cancel := context.WithCancel(context.Background())
30-
d.close = cancel
31-
32-
deviceEventChan := make(chan bool, 1)
29+
deviceEventChan := d.runUpdateSender(ctx, eventCB, errorCB)
3330
go func() {
3431
err := devicenotification.Start(ctx, func() {
3532
select {
@@ -42,30 +39,6 @@ func (d *DFUDiscovery) sync(eventCB discovery.EventCallback, errorCB discovery.E
4239
}
4340
}()
4441

45-
go func() {
46-
d.sendUpdates(eventCB, errorCB)
47-
48-
for {
49-
select {
50-
case <-ctx.Done():
51-
return
52-
case <-deviceEventChan:
53-
}
54-
55-
again:
56-
d.sendUpdates(eventCB, errorCB)
57-
58-
// Trigger another update after 500ms because Windows might signal a
59-
// new port much before it becomes actually available.
60-
select {
61-
case <-ctx.Done():
62-
return
63-
case <-deviceEventChan:
64-
goto again
65-
case <-time.After(time.Millisecond * 500):
66-
}
67-
d.sendUpdates(eventCB, errorCB)
68-
}
69-
}()
42+
d.close = cancel
7043
return nil
7144
}

0 commit comments

Comments
 (0)