@@ -13,13 +13,16 @@ char *get_path(libusb_device *dev);
13
13
// Defined in main.c
14
14
const char *libusbOpen();
15
15
void libusbClose();
16
+ void dfuProbeDevices();
16
17
*/
17
18
import "C"
18
19
19
20
import (
20
21
"fmt"
21
22
"os"
23
+ "time"
22
24
25
+ "github.com/arduino/go-properties-orderedmap"
23
26
discovery "github.com/arduino/pluggable-discovery-protocol-handler/v2"
24
27
)
25
28
@@ -34,6 +37,7 @@ func main() {
34
37
35
38
// DFUDiscovery is the implementation of the DFU pluggable-discovery
36
39
type DFUDiscovery struct {
40
+ closeChan chan <- struct {}
37
41
}
38
42
39
43
// Hello is the handler for the pluggable-discovery HELLO command
@@ -43,10 +47,15 @@ func (d *DFUDiscovery) Hello(userAgent string, protocolVersion int) error {
43
47
44
48
// Quit is the handler for the pluggable-discovery QUIT command
45
49
func (d * DFUDiscovery ) Quit () {
50
+ d .Stop ()
46
51
}
47
52
48
53
// Stop is the handler for the pluggable-discovery STOP command
49
54
func (d * DFUDiscovery ) Stop () error {
55
+ if d .closeChan != nil {
56
+ close (d .closeChan )
57
+ d .closeChan = nil
58
+ }
50
59
C .libusbClose ()
51
60
return nil
52
61
}
@@ -56,9 +65,86 @@ func (d *DFUDiscovery) StartSync(eventCB discovery.EventCallback, errorCB discov
56
65
if cErr := C .libusbOpen (); cErr != nil {
57
66
return fmt .Errorf ("can't open libusb: %s" , C .GoString (cErr ))
58
67
}
68
+ closeChan := make (chan struct {})
69
+ go func () {
70
+ for {
71
+ d .sendUpdates (eventCB , errorCB )
72
+ select {
73
+ case <- time .After (5 * time .Second ):
74
+ case <- closeChan :
75
+ return
76
+ }
77
+ }
78
+ }()
79
+ d .closeChan = closeChan
59
80
return nil
60
81
}
61
82
83
+ func (d * DFUDiscovery ) sendUpdates (eventCB discovery.EventCallback , errorCB discovery.ErrorCallback ) {
84
+ C .dfuProbeDevices ()
85
+ for _ , dfuIf := range d .getDFUInterfaces () {
86
+ eventCB ("add" , dfuIf .AsDiscoveryPort ())
87
+ }
88
+ }
89
+
62
90
func getPath (dev * C.struct_libusb_device ) string {
63
91
return C .GoString (C .get_path (dev ))
64
92
}
93
+
94
+ // DFUInterface represents a DFU Interface
95
+ type DFUInterface struct {
96
+ Path string
97
+ AltName string
98
+ VID , PID uint16
99
+ SerialNumber string
100
+ Flags uint32
101
+ }
102
+
103
+ // AsDiscoveryPort converts this DFUInterface into a discovery.Port
104
+ func (i * DFUInterface ) AsDiscoveryPort () * discovery.Port {
105
+ props := properties .NewMap ()
106
+ props .Set ("vid" , fmt .Sprintf ("%04X" , i .VID ))
107
+ props .Set ("pid" , fmt .Sprintf ("%04X" , i .PID ))
108
+ if i .SerialNumber != "" {
109
+ props .Set ("serial" , i .SerialNumber )
110
+ }
111
+ // ProtocolLabel: pdfu.flags & DFU_IFF_DFU ? "DFU" : "Runtime"
112
+ return & discovery.Port {
113
+ Address : i .Path ,
114
+ AddressLabel : i .Path ,
115
+ Protocol : "dfu" ,
116
+ ProtocolLabel : "USB DFU" ,
117
+ Properties : props ,
118
+ HardwareID : props .Get ("serial" ),
119
+ }
120
+ }
121
+
122
+ func (d * DFUDiscovery ) getDFUInterfaces () []* DFUInterface {
123
+ res := []* DFUInterface {}
124
+ for pdfu := C .dfu_root ; pdfu != nil ; pdfu = pdfu .next {
125
+ fmt .Println (pdfu )
126
+ if (pdfu .flags & C .DFU_IFF_DFU ) == 0 {
127
+ // decide what to do with DFU runtime objects
128
+ // for the time being, ignore them
129
+ continue
130
+ }
131
+ ifPath := getPath (pdfu .dev )
132
+ // for i := 0; i < index; i++ {
133
+ // // allow only one object
134
+ // if j["ports"][i]["address"] == ifPath {
135
+ // index = i
136
+ // break
137
+ // }
138
+ // }
139
+
140
+ dfuIf := & DFUInterface {
141
+ Path : ifPath ,
142
+ AltName : C .GoString (pdfu .alt_name ),
143
+ VID : uint16 (pdfu .vendor ),
144
+ PID : uint16 (pdfu .product ),
145
+ SerialNumber : C .GoString (pdfu .serial_name ),
146
+ }
147
+ res = append (res , dfuIf )
148
+ }
149
+ return res
150
+ }
0 commit comments