Skip to content

Commit 6fe20d3

Browse files
committed
Fixed LIBUSB_ERROR_ACCESS on Linux
1 parent 824e16d commit 6fe20d3

File tree

1 file changed

+44
-7
lines changed

1 file changed

+44
-7
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

0 commit comments

Comments
 (0)