@@ -20,9 +20,6 @@ package commands
20
20
import (
21
21
"encoding/json"
22
22
"fmt"
23
- "io"
24
- "os/exec"
25
- "strings"
26
23
"sync"
27
24
"time"
28
25
@@ -36,6 +33,7 @@ import (
36
33
)
37
34
38
35
var (
36
+ mutex = sync.Mutex {}
39
37
sdVersion = semver .ParseRelaxed ("1.0.0" )
40
38
flavors = []* cores.Flavor {
41
39
{
@@ -101,16 +99,6 @@ var (
101
99
}
102
100
)
103
101
104
- // SerialDiscovery is an instance of a discovery tool
105
- type SerialDiscovery struct {
106
- sync.Mutex
107
- ID string
108
- in io.WriteCloser
109
- out io.ReadCloser
110
- outJSON * json.Decoder
111
- cmd * exec.Cmd
112
- }
113
-
114
102
// BoardPort is a generic port descriptor
115
103
type BoardPort struct {
116
104
Address string `json:"address"`
@@ -126,100 +114,86 @@ type eventJSON struct {
126
114
Ports []* BoardPort `json:"ports"`
127
115
}
128
116
129
- // NewBuiltinSerialDiscovery returns a wrapper to control the serial-discovery program
130
- func NewBuiltinSerialDiscovery (pm * packagemanager.PackageManager ) (* SerialDiscovery , error ) {
117
+ // ListBoards foo
118
+ func ListBoards (pm * packagemanager.PackageManager ) ([]* BoardPort , error ) {
119
+ // ensure the connection to the discoverer is unique to avoid messing up
120
+ // the messages exchanged
121
+ mutex .Lock ()
122
+ defer mutex .Unlock ()
123
+
124
+ // get the bundled tool
131
125
t , err := getBuiltinSerialDiscoveryTool (pm )
132
126
if err != nil {
133
127
return nil , err
134
128
}
135
129
130
+ // determine if it's installed
136
131
if ! t .IsInstalled () {
137
132
return nil , fmt .Errorf ("missing serial-discovery tool" )
138
133
}
139
134
140
- cmdArgs := []string {
141
- t .InstallDir .Join ("serial-discovery" ).String (),
142
- }
143
-
144
- cmd , err := executils .Command (cmdArgs )
135
+ // build the command to be executed
136
+ args := []string {t .InstallDir .Join ("serial-discovery" ).String ()}
137
+ cmd , err := executils .Command (args )
145
138
if err != nil {
146
139
return nil , errors .Wrap (err , "creating discovery process" )
147
140
}
148
141
149
- return & SerialDiscovery {
150
- ID : strings .Join (cmdArgs , " " ),
151
- cmd : cmd ,
152
- }, nil
153
- }
154
-
155
- // Start starts the specified discovery
156
- func (d * SerialDiscovery ) start () error {
157
- if in , err := d .cmd .StdinPipe (); err == nil {
158
- d .in = in
159
- } else {
160
- return fmt .Errorf ("creating stdin pipe for discovery: %s" , err )
161
- }
162
-
163
- if out , err := d .cmd .StdoutPipe (); err == nil {
164
- d .out = out
165
- d .outJSON = json .NewDecoder (d .out )
166
- } else {
167
- return fmt .Errorf ("creating stdout pipe for discovery: %s" , err )
142
+ // attach in/out pipes to the process
143
+ in , err := cmd .StdinPipe ()
144
+ if err != nil {
145
+ return nil , fmt .Errorf ("creating stdin pipe for discovery: %s" , err )
168
146
}
169
147
170
- if err := d .cmd .Start (); err != nil {
171
- return fmt .Errorf ("starting discovery process: %s" , err )
148
+ out , err := cmd .StdoutPipe ()
149
+ if err != nil {
150
+ return nil , fmt .Errorf ("creating stdout pipe for discovery: %s" , err )
172
151
}
152
+ outJSON := json .NewDecoder (out )
173
153
174
- return nil
175
- }
176
-
177
- // List retrieve the port list from this discovery
178
- func (d * SerialDiscovery ) List () ([]* BoardPort , error ) {
179
- // ensure the connection to the discoverer is unique to avoid messing up
180
- // the messages exchanged
181
- d .Lock ()
182
- defer d .Unlock ()
183
-
184
- if err := d .start (); err != nil {
185
- return nil , fmt .Errorf ("discovery hasn't started: %v" , err )
154
+ // start the process
155
+ if err := cmd .Start (); err != nil {
156
+ return nil , fmt .Errorf ("starting discovery process: %s" , err )
186
157
}
187
158
188
- if _ , err := d .in .Write ([]byte ("LIST\n " )); err != nil {
159
+ // send the LIST command
160
+ if _ , err := in .Write ([]byte ("LIST\n " )); err != nil {
189
161
return nil , fmt .Errorf ("sending LIST command to discovery: %s" , err )
190
162
}
163
+
164
+ // read the response from the pipe
165
+ decodeResult := make (chan error )
191
166
var event eventJSON
192
- done := make (chan bool )
193
- timeout := false
194
167
go func () {
195
- select {
196
- case <- done :
197
- case <- time .After (10 * time .Second ):
198
- timeout = true
199
- d .close ()
200
- }
168
+ decodeResult <- outJSON .Decode (& event )
201
169
}()
202
- if err := d .outJSON .Decode (& event ); err != nil {
203
- if timeout {
204
- return nil , fmt .Errorf ("decoding LIST command: timeout" )
170
+
171
+ var finalError error
172
+ var retVal []* BoardPort
173
+
174
+ // wait for the response
175
+ select {
176
+ case err := <- decodeResult :
177
+ if err == nil {
178
+ retVal = event .Ports
179
+ } else {
180
+ finalError = err
205
181
}
206
- return nil , fmt .Errorf ("decoding LIST command: %s" , err )
182
+ case <- time .After (10 * time .Second ):
183
+ finalError = fmt .Errorf ("decoding LIST command: timeout" )
207
184
}
208
- done <- true
209
- return event .Ports , d .close ()
210
- }
211
185
212
- // Close stops the Discovery and free the resources
213
- func ( d * SerialDiscovery ) close () error {
214
- _ , _ = d . in .Write ([] byte ( "QUIT \n " ) )
215
- _ = d . in .Close ()
216
- _ = d . out . Close ()
217
- timer := time .AfterFunc (time .Second , func () {
218
- _ = d . cmd .Process .Kill ()
186
+ // tell the process to quit
187
+ in . Write ([] byte ( "QUIT \n " ))
188
+ in .Close ( )
189
+ out .Close ()
190
+ // kill the process if it takes too long to quit
191
+ time .AfterFunc (time .Second , func () {
192
+ cmd .Process .Kill ()
219
193
})
220
- err := d . cmd .Wait ()
221
- _ = timer . Stop ()
222
- return err
194
+ cmd .Wait ()
195
+
196
+ return retVal , finalError
223
197
}
224
198
225
199
func getBuiltinSerialDiscoveryTool (pm * packagemanager.PackageManager ) (* cores.ToolRelease , error ) {
0 commit comments