Add support for multiple zedmons on one system.
* Add zedmon list command.
* Add --config=<json config file> to open zedmon by serial number
Change-Id: I7b484b8b6537217defe9177362c61cde7ff2ff46
diff --git a/cmd/zedmon/common.go b/cmd/zedmon/common.go
new file mode 100644
index 0000000..2562aa4
--- /dev/null
+++ b/cmd/zedmon/common.go
@@ -0,0 +1,61 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package main
+
+import (
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "fuchsia.googlesource.com/zedmon"
+)
+
+var configFileName string
+
+func setCommonFlags(flags *flag.FlagSet) {
+ flags.StringVar(&configFileName, "config", "", "Config file.")
+}
+
+func getConfig() zedmon.Config {
+ var config zedmon.Config
+ if configFileName != "" {
+ f, err := os.Open(configFileName)
+ if err != nil {
+ panic(fmt.Sprintf("Can't open %s: %v.", configFileName, err))
+ }
+ b, _ := ioutil.ReadAll(f)
+ err = json.Unmarshal(b, &config)
+ if err != nil {
+ panic(fmt.Sprintf("Can't decode config: %v.", err))
+ }
+ }
+ return config
+}
diff --git a/cmd/zedmon/gpio.go b/cmd/zedmon/gpio.go
index 06cfdc8..fc6ac48 100644
--- a/cmd/zedmon/gpio.go
+++ b/cmd/zedmon/gpio.go
@@ -47,11 +47,12 @@
`
}
-func (*gpioCmd) SetFlags(_ *flag.FlagSet) {
+func (*gpioCmd) SetFlags(flags *flag.FlagSet) {
+ setCommonFlags(flags)
}
func (*gpioCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
- zedmon, err := zedmon.OpenZedmon()
+ zedmon, err := zedmon.OpenZedmon(getConfig())
if err != nil {
fmt.Printf("Can't open zendmon: %v", err)
return subcommands.ExitFailure
diff --git a/cmd/zedmon/list.go b/cmd/zedmon/list.go
new file mode 100644
index 0000000..6187837
--- /dev/null
+++ b/cmd/zedmon/list.go
@@ -0,0 +1,64 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+
+ "fuchsia.googlesource.com/zedmon"
+ "github.com/google/subcommands"
+)
+
+type listCmd struct{}
+
+func (*listCmd) Name() string { return "list" }
+func (*listCmd) Synopsis() string { return "List connected zedmons." }
+func (*listCmd) Usage() string {
+ return `list
+`
+}
+
+func (*listCmd) SetFlags(_ *flag.FlagSet) {
+}
+
+func (*listCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
+ devs, err := zedmon.Enumerate()
+ if err != nil {
+ fmt.Printf("Can't enumerate zendmon: %v", err)
+ return subcommands.ExitFailure
+ }
+
+ for _, dev := range devs {
+ fmt.Printf("%s\n", dev.Serial)
+ }
+
+ return subcommands.ExitSuccess
+}
diff --git a/cmd/zedmon/record.go b/cmd/zedmon/record.go
index 1c71cb6..1053656 100644
--- a/cmd/zedmon/record.go
+++ b/cmd/zedmon/record.go
@@ -50,11 +50,12 @@
`
}
-func (*recordCmd) SetFlags(_ *flag.FlagSet) {
+func (*recordCmd) SetFlags(flags *flag.FlagSet) {
+ setCommonFlags(flags)
}
func (*recordCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
- zedmon, err := zedmon.OpenZedmon()
+ zedmon, err := zedmon.OpenZedmon(getConfig())
if err != nil {
fmt.Printf("Can't open zendmon: %v", err)
return subcommands.ExitFailure
diff --git a/cmd/zedmon/relay.go b/cmd/zedmon/relay.go
index c06c0b7..6133813 100644
--- a/cmd/zedmon/relay.go
+++ b/cmd/zedmon/relay.go
@@ -46,11 +46,12 @@
`
}
-func (*relayCmd) SetFlags(_ *flag.FlagSet) {
+func (*relayCmd) SetFlags(flags *flag.FlagSet) {
+ setCommonFlags(flags)
}
func (*relayCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
- zedmon, err := zedmon.OpenZedmon()
+ zedmon, err := zedmon.OpenZedmon(getConfig())
if err != nil {
fmt.Printf("Can't open zendmon: %v", err)
return subcommands.ExitFailure
diff --git a/cmd/zedmon/zedmon.go b/cmd/zedmon/zedmon.go
index a3d92db..52868e8 100644
--- a/cmd/zedmon/zedmon.go
+++ b/cmd/zedmon/zedmon.go
@@ -41,6 +41,7 @@
subcommands.Register(subcommands.FlagsCommand(), "")
subcommands.Register(subcommands.CommandsCommand(), "")
subcommands.Register(&gpioCmd{}, "")
+ subcommands.Register(&listCmd{}, "")
subcommands.Register(&recordCmd{}, "")
subcommands.Register(&relayCmd{}, "")
diff --git a/lib/zedmon.go b/lib/zedmon.go
index 755aaf0..d520289 100644
--- a/lib/zedmon.go
+++ b/lib/zedmon.go
@@ -32,6 +32,7 @@
"bytes"
"context"
"encoding/binary"
+ "errors"
"fmt"
"log"
"math"
@@ -40,6 +41,14 @@
"github.com/google/gousb"
)
+type Info struct {
+ Serial string
+}
+
+type Config struct {
+ Serial *string `json:"serial"`
+}
+
type Report struct {
Timestamp uint64
Values []float64
@@ -207,7 +216,7 @@
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, &packet)
if err != nil {
- return fmt.Errorf("SetOuput: binary.Write failed:", err)
+ return fmt.Errorf("SetOuput: binary.Write failed: %v", err)
}
_, err = z.outEp.Write(buf.Bytes())
@@ -342,17 +351,70 @@
}
}
-func OpenZedmon() (*Zedmon, error) {
+func Enumerate() ([]Info, error) {
+ ctx := gousb.NewContext()
+ devs, err := ctx.OpenDevices(func(desc *gousb.DeviceDesc) bool {
+ return desc.Vendor == 0x18d1 && desc.Product == 0xaf00
+ })
+ if err != nil {
+ ctx.Close()
+ return nil, err
+ }
+
+ if len(devs) == 0 {
+ return nil, errors.New("No zedmon device found")
+ }
+
+ var infos []Info
+ for _, d := range devs {
+ serial, err := d.SerialNumber()
+ if err != nil {
+ continue
+ }
+ infos = append(infos, Info{Serial: serial})
+ }
+
+ return infos, nil
+}
+
+func OpenZedmon(config Config) (*Zedmon, error) {
zedmon := &Zedmon{
ctx: gousb.NewContext(),
}
- dev, err := zedmon.ctx.OpenDeviceWithVIDPID(0x18d1, 0xaf00)
+ devs, err := zedmon.ctx.OpenDevices(func(desc *gousb.DeviceDesc) bool {
+ return desc.Vendor == 0x18d1 && desc.Product == 0xaf00
+ })
if err != nil {
zedmon.Close()
return nil, err
}
+ if len(devs) == 0 {
+ return nil, errors.New("No zedmon device found")
+ }
+
+ var dev *gousb.Device
+ if config.Serial == nil {
+ dev = devs[0]
+ } else {
+
+ for _, d := range devs {
+ serial, err := d.SerialNumber()
+ if err != nil {
+ continue
+ }
+ if serial == *config.Serial {
+ dev = d
+ break
+ }
+ }
+ if dev == nil {
+ zedmon.Close()
+ return nil, fmt.Errorf("No zedmon device with serial %s found", *config.Serial)
+ }
+ }
+
configNum, intfNum, settingNum, err := findZedmonInterface(dev)
if err != nil {
zedmon.Close()
diff --git a/stub.go b/stub.go
index b5d62a4..f8727e5 100644
--- a/stub.go
+++ b/stub.go
@@ -32,6 +32,13 @@
"fuchsia.googlesource.com/zedmon/lib"
)
-func OpenZedmon() (*lib.Zedmon, error) {
- return lib.OpenZedmon()
+type Config = lib.Config
+type Info = lib.Info
+
+func Enumerate() ([]Info, error) {
+ return lib.Enumerate()
+}
+
+func OpenZedmon(config lib.Config) (*lib.Zedmon, error) {
+ return lib.OpenZedmon(config)
}