Merge "[docs] Add overview and compilation info."
diff --git a/cmd/zedmon/zedmon.go b/cmd/zedmon/zedmon.go
new file mode 100644
index 0000000..cd20015
--- /dev/null
+++ b/cmd/zedmon/zedmon.go
@@ -0,0 +1,92 @@
+// Copyright 2017 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/csv"
+	"fmt"
+	"os"
+	"os/signal"
+	"strconv"
+
+	"fuchsia.googlesource.com/zedmon"
+)
+
+func main() {
+	zedmon, err := zedmon.OpenZedmon()
+	if err != nil {
+		panic(fmt.Sprintf("Can't open zendmon: %v", err))
+	}
+	defer zedmon.Close()
+
+	f, err := os.OpenFile("zedmon.csv", os.O_CREATE|os.O_RDWR, 0666)
+	if err != nil {
+		panic(fmt.Sprintf("Can't open zedmon.csv: %v", err))
+	}
+	defer f.Close()
+
+	offset, delta, err := zedmon.GetTimeOffset()
+	if err != nil {
+		panic(fmt.Sprintf("Get time offset: %v", err))
+	}
+	fmt.Printf("Time offset: %v ± %v\n", offset, delta)
+
+	termChan := make(chan os.Signal, 1)
+	signal.Notify(termChan, os.Interrupt)
+
+	writer := csv.NewWriter(f)
+	defer writer.Flush()
+
+	fmt.Printf("Starting report recording. Send ^C to stop.\n")
+	zedmon.EnableReporting()
+
+RecordSampling:
+	for {
+		reports, err := zedmon.ReadReports()
+		if err != nil {
+			fmt.Printf("Error reading reports: %v\n", err)
+			continue
+		}
+		for _, report := range reports {
+			record := make([]string, 0, len(report.Values))
+			record = append(record, strconv.FormatUint(report.Timestamp, 10))
+			for _, value := range report.Values {
+				record = append(record, strconv.FormatFloat(value, 'g', -1, 64))
+			}
+			writer.Write(record)
+		}
+
+		select {
+		case <-termChan:
+			break RecordSampling
+		default:
+		}
+	}
+	fmt.Printf("Stopping report recording.\n")
+}
diff --git a/lib/data_type.go b/lib/data_type.go
new file mode 100644
index 0000000..c7b3e45
--- /dev/null
+++ b/lib/data_type.go
@@ -0,0 +1,89 @@
+package lib
+
+import (
+	"encoding/binary"
+	"fmt"
+	"io"
+)
+
+type DataType uint
+
+const (
+	DATA_TYPE_UINT8   DataType = 0x00
+	DATA_TYPE_UINT16           = 0x01
+	DATA_TYPE_UINT32           = 0x02
+	DATA_TYPE_UINT64           = 0x03
+	DATA_TYPE_INT8             = 0x10
+	DATA_TYPE_INT16            = 0x11
+	DATA_TYPE_INT32            = 0x12
+	DATA_TYPE_INT64            = 0x13
+	DATA_TYPE_FLOAT32          = 0x40
+)
+
+func (dt DataType) Size() int {
+	switch dt {
+	case DATA_TYPE_UINT8:
+		return 1
+	case DATA_TYPE_UINT16:
+		return 2
+	case DATA_TYPE_UINT32:
+		return 4
+	case DATA_TYPE_UINT64:
+		return 8
+	case DATA_TYPE_INT8:
+		return 1
+	case DATA_TYPE_INT16:
+		return 2
+	case DATA_TYPE_INT32:
+		return 4
+	case DATA_TYPE_INT64:
+		return 8
+	case DATA_TYPE_FLOAT32:
+		return 4
+	default:
+		return -1
+	}
+}
+
+func (dt DataType) Read(r io.Reader) (float64, error) {
+	switch dt {
+	case DATA_TYPE_UINT8:
+		var val uint8
+		err := binary.Read(r, binary.LittleEndian, &val)
+		return float64(val), err
+	case DATA_TYPE_UINT16:
+		var val uint16
+		err := binary.Read(r, binary.LittleEndian, &val)
+		return float64(val), err
+	case DATA_TYPE_UINT32:
+		var val uint32
+		err := binary.Read(r, binary.LittleEndian, &val)
+		return float64(val), err
+	case DATA_TYPE_UINT64:
+		var val uint64
+		err := binary.Read(r, binary.LittleEndian, &val)
+		return float64(val), err
+	case DATA_TYPE_INT8:
+		var val int8
+		err := binary.Read(r, binary.LittleEndian, &val)
+		return float64(val), err
+	case DATA_TYPE_INT16:
+		var val int16
+		err := binary.Read(r, binary.LittleEndian, &val)
+		return float64(val), err
+	case DATA_TYPE_INT32:
+		var val int32
+		err := binary.Read(r, binary.LittleEndian, &val)
+		return float64(val), err
+	case DATA_TYPE_INT64:
+		var val int64
+		err := binary.Read(r, binary.LittleEndian, &val)
+		return float64(val), err
+	case DATA_TYPE_FLOAT32:
+		var val float32
+		err := binary.Read(r, binary.LittleEndian, &val)
+		return float64(val), err
+	default:
+		return 0.0, fmt.Errorf("Can't decode type %d.", dt)
+	}
+}
diff --git a/lib/field.go b/lib/field.go
new file mode 100644
index 0000000..1c24880
--- /dev/null
+++ b/lib/field.go
@@ -0,0 +1,56 @@
+// Copyright 2017 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 lib
+
+import (
+	"io"
+)
+
+type Unit uint
+
+const (
+	UNIT_AMPHERE Unit = 0
+	UNIT_VOLT         = 1
+)
+
+type Field struct {
+	Name   string
+	Offset int
+	Type   DataType
+	Unit   Unit
+	Scale  float32
+}
+
+func (f *Field) Decode(r io.Reader) (float64, error) {
+	val, err := f.Type.Read(r)
+	if err != nil {
+		return 0.0, err
+	}
+	return val * float64(f.Scale), nil
+}
diff --git a/lib/proto.go b/lib/proto.go
new file mode 100644
index 0000000..6094291
--- /dev/null
+++ b/lib/proto.go
@@ -0,0 +1,50 @@
+// Copyright 2017 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 lib
+
+type PacketType uint8
+
+const (
+	PACKET_TYPE_QUERY_REPORT_FORMAT PacketType = 0x00
+	PACKET_TYPE_QUERY_TIME                     = 0x01
+	PACKET_TYPE_ENABLE_REPORTING               = 0x10
+	PACKET_TYPE_DISABLE_REPORTING              = 0x11
+	PACKET_TYPE_REPORT_FORMAT                  = 0x80
+	PACKET_TYPE_REPORT                         = 0x81
+	PACKET_TYPE_TIMESTAMP                      = 0x82
+)
+
+type reportFormatPacket struct {
+	PacketType uint8
+	ValueIndex uint8
+	ValueType  uint8
+	ValueUnit  uint8
+	Scale      float32
+	Name       [56]byte
+}
diff --git a/lib/zedmon.go b/lib/zedmon.go
new file mode 100644
index 0000000..366dfda
--- /dev/null
+++ b/lib/zedmon.go
@@ -0,0 +1,378 @@
+// Copyright 2017 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 lib
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"log"
+	"math"
+	"time"
+
+	"github.com/google/gousb"
+)
+
+type Report struct {
+	Timestamp uint64
+	Values    []float64
+}
+
+type Zedmon struct {
+	ctx    *gousb.Context
+	dev    *gousb.Device
+	config *gousb.Config
+	intf   *gousb.Interface
+
+	inEpNum  int
+	outEpNum int
+
+	inEp  *gousb.InEndpoint
+	outEp *gousb.OutEndpoint
+
+	readStream       *gousb.ReadStream
+	reportingEnabled bool
+
+	fields []*Field
+}
+
+func (z *Zedmon) Close() {
+	if z.reportingEnabled {
+		z.DisableReporting()
+	}
+
+	if z.readStream != nil {
+		z.readStream.Close()
+	}
+
+	if z.intf != nil {
+		z.intf.Close()
+	}
+
+	if z.config != nil {
+		z.config.Close()
+	}
+
+	if z.dev != nil {
+		z.dev.Close()
+	}
+
+	if z.ctx != nil {
+		z.ctx.Close()
+	}
+}
+
+func (z *Zedmon) read() []byte {
+	buf := make([]byte, z.inEp.Desc.MaxPacketSize)
+	len, err := z.readStream.Read(buf)
+	if err != nil {
+		log.Printf("Read stream error: %v", err)
+		return nil
+	}
+	return buf[:len]
+}
+
+// Synchronize with the device.
+//
+// It is possible for out endpoint data toggles to get out of phase on on
+// successive invocations.  Repeating a get format report command until we
+// get a response synchronizes them.
+func (z *Zedmon) sync() {
+	z.inEp.Timeout = time.Millisecond * 100
+	for {
+		data := make([]byte, 2)
+		data[0] = 0x00
+		data[1] = 0x00
+		_, err := z.outEp.Write(data)
+		if err != nil {
+			log.Printf("Sync Send Error: %v\n", err)
+			continue
+		}
+		buf := make([]byte, z.inEp.Desc.MaxPacketSize)
+		_, err = z.inEp.Read(buf)
+		if err == nil {
+			break
+		}
+		if usbErr, ok := err.(gousb.TransferStatus); ok && usbErr == gousb.TransferTimedOut {
+			continue
+		}
+		log.Printf("Sync Read Error: %v\n", err)
+	}
+}
+
+func (z *Zedmon) GetTimeOffset() (time.Duration, time.Duration, error) {
+	bestRoundTripDuration := time.Duration(math.MaxInt64)
+	bestOffset := time.Duration(0)
+
+	for i := 0; i < 10; i++ {
+		data := make([]byte, 1)
+		data[0] = 0x01
+
+		start := time.Now()
+		_, err := z.outEp.Write(data)
+		if err != nil {
+			log.Printf("Sync Send Error: %v\n", err)
+			return 0, 0, err
+		}
+		buf := z.read()
+		if buf == nil {
+			return 0, 0, fmt.Errorf("Can't read packet\n")
+		}
+		end := time.Now()
+		reader := bytes.NewReader(buf[1:])
+		var rawTimestamp uint64
+		err = binary.Read(reader, binary.LittleEndian, &rawTimestamp)
+		timestamp := time.Unix(int64(rawTimestamp/1000000), int64((rawTimestamp%1000000)*1000))
+
+		delta := end.Sub(start)
+		median := start.Add(delta / 2)
+		offset := median.Sub(timestamp)
+
+		if delta < bestRoundTripDuration {
+			bestRoundTripDuration = delta
+			bestOffset = offset
+		}
+	}
+
+	return bestOffset, bestRoundTripDuration, nil
+}
+
+func (z *Zedmon) EnableReporting() error {
+	data := make([]byte, 1)
+	data[0] = PACKET_TYPE_ENABLE_REPORTING
+	_, err := z.outEp.Write(data)
+	if err != nil {
+		return err
+	}
+
+	z.reportingEnabled = true
+
+	return nil
+}
+
+func (z *Zedmon) DisableReporting() error {
+	data := make([]byte, 1)
+	data[0] = PACKET_TYPE_DISABLE_REPORTING
+	_, err := z.outEp.Write(data)
+	if err != nil {
+		return err
+	}
+
+	// Give time for the packet to be sent.  This could be avoided by adding
+	// ACKs to the protocol.
+	time.Sleep(time.Millisecond * 100)
+
+	z.reportingEnabled = false
+	return nil
+}
+
+// TODO: Add mechanism for pre-allocating reports.
+func (z *Zedmon) ReadReports() ([]*Report, error) {
+	buf := z.read()
+
+	if buf[0] != PACKET_TYPE_REPORT {
+		return nil, fmt.Errorf("Unexpected packet type: %02x", buf[0])
+	}
+
+	var reports []*Report
+
+	reader := bytes.NewReader(buf[1:])
+	for reader.Len() > 0 {
+		var timestamp uint64
+		err := binary.Read(reader, binary.LittleEndian, &timestamp)
+		if err != nil {
+			return nil, err
+		}
+
+		report := &Report{
+			Timestamp: timestamp,
+			Values:    make([]float64, 0, len(z.fields)),
+		}
+
+		for _, field := range z.fields {
+			val, err := field.Decode(reader)
+			if err != nil {
+				return nil, err
+			}
+			report.Values = append(report.Values, val)
+		}
+
+		reports = append(reports, report)
+	}
+
+	return reports, nil
+}
+
+// Returns: offset after this field, error
+func (z *Zedmon) getFormatReport(index uint, offset *int) (bool, error) {
+	if index >= 0xff {
+		return false, fmt.Errorf("Index %d out of range.", index)
+	}
+
+	data := make([]byte, 2)
+	data[0] = 0x00
+	data[1] = uint8(index)
+	numBytes, err := z.outEp.Write(data)
+	if err != nil {
+		return false, err
+	}
+	if numBytes != len(data) {
+		return false, fmt.Errorf("Incomplete write %d != %d", numBytes, len(data))
+	}
+
+	response := z.read() //<-z.readChan
+	var packet reportFormatPacket
+	binary.Read(bytes.NewReader(response), binary.LittleEndian, &packet)
+
+	if packet.ValueIndex == 0xff {
+		return true, nil
+	}
+
+	dataType := DataType(packet.ValueType)
+	if dataType.Size() < 0 {
+		return false, fmt.Errorf("Can't handle Value type %d.", dataType)
+	}
+
+	// TODO: validate Unit
+
+	var name string
+	n := bytes.IndexByte(packet.Name[:], 0x00)
+	if n != -1 {
+		name = string(packet.Name[:n])
+	} else {
+		name = string(packet.Name[:])
+	}
+
+	field := &Field{
+		Offset: *offset,
+		Name:   name,
+		Type:   dataType,
+		Unit:   Unit(packet.ValueUnit),
+		Scale:  packet.Scale,
+	}
+
+	z.fields = append(z.fields, field)
+	*offset += dataType.Size()
+
+	return false, nil
+}
+
+func findZedmonInterface(dev *gousb.Device) (config int, intf int, setting int, err error) {
+	for cfgNum, cfgDesc := range dev.Desc.Configs {
+		for intfNum, intfDesc := range cfgDesc.Interfaces {
+			for settingNum, settingDesc := range intfDesc.AltSettings {
+				if settingDesc.Class == gousb.ClassVendorSpec &&
+					settingDesc.SubClass == gousb.ClassVendorSpec &&
+					settingDesc.Protocol == 0x0 &&
+					len(settingDesc.Endpoints) == 2 {
+					return cfgNum, intfNum, settingNum, nil
+				}
+			}
+		}
+	}
+	return 0, 0, 0, fmt.Errorf("Can't find zedmon interface.")
+}
+
+func (z *Zedmon) enumerateFields() error {
+	offset := 0
+	for i := uint(0); ; i++ {
+		done, err := z.getFormatReport(i, &offset)
+		if err != nil {
+			return err
+		}
+		if done {
+			return nil
+		}
+	}
+}
+
+func OpenZedmon() (*Zedmon, error) {
+	zedmon := &Zedmon{
+		ctx: gousb.NewContext(),
+	}
+
+	dev, err := zedmon.ctx.OpenDeviceWithVIDPID(0x18d1, 0xaf00)
+	if err != nil {
+		zedmon.Close()
+		return nil, err
+	}
+
+	configNum, intfNum, settingNum, err := findZedmonInterface(dev)
+	if err != nil {
+		zedmon.Close()
+		return nil, err
+	}
+
+	zedmon.config, err = dev.Config(configNum)
+	if err != nil {
+		zedmon.Close()
+		return nil, err
+	}
+
+	zedmon.intf, err = zedmon.config.Interface(intfNum, settingNum)
+	if err != nil {
+		zedmon.Close()
+		return nil, err
+	}
+
+	// TODO: We should verify this will succeed in findZedmonInterface().
+	for _, epDesc := range zedmon.intf.Setting.Endpoints {
+		switch epDesc.Direction {
+		case gousb.EndpointDirectionIn:
+			zedmon.inEpNum = epDesc.Number
+		case gousb.EndpointDirectionOut:
+			zedmon.outEpNum = epDesc.Number
+		}
+	}
+
+	zedmon.inEp, err = zedmon.intf.InEndpoint(zedmon.inEpNum)
+	if err != nil {
+		zedmon.Close()
+		return nil, err
+	}
+
+	zedmon.outEp, err = zedmon.intf.OutEndpoint(zedmon.outEpNum)
+	if err != nil {
+		zedmon.Close()
+		return nil, err
+	}
+
+	zedmon.sync()
+
+	zedmon.inEp.Timeout = time.Second * 1
+	zedmon.readStream, err = zedmon.inEp.NewStream(zedmon.inEp.Desc.MaxPacketSize, 100)
+	if err != nil {
+		zedmon.Close()
+		return nil, err
+	}
+
+	zedmon.enumerateFields()
+
+	return zedmon, nil
+}
diff --git a/stub.go b/stub.go
new file mode 100644
index 0000000..2171b1f
--- /dev/null
+++ b/stub.go
@@ -0,0 +1,39 @@
+// Copyright 2017 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 zedmon
+
+import (
+	"fuchsia.googlesource.com/zedmon/lib"
+)
+
+type Zedmon = lib.Zedmon
+
+func OpenZedmon() (*Zedmon, error) {
+	return lib.OpenZedmon()
+}