@@ -20,9 +20,6 @@ package commands
2020import (
2121 "encoding/json"
2222 "fmt"
23- "io"
24- "os/exec"
25- "strings"
2623 "sync"
2724 "time"
2825
@@ -36,6 +33,7 @@ import (
3633)
3734
3835var (
36+ mutex = sync.Mutex {}
3937 sdVersion = semver .ParseRelaxed ("1.0.0" )
4038 flavors = []* cores.Flavor {
4139 {
@@ -101,16 +99,6 @@ var (
10199 }
102100)
103101
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-
114102// BoardPort is a generic port descriptor
115103type BoardPort struct {
116104 Address string `json:"address"`
@@ -126,100 +114,86 @@ type eventJSON struct {
126114 Ports []* BoardPort `json:"ports"`
127115}
128116
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
131125 t , err := getBuiltinSerialDiscoveryTool (pm )
132126 if err != nil {
133127 return nil , err
134128 }
135129
130+ // determine if it's installed
136131 if ! t .IsInstalled () {
137132 return nil , fmt .Errorf ("missing serial-discovery tool" )
138133 }
139134
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 )
145138 if err != nil {
146139 return nil , errors .Wrap (err , "creating discovery process" )
147140 }
148141
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 )
168146 }
169147
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 )
172151 }
152+ outJSON := json .NewDecoder (out )
173153
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 )
186157 }
187158
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 {
189161 return nil , fmt .Errorf ("sending LIST command to discovery: %s" , err )
190162 }
163+
164+ // read the response from the pipe
165+ decodeResult := make (chan error )
191166 var event eventJSON
192- done := make (chan bool )
193- timeout := false
194167 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 )
201169 }()
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
205181 }
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" )
207184 }
208- done <- true
209- return event .Ports , d .close ()
210- }
211185
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 ()
219193 })
220- err := d . cmd .Wait ()
221- _ = timer . Stop ()
222- return err
194+ cmd .Wait ()
195+
196+ return retVal , finalError
223197}
224198
225199func getBuiltinSerialDiscoveryTool (pm * packagemanager.PackageManager ) (* cores.ToolRelease , error ) {
0 commit comments